From d51b4462ec2d4a7d8d647afcf86353ca4e971b70 Mon Sep 17 00:00:00 2001 From: ardi Date: Fri, 7 Jun 2024 16:25:43 +0200 Subject: Improve conflict marker recovery --- compiler/rustc_parse/src/parser/diagnostics.rs | 51 +++++++++++++++++++------- 1 file changed, 38 insertions(+), 13 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c1aac84bcae..e4630bbceb9 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2990,14 +2990,18 @@ impl<'a> Parser<'a> { } pub(crate) fn err_vcs_conflict_marker(&mut self) -> PResult<'a, ()> { + // <<<<<<< let Some(start) = self.conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) else { return Ok(()); }; let mut spans = Vec::with_capacity(3); spans.push(start); + // ||||||| let mut middlediff3 = None; + // ======= let mut middle = None; + // >>>>>>> let mut end = None; loop { if self.token.kind == TokenKind::Eof { @@ -3018,29 +3022,50 @@ impl<'a> Parser<'a> { } self.bump(); } + let mut err = self.dcx().struct_span_err(spans, "encountered diff marker"); - err.span_label(start, "after this is the code before the merge"); - if let Some(middle) = middlediff3 { - err.span_label(middle, ""); - } + match middlediff3 { + // We're using diff3 + Some(middlediff3) => { + err.span_label( + start, + "between this marker and `|||||||` is the code that we're merging into", + ); + err.span_label(middlediff3, "between this marker and `=======` is the base code (what the two refs diverged from)"); + } + None => { + err.span_label( + start, + "between this marker and `=======` is the code that we're merging into", + ); + } + }; + if let Some(middle) = middle { - err.span_label(middle, ""); + err.span_label(middle, "between this marker and `>>>>>>>` is the incoming code"); } if let Some(end) = end { - err.span_label(end, "above this are the incoming code changes"); + err.span_label(end, "this marker concludes the conflict region"); } - err.help( - "if you're having merge conflicts after pulling new code, the top section is the code \ - you already had and the bottom section is the remote code", + err.note( + "conflict markers indicate that a merge was started but could not be completed due \ + to merge conflicts\n\ + to resolve a conflict, keep only the code you want and then delete the lines \ + containing conflict markers", ); err.help( - "if you're in the middle of a rebase, the top section is the code being rebased onto \ - and the bottom section is the code coming from the current commit being rebased", + "if you're having merge conflicts after pulling new code:\n\ + the top section is the code you already had and the bottom section is the remote code\n\ + if you're in the middle of a rebase:\n\ + the top section is the code being rebased onto and the bottom section is the code \ + coming from the current commit being rebased", ); + err.note( - "for an explanation on these markers from the `git` documentation, visit \ - ", + "for an explanation on these markers from the `git` documentation:\n\ + visit ", ); + Err(err) } -- cgit 1.4.1-3-g733a5 From 9f6371236f516ac2a883eb8707839ab80fc7f9f7 Mon Sep 17 00:00:00 2001 From: ardi Date: Mon, 10 Jun 2024 10:16:51 +0200 Subject: make this comment correct --- compiler/rustc_parse/src/parser/diagnostics.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index e4630bbceb9..db23ce6fb7b 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2958,9 +2958,10 @@ impl<'a> Parser<'a> { /// This checks if this is a conflict marker, depending of the parameter passed. /// - /// * `>>>>>` - /// * `=====` - /// * `<<<<<` + /// * `<<<<<<<` + /// * `|||||||` + /// * `=======` + /// * `>>>>>>>` /// pub(super) fn is_vcs_conflict_marker( &mut self, -- cgit 1.4.1-3-g733a5 From 3e8898a4e1afd44f09a5a80d466cd5b1a87e0fa8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 19 Jun 2024 12:21:09 -0400 Subject: Allow naming expr_2021 in all editions --- compiler/rustc_ast/src/token.rs | 19 ++++++++++++----- compiler/rustc_expand/src/mbe/macro_rules.rs | 4 +++- compiler/rustc_expand/src/mbe/quoted.rs | 3 ++- compiler/rustc_parse/src/parser/nonterminal.rs | 5 ++--- tests/ui/macros/expr_2021_implicit_in_2024.rs | 2 ++ tests/ui/macros/expr_2021_implicit_in_2024.stderr | 10 --------- tests/ui/macros/expr_2021_old_edition.rs | 13 ------------ tests/ui/macros/expr_2021_old_edition.stderr | 26 ----------------------- 8 files changed, 23 insertions(+), 59 deletions(-) delete mode 100644 tests/ui/macros/expr_2021_implicit_in_2024.stderr delete mode 100644 tests/ui/macros/expr_2021_old_edition.rs delete mode 100644 tests/ui/macros/expr_2021_old_edition.stderr (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 109c401bb6a..9c8b2451b79 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -884,7 +884,11 @@ pub enum NonterminalKind { PatWithOr, Expr, /// Matches an expression using the rules from edition 2021 and earlier. - Expr2021, + Expr2021 { + /// Keep track of whether the user used `:expr` or `:expr_2021` and we inferred it from the + /// edition of the span. This is used for diagnostics AND feature gating. + inferred: bool, + }, Ty, Ident, Lifetime, @@ -913,8 +917,13 @@ impl NonterminalKind { Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr, }, sym::pat_param => NonterminalKind::PatParam { inferred: false }, - sym::expr => NonterminalKind::Expr, - sym::expr_2021 if edition().at_least_rust_2021() => NonterminalKind::Expr2021, + sym::expr => match edition() { + Edition::Edition2015 | Edition::Edition2018 | Edition::Edition2021 => { + NonterminalKind::Expr2021 { inferred: true } + } + Edition::Edition2024 => NonterminalKind::Expr, + }, + sym::expr_2021 => NonterminalKind::Expr2021 { inferred: false }, sym::ty => NonterminalKind::Ty, sym::ident => NonterminalKind::Ident, sym::lifetime => NonterminalKind::Lifetime, @@ -933,8 +942,8 @@ impl NonterminalKind { NonterminalKind::Stmt => sym::stmt, NonterminalKind::PatParam { inferred: false } => sym::pat_param, NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat, - NonterminalKind::Expr => sym::expr, - NonterminalKind::Expr2021 => sym::expr_2021, + NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: true } => sym::expr, + NonterminalKind::Expr2021 { inferred: false } => sym::expr_2021, NonterminalKind::Ty => sym::ty, NonterminalKind::Ident => sym::ident, NonterminalKind::Lifetime => sym::lifetime, diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 49b1f5ce0e3..0050ff10539 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1292,7 +1292,9 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { // maintain IsInFollow::Yes } - NonterminalKind::Stmt | NonterminalKind::Expr | NonterminalKind::Expr2021 => { + NonterminalKind::Stmt + | NonterminalKind::Expr + | NonterminalKind::Expr2021 { inferred: _ } => { const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"]; match tok { TokenTree::Token(token) => match token.kind { diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 74f78c0ef78..fdf187438d3 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -113,7 +113,8 @@ pub(super) fn parse( ); token::NonterminalKind::Ident }); - if kind == token::NonterminalKind::Expr2021 + if kind + == (token::NonterminalKind::Expr2021 { inferred: false }) && !features.expr_fragment_specifier_2024 { rustc_session::parse::feature_err( diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index a0b704aeea5..59f6eff07b3 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -36,7 +36,7 @@ impl<'a> Parser<'a> { } match kind { - NonterminalKind::Expr2021 => { + NonterminalKind::Expr2021 { inferred: _ } => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) @@ -47,7 +47,6 @@ impl<'a> Parser<'a> { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) - && (!token.is_keyword(kw::Const) || token.span.edition().at_least_rust_2024()) } NonterminalKind::Ty => token.can_begin_type(), NonterminalKind::Ident => get_macro_ident(token).is_some(), @@ -149,7 +148,7 @@ impl<'a> Parser<'a> { })?) } - NonterminalKind::Expr | NonterminalKind::Expr2021 => { + NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: _ } => { NtExpr(self.parse_expr_force_collect()?) } NonterminalKind::Literal => { diff --git a/tests/ui/macros/expr_2021_implicit_in_2024.rs b/tests/ui/macros/expr_2021_implicit_in_2024.rs index d612c03650d..b3f7a31a802 100644 --- a/tests/ui/macros/expr_2021_implicit_in_2024.rs +++ b/tests/ui/macros/expr_2021_implicit_in_2024.rs @@ -1,6 +1,8 @@ //@ compile-flags: --edition=2024 -Zunstable-options //@ aux-build:expr_2021_implicit.rs +//@ check-pass + extern crate expr_2021_implicit; // Makes sure that a `:expr` fragment matcher defined in a edition 2021 crate diff --git a/tests/ui/macros/expr_2021_implicit_in_2024.stderr b/tests/ui/macros/expr_2021_implicit_in_2024.stderr deleted file mode 100644 index 962d572ca07..00000000000 --- a/tests/ui/macros/expr_2021_implicit_in_2024.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: did not expect an expression to be parsed - --> $DIR/expr_2021_implicit_in_2024.rs:8:1 - | -LL | expr_2021_implicit::m!(const {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `expr_2021_implicit::m` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 1 previous error - diff --git a/tests/ui/macros/expr_2021_old_edition.rs b/tests/ui/macros/expr_2021_old_edition.rs deleted file mode 100644 index a7711266106..00000000000 --- a/tests/ui/macros/expr_2021_old_edition.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ compile-flags: --edition=2018 - -// This test ensures that expr_2021 is not allowed on pre-2021 editions - -macro_rules! m { - ($e:expr_2021) => { //~ ERROR: invalid fragment specifier `expr_2021` - $e - }; -} - -fn main() { - m!(()); //~ ERROR: no rules expected the token `(` -} diff --git a/tests/ui/macros/expr_2021_old_edition.stderr b/tests/ui/macros/expr_2021_old_edition.stderr deleted file mode 100644 index bffa8a1ca17..00000000000 --- a/tests/ui/macros/expr_2021_old_edition.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error: invalid fragment specifier `expr_2021` - --> $DIR/expr_2021_old_edition.rs:6:6 - | -LL | ($e:expr_2021) => { - | ^^^^^^^^^^^^ - | - = help: fragment specifier `expr_2021` requires Rust 2021 or later - valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` - -error: no rules expected the token `(` - --> $DIR/expr_2021_old_edition.rs:12:8 - | -LL | macro_rules! m { - | -------------- when calling this macro -... -LL | m!(()); - | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$e:ident` - --> $DIR/expr_2021_old_edition.rs:6:6 - | -LL | ($e:expr_2021) => { - | ^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - -- cgit 1.4.1-3-g733a5 From 7d9a92ba31122950f2c7f6a71ad6dee49b3e95e4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 13 Jun 2024 13:40:14 +1000 Subject: Inline `can_begin_literal_maybe_minus` call into two places. It's clearer this way, because the `Interpolated` cases in `can_begin_const_arg` and `is_pat_range_end_start` are more permissive than the `Interpolated` cases in `can_begin_literal_maybe_minus`. --- compiler/rustc_ast/src/token.rs | 5 +++-- compiler/rustc_parse/src/parser/pat.rs | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 109c401bb6a..4d513797f5f 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -558,9 +558,10 @@ impl Token { /// Returns `true` if the token can appear at the start of a const param. pub fn can_begin_const_arg(&self) -> bool { match self.kind { - OpenDelim(Delimiter::Brace) => true, + OpenDelim(Delimiter::Brace) | Literal(..) | BinOp(Minus) => true, + Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, Interpolated(ref nt) => matches!(&**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)), - _ => self.can_begin_literal_maybe_minus(), + _ => false, } } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 03aea0888d9..6f2b7177159 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -939,7 +939,8 @@ impl<'a> Parser<'a> { || self.look_ahead(dist, |t| { t.is_path_start() // e.g. `MY_CONST`; || t.kind == token::Dot // e.g. `.5` for recovery; - || t.can_begin_literal_maybe_minus() // e.g. `42`. + || matches!(t.kind, token::Literal(..) | token::BinOp(token::Minus)) + || t.is_bool_lit() || t.is_whole_expr() || t.is_lifetime() // recover `'a` instead of `'a'` || (self.may_recover() // recover leading `(` -- cgit 1.4.1-3-g733a5 From c6f78270b66b2ffc78742006445df76105b7d558 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 13 Jun 2024 13:52:20 +1000 Subject: Introduce `can_begin_string_literal`. We currently use `can_begin_literal_maybe_minus` in a couple of places where only string literals are allowed. This commit introduces a more specific function, which makes things clearer. It doesn't change behaviour because the two functions affected (`is_unsafe_foreign_mod` and `check_keyword_case`) are always followed by a call to `parse_abi`, which checks again for a string literal. --- compiler/rustc_ast/src/token.rs | 15 +++++++++++++++ compiler/rustc_parse/src/parser/item.rs | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 4d513797f5f..4dc41a02cb8 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -621,6 +621,21 @@ impl Token { } } + pub fn can_begin_string_literal(&self) -> bool { + match self.uninterpolate().kind { + Literal(..) => true, + Interpolated(ref nt) => match &**nt { + NtLiteral(_) => true, + NtExpr(e) => match &e.kind { + ast::ExprKind::Lit(_) => true, + _ => false, + }, + _ => false, + }, + _ => false, + } + } + /// A convenience function for matching on identifiers during parsing. /// Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token /// into the regular identifier or lifetime token it refers to, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 2db777a9f70..3e1ea7b129d 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1259,7 +1259,7 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Extern]) && self.look_ahead( - 2 + self.look_ahead(2, |t| t.can_begin_literal_maybe_minus() as usize), + 2 + self.look_ahead(2, |t| t.can_begin_string_literal() as usize), |t| t.kind == token::OpenDelim(Delimiter::Brace), ) } @@ -2448,7 +2448,7 @@ impl<'a> Parser<'a> { }) // `extern ABI fn` || self.check_keyword_case(kw::Extern, case) - && self.look_ahead(1, |t| t.can_begin_literal_maybe_minus()) + && self.look_ahead(1, |t| t.can_begin_string_literal()) && (self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) || // this branch is only for better diagnostic in later, `pub` is not allowed here (self.may_recover() -- cgit 1.4.1-3-g733a5 From b104fbec85ac819d11bf8bf0d9cc11d0b8fb737e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 20 Jun 2024 06:06:53 +1000 Subject: Add blank lines after module-level `//` comments. Similar to the previous commit. --- compiler/rustc_hir_analysis/src/check/dropck.rs | 1 + compiler/rustc_parse/src/parser/expr.rs | 1 + library/core/tests/net/parser.rs | 1 + library/core/tests/pin_macro.rs | 1 + tests/run-make/symlinked-libraries/rmake.rs | 1 + 5 files changed, 5 insertions(+) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 8ec6dd12a78..19371448025 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -1,6 +1,7 @@ // FIXME(@lcnr): Move this module out of `rustc_hir_analysis`. // // We don't do any drop checking during hir typeck. + use rustc_data_structures::fx::FxHashSet; use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 09f706143fa..9fad954adda 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1,4 +1,5 @@ // ignore-tidy-filelength + use super::diagnostics::SnapshotParser; use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; diff --git a/library/core/tests/net/parser.rs b/library/core/tests/net/parser.rs index 36b87d7c1f5..e03959ac77c 100644 --- a/library/core/tests/net/parser.rs +++ b/library/core/tests/net/parser.rs @@ -1,4 +1,5 @@ // FIXME: These tests are all excellent candidates for AFL fuzz testing + use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; use core::str::FromStr; diff --git a/library/core/tests/pin_macro.rs b/library/core/tests/pin_macro.rs index 79c8c166c58..57485ef3974 100644 --- a/library/core/tests/pin_macro.rs +++ b/library/core/tests/pin_macro.rs @@ -1,4 +1,5 @@ // edition:2021 + use core::{ marker::PhantomPinned, mem::{drop as stuff, transmute}, diff --git a/tests/run-make/symlinked-libraries/rmake.rs b/tests/run-make/symlinked-libraries/rmake.rs index eaf0c44206a..3f02f19ccd5 100644 --- a/tests/run-make/symlinked-libraries/rmake.rs +++ b/tests/run-make/symlinked-libraries/rmake.rs @@ -6,6 +6,7 @@ // See https://github.com/rust-lang/rust/issues/12459 //@ ignore-cross-compile + use run_make_support::{create_symlink, dynamic_lib_name, fs_wrapper, rustc}; fn main() { -- cgit 1.4.1-3-g733a5 From 108b3f214a7e160ecb7ac2ec05bbb41aedd05a95 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Jun 2024 14:14:36 -0400 Subject: Properly gate `safe` keyword in pre-expansion --- compiler/rustc_ast_passes/src/feature_gate.rs | 4 ++++ compiler/rustc_parse/src/parser/mod.rs | 3 +++ tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs | 8 ++++++++ .../feature-gates/feature-gate-unsafe-extern-blocks.stderr | 13 ++++++++++++- 4 files changed, 27 insertions(+), 1 deletion(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 764d942836c..e1c1a027a30 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -562,6 +562,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental"); gate_all!(global_registration, "global registration is experimental"); gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental"); + gate_all!( + unsafe_extern_blocks, + "`unsafe extern {}` blocks and `safe` keyword are experimental" + ); if !visitor.features.never_patterns { if let Some(spans) = spans.get(&sym::never_patterns) { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 2f12459da57..cfd0a72c056 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1214,6 +1214,9 @@ impl<'a> Parser<'a> { if self.eat_keyword_case(kw::Unsafe, case) { Safety::Unsafe(self.prev_token.uninterpolated_span()) } else if self.eat_keyword_case(kw::Safe, case) { + self.psess + .gated_spans + .gate(sym::unsafe_extern_blocks, self.prev_token.uninterpolated_span()); Safety::Safe(self.prev_token.uninterpolated_span()) } else { Safety::Default diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs index eab134a4a4d..3ea62e875b8 100644 --- a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs +++ b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs @@ -2,4 +2,12 @@ unsafe extern "C" { //~^ ERROR extern block cannot be declared unsafe } +// We can't gate `unsafe extern` blocks themselves since they were previously +// allowed, but we should gate the `safe` soft keyword. +#[cfg(any())] +unsafe extern "C" { + safe fn foo(); + //~^ ERROR `unsafe extern {}` blocks and `safe` keyword are experimental +} + fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr index 7e9b199a2db..84f00827c60 100644 --- a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr +++ b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr @@ -4,5 +4,16 @@ error: extern block cannot be declared unsafe LL | unsafe extern "C" { | ^^^^^^ -error: aborting due to 1 previous error +error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental + --> $DIR/feature-gate-unsafe-extern-blocks.rs:9:5 + | +LL | safe fn foo(); + | ^^^^ + | + = note: see issue #123743 for more information + = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0658`. -- cgit 1.4.1-3-g733a5 From 3e59f0c3c5b4e23057dcfbe9da784164e2410a78 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Jun 2024 19:50:57 -0400 Subject: StaticForeignItem and StaticItem are the same --- compiler/rustc_ast/src/ast.rs | 34 +--------------------- compiler/rustc_ast/src/mut_visit.rs | 7 +---- compiler/rustc_ast/src/visit.rs | 7 +---- compiler/rustc_ast_lowering/src/item.rs | 7 +---- compiler/rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state/item.rs | 7 +---- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_resolve/src/def_collector.rs | 7 +---- src/tools/clippy/clippy_utils/src/ast_utils.rs | 4 +-- 9 files changed, 10 insertions(+), 67 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 71932f02017..30c54ef2d3c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3184,38 +3184,6 @@ pub struct StaticItem { pub expr: Option>, } -/// A static item in `extern` block. -// This struct is identical to StaticItem for now but it's going to have a safety attribute. -#[derive(Clone, Encodable, Decodable, Debug)] -pub struct StaticForeignItem { - pub ty: P, - pub safety: Safety, - pub mutability: Mutability, - pub expr: Option>, -} - -impl From for StaticForeignItem { - fn from(static_item: StaticItem) -> StaticForeignItem { - StaticForeignItem { - ty: static_item.ty, - safety: static_item.safety, - mutability: static_item.mutability, - expr: static_item.expr, - } - } -} - -impl From for StaticItem { - fn from(static_item: StaticForeignItem) -> StaticItem { - StaticItem { - ty: static_item.ty, - safety: static_item.safety, - mutability: static_item.mutability, - expr: static_item.expr, - } - } -} - #[derive(Clone, Encodable, Decodable, Debug)] pub struct ConstItem { pub defaultness: Defaultness, @@ -3430,7 +3398,7 @@ impl TryFrom for AssocItemKind { #[derive(Clone, Encodable, Decodable, Debug)] pub enum ForeignItemKind { /// A foreign static item (`static FOO: u8`). - Static(Box), + Static(Box), /// An foreign function. Fn(Box), /// An foreign type. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 35aa53e978c..c9d2f5c779b 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1310,12 +1310,7 @@ pub fn noop_flat_map_item( impl NoopVisitItemKind for ForeignItemKind { fn noop_visit(&mut self, visitor: &mut impl MutVisitor) { match self { - ForeignItemKind::Static(box StaticForeignItem { - ty, - mutability: _, - expr, - safety: _, - }) => { + ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => { visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index ed34a44db67..ce38a67ea69 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -672,12 +672,7 @@ impl WalkItemKind for ForeignItemKind { ) -> V::Result { let &Item { id, span, ident, ref vis, .. } = item; match self { - ForeignItemKind::Static(box StaticForeignItem { - ty, - mutability: _, - expr, - safety: _, - }) => { + ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c6c0d9a2e60..4c7e8c24d32 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -664,12 +664,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics, safety) } - ForeignItemKind::Static(box StaticForeignItem { - ty, - mutability, - expr: _, - safety, - }) => { + ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => { let ty = self .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); let safety = self.lower_safety(*safety, hir::Safety::Unsafe); diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b274a9b9114..cad1fc79d7f 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1232,7 +1232,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_foreign_ty_genericless(generics, where_clauses); self.check_foreign_item_ascii_only(fi.ident); } - ForeignItemKind::Static(box StaticForeignItem { expr, safety, .. }) => { + ForeignItemKind::Static(box StaticItem { expr, safety, .. }) => { self.check_foreign_item_safety(fi.span, *safety); self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span)); self.check_foreign_item_ascii_only(fi.ident); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 49ac5ece337..d8382057d3f 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -37,12 +37,7 @@ impl<'a> State<'a> { ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => { self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs); } - ast::ForeignItemKind::Static(box ast::StaticForeignItem { - ty, - mutability, - expr, - safety, - }) => { + ast::ForeignItemKind::Static(box ast::StaticItem { ty, mutability, expr, safety }) => { self.print_safety(*safety); self.print_item_const( ident, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 3e1ea7b129d..abb6b51cebd 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1228,7 +1228,7 @@ impl<'a> Parser<'a> { ident_span: ident.span, const_span, }); - ForeignItemKind::Static(Box::new(StaticForeignItem { + ForeignItemKind::Static(Box::new(StaticItem { ty, mutability: Mutability::Not, expr, diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index fb6e55f2b7b..ad1ec4438cc 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -217,12 +217,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { let def_kind = match fi.kind { - ForeignItemKind::Static(box StaticForeignItem { - ty: _, - mutability, - expr: _, - safety, - }) => { + ForeignItemKind::Static(box StaticItem { ty: _, mutability, expr: _, safety }) => { let safety = match safety { ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe, ast::Safety::Safe(_) => hir::Safety::Safe, diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index fb43f7d80af..785d5ed5dbe 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -449,13 +449,13 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { use ForeignItemKind::*; match (l, r) { ( - Static(box StaticForeignItem { + Static(box StaticItem { ty: lt, mutability: lm, expr: le, safety: ls, }), - Static(box StaticForeignItem { + Static(box StaticItem { ty: rt, mutability: rm, expr: re, -- cgit 1.4.1-3-g733a5 From e2aa38e6abf9c2ddd06fb2469628ee488dc49e30 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 23 Jun 2024 08:13:56 +1000 Subject: Rework pattern and expression nonterminal kinds. Merge `PatParam`/`PatWithOr`, and `Expr`/`Expr2021`, for a few reasons. - It's conceptually nice, because the two pattern kinds and the two expression kinds are very similar. - With expressions in particular, there are several places where both expression kinds get the same treatment. - It removes one unreachable match arm. - Most importantly, for #124141 I will need to introduce a new type `MetaVarKind` that is very similar to `NonterminalKind`, but records a couple of extra fields for expression metavars. It's nicer to have a single `MetaVarKind::Expr` expression variant to hold those extra fields instead of duplicating them across two variants `MetaVarKind::{Expr,Expr2021}`. And then it makes sense for patterns to be treated the same way, and for `NonterminalKind` to also be treated the same way. I also clarified the comments, because I have long found them a little hard to understand. --- compiler/rustc_ast/src/token.rs | 73 ++++++++++++++++---------- compiler/rustc_expand/src/mbe/macro_rules.rs | 20 +++---- compiler/rustc_expand/src/mbe/quoted.rs | 4 +- compiler/rustc_parse/src/parser/nonterminal.rs | 28 +++++----- src/tools/rustfmt/src/parse/macros/mod.rs | 6 +-- 5 files changed, 71 insertions(+), 60 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index cc66cc87652..efe19566152 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -1,6 +1,8 @@ pub use BinOpToken::*; pub use LitKind::*; pub use Nonterminal::*; +pub use NtExprKind::*; +pub use NtPatKind::*; pub use TokenKind::*; use crate::ast; @@ -871,6 +873,27 @@ impl PartialEq for Token { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable)] +pub enum NtPatKind { + // Matches or-patterns. Was written using `pat` in edition 2021 or later. + PatWithOr, + // Doesn't match or-patterns. + // - `inferred`: was written using `pat` in edition 2015 or 2018. + // - `!inferred`: was written using `pat_param`. + PatParam { inferred: bool }, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable)] +pub enum NtExprKind { + // Matches expressions using the post-edition 2024. Was written using + // `expr` in edition 2024 or later. + Expr, + // Matches expressions using the pre-edition 2024 rules. + // - `inferred`: was written using `expr` in edition 2021 or earlier. + // - `!inferred`: was written using `expr_2021`. + Expr2021 { inferred: bool }, +} + #[derive(Clone, Encodable, Decodable)] /// For interpolation during macro expansion. pub enum Nonterminal { @@ -892,19 +915,8 @@ pub enum NonterminalKind { Item, Block, Stmt, - PatParam { - /// Keep track of whether the user used `:pat_param` or `:pat` and we inferred it from the - /// edition of the span. This is used for diagnostics. - inferred: bool, - }, - PatWithOr, - Expr, - /// Matches an expression using the rules from edition 2021 and earlier. - Expr2021 { - /// Keep track of whether the user used `:expr` or `:expr_2021` and we inferred it from the - /// edition of the span. This is used for diagnostics AND feature gating. - inferred: bool, - }, + Pat(NtPatKind), + Expr(NtExprKind), Ty, Ident, Lifetime, @@ -926,20 +938,22 @@ impl NonterminalKind { sym::item => NonterminalKind::Item, sym::block => NonterminalKind::Block, sym::stmt => NonterminalKind::Stmt, - sym::pat => match edition() { - Edition::Edition2015 | Edition::Edition2018 => { - NonterminalKind::PatParam { inferred: true } + sym::pat => { + if edition().at_least_rust_2021() { + NonterminalKind::Pat(PatWithOr) + } else { + NonterminalKind::Pat(PatParam { inferred: true }) } - Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr, - }, - sym::pat_param => NonterminalKind::PatParam { inferred: false }, - sym::expr => match edition() { - Edition::Edition2015 | Edition::Edition2018 | Edition::Edition2021 => { - NonterminalKind::Expr2021 { inferred: true } + } + sym::pat_param => NonterminalKind::Pat(PatParam { inferred: false }), + sym::expr => { + if edition().at_least_rust_2024() { + NonterminalKind::Expr(Expr) + } else { + NonterminalKind::Expr(Expr2021 { inferred: true }) } - Edition::Edition2024 => NonterminalKind::Expr, - }, - sym::expr_2021 => NonterminalKind::Expr2021 { inferred: false }, + } + sym::expr_2021 => NonterminalKind::Expr(Expr2021 { inferred: false }), sym::ty => NonterminalKind::Ty, sym::ident => NonterminalKind::Ident, sym::lifetime => NonterminalKind::Lifetime, @@ -951,15 +965,16 @@ impl NonterminalKind { _ => return None, }) } + fn symbol(self) -> Symbol { match self { NonterminalKind::Item => sym::item, NonterminalKind::Block => sym::block, NonterminalKind::Stmt => sym::stmt, - NonterminalKind::PatParam { inferred: false } => sym::pat_param, - NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat, - NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: true } => sym::expr, - NonterminalKind::Expr2021 { inferred: false } => sym::expr_2021, + NonterminalKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat, + NonterminalKind::Pat(PatParam { inferred: false }) => sym::pat_param, + NonterminalKind::Expr(Expr2021 { inferred: true } | Expr) => sym::expr, + NonterminalKind::Expr(Expr2021 { inferred: false }) => sym::expr_2021, NonterminalKind::Ty => sym::ty, NonterminalKind::Ident => sym::ident, NonterminalKind::Lifetime => sym::lifetime, diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 0045baf7c56..e43ba7c3a5a 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -10,7 +10,9 @@ use crate::mbe::transcribe::transcribe; use ast::token::IdentIsRaw; use rustc_ast as ast; -use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind, TokenKind::*}; +use rustc_ast::token::{ + self, Delimiter, NonterminalKind, NtPatKind::*, Token, TokenKind, TokenKind::*, +}; use rustc_ast::tokenstream::{DelimSpan, TokenStream}; use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; @@ -1145,7 +1147,7 @@ fn check_matcher_core<'tt>( // Macros defined in the current crate have a real node id, // whereas macros from an external crate have a dummy id. if def.id != DUMMY_NODE_ID - && matches!(kind, NonterminalKind::PatParam { inferred: true }) + && matches!(kind, NonterminalKind::Pat(PatParam { inferred: true })) && matches!( next_token, TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or) @@ -1155,7 +1157,7 @@ fn check_matcher_core<'tt>( let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( span, name, - Some(NonterminalKind::PatParam { inferred: false }), + Some(NonterminalKind::Pat(PatParam { inferred: false })), )); sess.psess.buffer_lint( RUST_2021_INCOMPATIBLE_OR_PATTERNS, @@ -1188,14 +1190,14 @@ fn check_matcher_core<'tt>( ); err.span_label(sp, format!("not allowed after `{kind}` fragments")); - if kind == NonterminalKind::PatWithOr + if kind == NonterminalKind::Pat(PatWithOr) && sess.psess.edition.at_least_rust_2021() && next_token.is_token(&BinOp(token::BinOpToken::Or)) { let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( span, name, - Some(NonterminalKind::PatParam { inferred: false }), + Some(NonterminalKind::Pat(PatParam { inferred: false })), )); err.span_suggestion( span, @@ -1295,9 +1297,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { // maintain IsInFollow::Yes } - NonterminalKind::Stmt - | NonterminalKind::Expr - | NonterminalKind::Expr2021 { inferred: _ } => { + NonterminalKind::Stmt | NonterminalKind::Expr(_) => { const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"]; match tok { TokenTree::Token(token) => match token.kind { @@ -1307,7 +1307,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { _ => IsInFollow::No(TOKENS), } } - NonterminalKind::PatParam { .. } => { + NonterminalKind::Pat(PatParam { .. }) => { const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"]; match tok { TokenTree::Token(token) => match token.kind { @@ -1320,7 +1320,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { _ => IsInFollow::No(TOKENS), } } - NonterminalKind::PatWithOr => { + NonterminalKind::Pat(PatWithOr) => { const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"]; match tok { TokenTree::Token(token) => match token.kind { diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index e60e4d70fbb..9c480f17b42 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -2,7 +2,7 @@ use crate::errors; use crate::mbe::macro_parser::count_metavar_decls; use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree}; -use rustc_ast::token::{self, Delimiter, IdentIsRaw, NonterminalKind, Token}; +use rustc_ast::token::{self, Delimiter, IdentIsRaw, NonterminalKind, NtExprKind::*, Token}; use rustc_ast::{tokenstream, NodeId}; use rustc_ast_pretty::pprust; use rustc_feature::Features; @@ -109,7 +109,7 @@ pub(super) fn parse( }); NonterminalKind::Ident }); - if kind == (NonterminalKind::Expr2021 { inferred: false }) + if kind == NonterminalKind::Expr(Expr2021 { inferred: false }) && !features.expr_fragment_specifier_2024 { rustc_session::parse::feature_err( diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 59f6eff07b3..4a78b427832 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -1,5 +1,7 @@ use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token}; +use rustc_ast::token::{ + self, Delimiter, Nonterminal::*, NonterminalKind, NtExprKind::*, NtPatKind::*, Token, +}; use rustc_ast::HasTokens; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; @@ -36,14 +38,14 @@ impl<'a> Parser<'a> { } match kind { - NonterminalKind::Expr2021 { inferred: _ } => { + NonterminalKind::Expr(Expr2021 { .. }) => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) // This exception is here for backwards compatibility. && !token.is_keyword(kw::Const) } - NonterminalKind::Expr => { + NonterminalKind::Expr(Expr) => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) @@ -74,7 +76,7 @@ impl<'a> Parser<'a> { token::Interpolated(nt) => may_be_ident(nt), _ => false, }, - NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => match &token.kind { + NonterminalKind::Pat(pat_kind) => match &token.kind { // box, ref, mut, and other identifiers (can stricten) token::Ident(..) | token::NtIdent(..) | token::OpenDelim(Delimiter::Parenthesis) | // tuple pattern @@ -89,7 +91,7 @@ impl<'a> Parser<'a> { token::Lt | // path (UFCS constant) token::BinOp(token::Shl) => true, // path (double UFCS) // leading vert `|` or-pattern - token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr), + token::BinOp(token::Or) => matches!(pat_kind, PatWithOr), token::Interpolated(nt) => may_be_ident(nt), _ => false, }, @@ -135,31 +137,25 @@ impl<'a> Parser<'a> { .create_err(UnexpectedNonterminal::Statement(self.token.span))); } }, - NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { - NtPat(self.collect_tokens_no_attrs(|this| match kind { - NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None), - NonterminalKind::PatWithOr => this.parse_pat_allow_top_alt( + NonterminalKind::Pat(pat_kind) => { + NtPat(self.collect_tokens_no_attrs(|this| match pat_kind { + PatParam { .. } => this.parse_pat_no_top_alt(None, None), + PatWithOr => this.parse_pat_allow_top_alt( None, RecoverComma::No, RecoverColon::No, CommaRecoveryMode::EitherTupleOrPipe, ), - _ => unreachable!(), })?) } - - NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: _ } => { - NtExpr(self.parse_expr_force_collect()?) - } + NonterminalKind::Expr(_) => NtExpr(self.parse_expr_force_collect()?), NonterminalKind::Literal => { // The `:literal` matcher does not support attributes NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?) } - NonterminalKind::Ty => { NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?) } - // this could be handled like a token, since it is one NonterminalKind::Ident => { return if let Some((ident, is_raw)) = get_macro_ident(&self.token) { diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs index 89169e10715..60c827fd03b 100644 --- a/src/tools/rustfmt/src/parse/macros/mod.rs +++ b/src/tools/rustfmt/src/parse/macros/mod.rs @@ -1,4 +1,4 @@ -use rustc_ast::token::{Delimiter, NonterminalKind, TokenKind}; +use rustc_ast::token::{Delimiter, NonterminalKind, NtExprKind::*, NtPatKind::*, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{ast, ptr}; use rustc_parse::parser::{ForceCollect, Parser, Recovery}; @@ -48,7 +48,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { parse_macro_arg!( Expr, - NonterminalKind::Expr, + NonterminalKind::Expr(Expr), |parser: &mut Parser<'b>| parser.parse_expr(), |x: ptr::P| Some(x) ); @@ -60,7 +60,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { ); parse_macro_arg!( Pat, - NonterminalKind::PatParam { inferred: false }, + NonterminalKind::Pat(PatParam { inferred: false }), |parser: &mut Parser<'b>| parser.parse_pat_no_top_alt(None, None), |x: ptr::P| Some(x) ); -- cgit 1.4.1-3-g733a5 From 284437d4342b70e03771d5329e5ac02dd719166a Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Sun, 23 Jun 2024 21:33:59 +0000 Subject: Special case when a code line only has multiline span starts ``` 3 | X0 Y0 Z0 | _____^ - - | | _______| | | || _________| 4 | ||| X1 Y1 Z1 5 | ||| X2 Y2 Z2 | |||____^__-__- `Z` label | ||_____|__| | |______| `Y` is a good letter too | `X` is a good letter ``` --- compiler/rustc_errors/src/emitter.rs | 27 ++++++++++++++++++++++++- compiler/rustc_parse/src/parser/tests.rs | 17 +++++++--------- tests/ui/async-await/async-is-unwindsafe.stderr | 5 ++--- tests/ui/lint/suggestions.stderr | 5 ++--- 4 files changed, 37 insertions(+), 17 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 7405705dd33..45118bcc58a 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -902,7 +902,7 @@ impl HumanEmitter { // // let mut annotations_position = vec![]; - let mut line_len = 0; + let mut line_len: usize = 0; let mut p = 0; for (i, annotation) in annotations.iter().enumerate() { for (j, next) in annotations.iter().enumerate() { @@ -973,6 +973,31 @@ impl HumanEmitter { return vec![]; } + if annotations_position + .iter() + .all(|(_, ann)| matches!(ann.annotation_type, AnnotationType::MultilineStart(_))) + && let Some(max_pos) = annotations_position.iter().map(|(pos, _)| *pos).max() + { + // Special case the following, so that we minimize overlapping multiline spans. + // + // 3 │ X0 Y0 Z0 + // │ ┏━━━━━┛ │ │ < We are writing these lines + // │ ┃┌───────┘ │ < by reverting the "depth" of + // │ ┃│┌─────────┘ < their multilne spans. + // 4 │ ┃││ X1 Y1 Z1 + // 5 │ ┃││ X2 Y2 Z2 + // │ ┃│└────╿──│──┘ `Z` label + // │ ┃└─────│──┤ + // │ ┗━━━━━━┥ `Y` is a good letter too + // ╰╴ `X` is a good letter + for (pos, _) in &mut annotations_position { + *pos = max_pos - *pos; + } + // We know then that we don't need an additional line for the span label, saving us + // one line of vertical space. + line_len = line_len.saturating_sub(1); + } + // Write the column separator. // // After this we will have: diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 3a4690670af..42392ad2163 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -322,9 +322,8 @@ error: foo --> test.rs:3:3 | 3 | X0 Y0 - | ___^__- - | |___| - | || + | ____^ - + | | ______| 4 | || X1 Y1 5 | || X2 Y2 | ||____^__- `Y` is a good letter too @@ -361,9 +360,8 @@ error: foo --> test.rs:3:3 | 3 | X0 Y0 - | ___^__- - | |___| - | || + | ____^ - + | | ______| 4 | || Y1 X1 | ||____-__^ `X` is a good letter | |____| @@ -445,10 +443,9 @@ error: foo --> test.rs:3:3 | 3 | X0 Y0 Z0 - | ___^__-__- - | |___|__| - | ||___| - | ||| + | _____^ - - + | | _______| | + | || _________| 4 | ||| X1 Y1 Z1 5 | ||| X2 Y2 Z2 | |||____^__-__- `Z` label diff --git a/tests/ui/async-await/async-is-unwindsafe.stderr b/tests/ui/async-await/async-is-unwindsafe.stderr index 5d87fc74768..85fdcda3b8c 100644 --- a/tests/ui/async-await/async-is-unwindsafe.stderr +++ b/tests/ui/async-await/async-is-unwindsafe.stderr @@ -2,9 +2,8 @@ error[E0277]: the type `&mut Context<'_>` may not be safely transferred across a --> $DIR/async-is-unwindsafe.rs:12:5 | LL | is_unwindsafe(async { - | _____^_____________- - | |_____| - | || + | ______^ - + | | ___________________| LL | || LL | || use std::ptr::null; LL | || use std::task::{Context, RawWaker, RawWakerVTable, Waker}; diff --git a/tests/ui/lint/suggestions.stderr b/tests/ui/lint/suggestions.stderr index 4caee777a13..a4871ead74b 100644 --- a/tests/ui/lint/suggestions.stderr +++ b/tests/ui/lint/suggestions.stderr @@ -41,9 +41,8 @@ warning: variable does not need to be mutable --> $DIR/suggestions.rs:54:13 | LL | let mut - | ______________^ - | | _____________| - | || + | _____________^ + | |_____________| LL | || b = 1; | ||____________-^ | |_____________| -- cgit 1.4.1-3-g733a5 From 379b7614627b3a917a5f459388f95c4fb55c39ad Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 17 Jun 2024 14:44:55 +1000 Subject: Inline and remove `maybe_whole_expr!`. And remove the `NtPath` and `NtBlock` cases in `parse_literal_maybe_minus`, because they are unnecessary. --- compiler/rustc_parse/src/parser/expr.rs | 73 ++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 32 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9fad954adda..e0c70884fee 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -39,36 +39,6 @@ use rustc_span::{BytePos, ErrorGuaranteed, Pos, Span}; use thin_vec::{thin_vec, ThinVec}; use tracing::instrument; -/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression -/// dropped into the token stream, which happens while parsing the result of -/// macro expansion). Placement of these is not as complex as I feared it would -/// be. The important thing is to make sure that lookahead doesn't balk at -/// `token::Interpolated` tokens. -macro_rules! maybe_whole_expr { - ($p:expr) => { - if let token::Interpolated(nt) = &$p.token.kind { - match &**nt { - token::NtExpr(e) | token::NtLiteral(e) => { - let e = e.clone(); - $p.bump(); - return Ok(e); - } - token::NtPath(path) => { - let path = (**path).clone(); - $p.bump(); - return Ok($p.mk_expr($p.prev_token.span, ExprKind::Path(None, path))); - } - token::NtBlock(block) => { - let block = block.clone(); - $p.bump(); - return Ok($p.mk_expr($p.prev_token.span, ExprKind::Block(block, None))); - } - _ => {} - }; - } - }; -} - #[derive(Debug)] pub(super) enum LhsExpr { // Already parsed just the outer attributes. @@ -1421,7 +1391,27 @@ impl<'a> Parser<'a> { /// correctly if called from `parse_dot_or_call_expr()`. fn parse_expr_bottom(&mut self) -> PResult<'a, P> { maybe_recover_from_interpolated_ty_qpath!(self, true); - maybe_whole_expr!(self); + + if let token::Interpolated(nt) = &self.token.kind { + match &**nt { + token::NtExpr(e) | token::NtLiteral(e) => { + let e = e.clone(); + self.bump(); + return Ok(e); + } + token::NtPath(path) => { + let path = (**path).clone(); + self.bump(); + return Ok(self.mk_expr(self.prev_token.span, ExprKind::Path(None, path))); + } + token::NtBlock(block) => { + let block = block.clone(); + self.bump(); + return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None))); + } + _ => {} + }; + } // Outer attributes are already parsed and will be // added to the return value after the fact. @@ -2190,7 +2180,26 @@ impl<'a> Parser<'a> { /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). /// Keep this in sync with `Token::can_begin_literal_maybe_minus`. pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { - maybe_whole_expr!(self); + if let token::Interpolated(nt) = &self.token.kind { + match &**nt { + // FIXME(nnethercote) The `NtExpr` case should only match if + // `e` is an `ExprKind::Lit` or an `ExprKind::Unary` containing + // an `UnOp::Neg` and an `ExprKind::Lit`, like how + // `can_begin_literal_maybe_minus` works. But this method has + // been over-accepting for a long time, and to make that change + // here requires also changing some `parse_literal_maybe_minus` + // call sites to accept additional expression kinds. E.g. + // `ExprKind::Path` must be accepted when parsing range + // patterns. That requires some care. So for now, we continue + // being less strict here than we should be. + token::NtExpr(e) | token::NtLiteral(e) => { + let e = e.clone(); + self.bump(); + return Ok(e); + } + _ => {} + }; + } let lo = self.token.span; let minus_present = self.eat(&token::BinOp(token::Minus)); -- cgit 1.4.1-3-g733a5 From cf0251d92ced77d926a2292df96cb9ad3ce14f97 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 17 Jun 2024 18:47:09 +1000 Subject: Fix a span in `parse_ty_bare_fn`. It currently goes one token too far. Example: line 259 of `tests/ui/abi/compatibility.rs`: ``` test_abi_compatible!(fn_fn, fn(), fn(i32) -> i32); ``` This commit changes the span for the second element from `fn(),` to `fn()`, i.e. removes the extraneous comma. --- compiler/rustc_ast/src/ast.rs | 3 ++- compiler/rustc_parse/src/parser/ty.rs | 2 +- tests/ui/rust-2024/safe-outside-extern.gated.stderr | 2 +- tests/ui/rust-2024/safe-outside-extern.ungated.stderr | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 30c54ef2d3c..4a3ce0e0c30 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2126,7 +2126,8 @@ pub struct BareFnTy { pub ext: Extern, pub generic_params: ThinVec, pub decl: P, - /// Span of the `fn(...) -> ...` part. + /// Span of the `[unsafe] [extern] fn(...) -> ...` part, i.e. everything + /// after the generic params (if there are any, e.g. `for<'a>`). pub decl_span: Span, } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index fcd623b477f..d2043c353fe 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -608,7 +608,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span }); } // FIXME(gen_blocks): emit a similar error for `gen fn()` - let decl_span = span_start.to(self.token.span); + let decl_span = span_start.to(self.prev_token.span); Ok(TyKind::BareFn(P(BareFnTy { ext, safety, generic_params: params, decl, decl_span }))) } diff --git a/tests/ui/rust-2024/safe-outside-extern.gated.stderr b/tests/ui/rust-2024/safe-outside-extern.gated.stderr index ea7aa181445..18a3361f35b 100644 --- a/tests/ui/rust-2024/safe-outside-extern.gated.stderr +++ b/tests/ui/rust-2024/safe-outside-extern.gated.stderr @@ -26,7 +26,7 @@ error: function pointers cannot be declared with `safe` safety qualifier --> $DIR/safe-outside-extern.rs:24:14 | LL | type FnPtr = safe fn(i32, i32) -> i32; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/rust-2024/safe-outside-extern.ungated.stderr b/tests/ui/rust-2024/safe-outside-extern.ungated.stderr index 908f5b504eb..9ea6d451e8c 100644 --- a/tests/ui/rust-2024/safe-outside-extern.ungated.stderr +++ b/tests/ui/rust-2024/safe-outside-extern.ungated.stderr @@ -26,7 +26,7 @@ error: function pointers cannot be declared with `safe` safety qualifier --> $DIR/safe-outside-extern.rs:24:14 | LL | type FnPtr = safe fn(i32, i32) -> i32; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental --> $DIR/safe-outside-extern.rs:4:1 -- cgit 1.4.1-3-g733a5 From 789ee88bd015fde4257464d0120ab57b0d744e0b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 27 Jun 2024 14:56:57 -0400 Subject: Tighten spans for async blocks --- compiler/rustc_ast/src/ast.rs | 5 ++- compiler/rustc_ast/src/mut_visit.rs | 3 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 7 ++- compiler/rustc_ast_lowering/src/item.rs | 16 +++---- compiler/rustc_ast_pretty/src/pprust/state/expr.rs | 2 +- .../rustc_builtin_macros/src/assert/context.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 5 ++- compiler/rustc_resolve/src/def_collector.rs | 2 +- .../src/suspicious_operation_groupings.rs | 2 +- src/tools/clippy/clippy_utils/src/ast_utils.rs | 2 +- src/tools/rustfmt/src/expr.rs | 2 +- ...sync-block-control-flow-static-semantics.stderr | 26 ++++++----- .../async-borrowck-escaping-block-error.stderr | 10 ++--- .../async-closures/wrong-fn-kind.stderr | 24 +++++------ tests/ui/async-await/async-is-unwindsafe.stderr | 25 ++++++----- tests/ui/async-await/coroutine-desc.stderr | 4 +- tests/ui/async-await/coroutine-not-future.stderr | 4 +- .../async-await/issue-67252-unnamed-future.stderr | 2 +- tests/ui/async-await/issue-68112.stderr | 15 +++---- .../async-await/issue-70935-complex-spans.stderr | 20 +++------ .../issue-74072-lifetime-name-annotations.stderr | 14 +++--- tests/ui/async-await/issue-86507.stderr | 2 +- .../issues/issue-78938-async-block.stderr | 10 ++--- .../track-caller/async-closure-gate.afn.stderr | 4 +- .../track-caller/async-closure-gate.nofeat.stderr | 4 +- tests/ui/async-await/try-on-option-in-async.stderr | 12 +++--- .../borrowck/cloning-in-async-block-121547.stderr | 18 ++++---- .../break-inside-coroutine-issue-124495.stderr | 50 +++++++++------------- tests/ui/coroutine/clone-impl-async.stderr | 24 +++++------ tests/ui/coroutine/gen_block_is_coro.stderr | 12 +++--- tests/ui/coroutine/gen_block_is_no_future.stderr | 6 +-- tests/ui/coroutine/gen_block_move.stderr | 13 +++--- .../issue-90014-tait.stderr | 2 +- tests/ui/impl-trait/issue-55872-3.stderr | 4 +- tests/ui/impl-trait/issues/issue-78722-2.stderr | 4 +- tests/ui/impl-trait/issues/issue-78722.stderr | 2 +- tests/ui/impl-trait/nested-return-type4.stderr | 2 +- .../mismatch-sugg-for-shorthand-field.stderr | 4 +- tests/ui/pattern/non-structural-match-types.stderr | 2 +- .../expected-boxed-future-isnt-pinned.stderr | 2 +- tests/ui/traits/next-solver/async.fail.stderr | 2 +- .../indirect-recursion-issue-112047.stderr | 4 +- 43 files changed, 173 insertions(+), 204 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4a3ce0e0c30..f5e79c04d78 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1454,7 +1454,10 @@ pub enum ExprKind { Block(P, Option