diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e7b2e4b1cb4b0..bdb1879ec201d 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -403,8 +403,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { walk_list!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref); visitor.visit_ty(&mutable_type.ty) } - TyKind::Tup(tys) => { - walk_list!(visitor, visit_ty, tys); + TyKind::Tup(tuple_element_types) => { + walk_list!(visitor, visit_ty, tuple_element_types); } TyKind::BareFn(function_declaration) => { walk_list!(visitor, visit_generic_param, &function_declaration.generic_params); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 26274822ed8a8..16d5edfd303a3 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2394,7 +2394,7 @@ impl<'a> Parser<'a> { /// Some special error handling for the "top-level" patterns in a match arm, /// `for` loop, `let`, &c. (in contrast to subpatterns within such). - pub(crate) fn maybe_recover_colon_colon_in_pat_typo_or_anon_enum( + pub(crate) fn maybe_recover_colon_colon_in_pat_typo( &mut self, mut first_pat: P, expected: Option, @@ -2405,41 +2405,26 @@ impl<'a> Parser<'a> { if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..)) || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) { - let mut snapshot_type = self.create_snapshot_for_diagnostic(); - snapshot_type.bump(); // `:` - match snapshot_type.parse_ty() { - Err(inner_err) => { - inner_err.cancel(); - } - Ok(ty) => { - let Err(mut err) = self.expected_one_of_not_found(&[], &[]) else { - return first_pat; - }; - err.span_label(ty.span, "specifying the type of a pattern isn't supported"); - self.restore_snapshot(snapshot_type); - let span = first_pat.span.to(ty.span); - first_pat = self.mk_pat(span, PatKind::Wild); - err.emit(); - } - } return first_pat; } // The pattern looks like it might be a path with a `::` -> `:` typo: // `match foo { bar:baz => {} }` - let colon_span = self.token.span; + let span = self.token.span; // We only emit "unexpected `:`" error here if we can successfully parse the // whole pattern correctly in that case. - let mut snapshot_pat = self.create_snapshot_for_diagnostic(); - let mut snapshot_type = self.create_snapshot_for_diagnostic(); + let snapshot = self.create_snapshot_for_diagnostic(); // Create error for "unexpected `:`". match self.expected_one_of_not_found(&[], &[]) { Err(mut err) => { - snapshot_pat.bump(); // Skip the `:`. - snapshot_type.bump(); // Skip the `:`. - match snapshot_pat.parse_pat_no_top_alt(expected) { + self.bump(); // Skip the `:`. + match self.parse_pat_no_top_alt(expected) { Err(inner_err) => { + // Carry on as if we had not done anything, callers will emit a + // reasonable error. inner_err.cancel(); + err.cancel(); + self.restore_snapshot(snapshot); } Ok(mut pat) => { // We've parsed the rest of the pattern. @@ -2503,8 +2488,8 @@ impl<'a> Parser<'a> { _ => {} } if show_sugg { - err.span_suggestion_verbose( - colon_span.until(self.look_ahead(1, |t| t.span)), + err.span_suggestion( + span, "maybe write a path separator here", "::", Applicability::MaybeIncorrect, @@ -2512,24 +2497,13 @@ impl<'a> Parser<'a> { } else { first_pat = self.mk_pat(new_span, PatKind::Wild); } - self.restore_snapshot(snapshot_pat); + err.emit(); } } - match snapshot_type.parse_ty() { - Err(inner_err) => { - inner_err.cancel(); - } - Ok(ty) => { - err.span_label(ty.span, "specifying the type of a pattern isn't supported"); - self.restore_snapshot(snapshot_type); - let new_span = first_pat.span.to(ty.span); - first_pat = self.mk_pat(new_span, PatKind::Wild); - } - } - err.emit(); } _ => { // Carry on as if we had not done anything. This should be unreachable. + self.restore_snapshot(snapshot); } }; first_pat diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 88c75fd81e758..e75554ba124b3 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -148,8 +148,7 @@ impl<'a> Parser<'a> { // Check if the user wrote `foo:bar` instead of `foo::bar`. if ra == RecoverColon::Yes { - first_pat = - self.maybe_recover_colon_colon_in_pat_typo_or_anon_enum(first_pat, expected); + first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, expected); } if let Some(leading_vert_span) = leading_vert_span { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 306cbcff149f7..646e2f45e640c 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -17,7 +17,6 @@ use rustc_ast::{ self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind, }; -use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, PResult}; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym, Ident}; @@ -50,24 +49,17 @@ pub(super) enum AllowPlus { No, } -#[derive(PartialEq, Clone, Copy)] +#[derive(PartialEq)] pub(super) enum RecoverQPath { Yes, No, } -#[derive(PartialEq, Clone, Copy)] pub(super) enum RecoverQuestionMark { Yes, No, } -#[derive(PartialEq, Clone, Copy)] -pub(super) enum RecoverAnonEnum { - Yes, - No, -} - /// Signals whether parsing a type should recover `->`. /// /// More specifically, when parsing a function like: @@ -100,7 +92,7 @@ impl RecoverReturnSign { } // Is `...` (`CVarArgs`) legal at this level of type parsing? -#[derive(PartialEq, Clone, Copy)] +#[derive(PartialEq)] enum AllowCVariadic { Yes, No, @@ -125,7 +117,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, - RecoverAnonEnum::No, ) } @@ -140,7 +131,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, Some(ty_params), RecoverQuestionMark::Yes, - RecoverAnonEnum::No, ) } @@ -155,7 +145,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, - RecoverAnonEnum::Yes, ) } @@ -173,7 +162,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, - RecoverAnonEnum::No, ) } @@ -187,7 +175,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::No, - RecoverAnonEnum::No, ) } @@ -199,7 +186,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::No, - RecoverAnonEnum::No, ) } @@ -212,7 +198,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::OnlyFatArrow, None, RecoverQuestionMark::Yes, - RecoverAnonEnum::No, ) } @@ -232,7 +217,6 @@ impl<'a> Parser<'a> { recover_return_sign, None, RecoverQuestionMark::Yes, - RecoverAnonEnum::Yes, )?; FnRetTy::Ty(ty) } else if recover_return_sign.can_recover(&self.token.kind) { @@ -247,7 +231,6 @@ impl<'a> Parser<'a> { recover_return_sign, None, RecoverQuestionMark::Yes, - RecoverAnonEnum::Yes, )?; FnRetTy::Ty(ty) } else { @@ -263,7 +246,6 @@ impl<'a> Parser<'a> { recover_return_sign: RecoverReturnSign, ty_generics: Option<&Generics>, recover_question_mark: RecoverQuestionMark, - recover_anon_enum: RecoverAnonEnum, ) -> PResult<'a, P> { let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); @@ -347,50 +329,9 @@ impl<'a> Parser<'a> { AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?, AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty), } - if RecoverQuestionMark::Yes == recover_question_mark { + if let RecoverQuestionMark::Yes = recover_question_mark { ty = self.maybe_recover_from_question_mark(ty); } - if recover_anon_enum == RecoverAnonEnum::Yes - && self.check_noexpect(&token::BinOp(token::Or)) - && self.look_ahead(1, |t| t.can_begin_type()) - { - let mut pipes = vec![self.token.span]; - let mut types = vec![ty]; - loop { - if !self.eat(&token::BinOp(token::Or)) { - break; - } - pipes.push(self.prev_token.span); - types.push(self.parse_ty_common( - allow_plus, - allow_c_variadic, - recover_qpath, - recover_return_sign, - ty_generics, - recover_question_mark, - RecoverAnonEnum::No, - )?); - } - let mut err = self.struct_span_err(pipes, "anonymous enums are not supported"); - for ty in &types { - err.span_label(ty.span, ""); - } - err.help(&format!( - "create a named `enum` and use it here instead:\nenum Name {{\n{}\n}}", - types - .iter() - .enumerate() - .map(|(i, t)| format!( - " Variant{}({}),", - i + 1, // Lets not confuse people with zero-indexing :) - pprust::to_string(|s| s.print_type(&t)), - )) - .collect::>() - .join("\n"), - )); - err.emit(); - return Ok(self.mk_ty(lo.to(self.prev_token.span), TyKind::Err)); - } if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) } } diff --git a/tests/ui/parser/anon-enums-are-ambiguous.rs b/tests/ui/parser/anon-enums-are-ambiguous.rs new file mode 100644 index 0000000000000..b0173cf98e0a6 --- /dev/null +++ b/tests/ui/parser/anon-enums-are-ambiguous.rs @@ -0,0 +1,26 @@ +// check-pass + +macro_rules! test_expr { + ($expr:expr) => {}; +} + +macro_rules! test_ty { + ($a:ty | $b:ty) => {}; +} + +fn main() { + test_expr!(a as fn() -> B | C); + // Do not break the `|` operator. + + test_expr!(|_: fn() -> B| C | D); + // Do not break `-> Ret` in closure args. + + test_ty!(A | B); + // We can't support anon enums in arbitrary positions. + + test_ty!(fn() -> A | B); + // Don't break fn ptrs. + + test_ty!(impl Fn() -> A | B); + // Don't break parenthesized generics. +} diff --git a/tests/ui/parser/anon-enums.rs b/tests/ui/parser/anon-enums.rs deleted file mode 100644 index 56b8a3d43bedf..0000000000000 --- a/tests/ui/parser/anon-enums.rs +++ /dev/null @@ -1,17 +0,0 @@ -fn foo(x: bool | i32) -> i32 | f64 { -//~^ ERROR anonymous enums are not supported -//~| ERROR anonymous enums are not supported - match x { - x: i32 => x, //~ ERROR expected - true => 42., - false => 0.333, - } -} - -fn main() { - match foo(true) { - 42: i32 => (), //~ ERROR expected - _: f64 => (), //~ ERROR expected - x: i32 => (), //~ ERROR expected - } -} diff --git a/tests/ui/parser/anon-enums.stderr b/tests/ui/parser/anon-enums.stderr deleted file mode 100644 index 8415822566091..0000000000000 --- a/tests/ui/parser/anon-enums.stderr +++ /dev/null @@ -1,68 +0,0 @@ -error: anonymous enums are not supported - --> $DIR/anon-enums.rs:1:16 - | -LL | fn foo(x: bool | i32) -> i32 | f64 { - | ---- ^ --- - | - = help: create a named `enum` and use it here instead: - enum Name { - Variant1(bool), - Variant2(i32), - } - -error: anonymous enums are not supported - --> $DIR/anon-enums.rs:1:30 - | -LL | fn foo(x: bool | i32) -> i32 | f64 { - | --- ^ --- - | - = help: create a named `enum` and use it here instead: - enum Name { - Variant1(i32), - Variant2(f64), - } - -error: expected one of `@` or `|`, found `:` - --> $DIR/anon-enums.rs:5:10 - | -LL | x: i32 => x, - | ^ --- specifying the type of a pattern isn't supported - | | - | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | x::i32 => x, - | ~~ - -error: expected one of `...`, `..=`, `..`, or `|`, found `:` - --> $DIR/anon-enums.rs:13:11 - | -LL | 42: i32 => (), - | ^ --- specifying the type of a pattern isn't supported - | | - | expected one of `...`, `..=`, `..`, or `|` - -error: expected `|`, found `:` - --> $DIR/anon-enums.rs:14:10 - | -LL | _: f64 => (), - | ^ --- specifying the type of a pattern isn't supported - | | - | expected `|` - -error: expected one of `@` or `|`, found `:` - --> $DIR/anon-enums.rs:15:10 - | -LL | x: i32 => (), - | ^ --- specifying the type of a pattern isn't supported - | | - | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | x::i32 => (), - | ~~ - -error: aborting due to 6 previous errors - diff --git a/tests/ui/parser/fake-anon-enums-in-macros.rs b/tests/ui/parser/fake-anon-enums-in-macros.rs deleted file mode 100644 index 38fe8dee23829..0000000000000 --- a/tests/ui/parser/fake-anon-enums-in-macros.rs +++ /dev/null @@ -1,20 +0,0 @@ -// build-pass -macro_rules! check_ty { - ($Z:ty) => { compile_error!("triggered"); }; - ($X:ty | $Y:ty) => { $X }; -} - -macro_rules! check { - ($Z:ty) => { compile_error!("triggered"); }; - ($X:ty | $Y:ty) => { }; -} - -check! { i32 | u8 } - -fn foo(x: check_ty! { i32 | u8 }) -> check_ty! { i32 | u8 } { - x -} -fn main() { - let x: check_ty! { i32 | u8 } = 42; - let _: check_ty! { i32 | u8 } = foo(x); -} diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs index e1ea38f2795df..0b7b67496d6f3 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs @@ -68,6 +68,7 @@ fn main() { Foo:Bar::Baz => {} //~^ ERROR: expected one of //~| HELP: maybe write a path separator here + //~| ERROR: failed to resolve: `Bar` is a variant, not a module } match myfoo { Foo::Bar => {} diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr index 63b072ac4cdc6..2050a16beb349 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr @@ -2,118 +2,89 @@ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:17:12 | LL | Foo:Bar => {} - | ^--- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | Foo::Bar => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:23:17 | LL | qux::Foo:Bar => {} - | ^--- specifying the type of a pattern isn't supported + | ^ | | | expected one of 8 possible tokens - | -help: maybe write a path separator here - | -LL | qux::Foo::Bar => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:29:12 | LL | qux:Foo::Baz => {} - | ^-------- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | qux::Foo::Baz => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:35:12 | LL | qux: Foo::Baz if true => {} - | ^ -------- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | qux::Foo::Baz if true => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:40:15 | LL | if let Foo:Bar = f() { - | ^--- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | if let Foo::Bar = f() { - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:48:16 | LL | ref qux: Foo::Baz => {} - | ^ -------- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | ref qux::Foo::Baz => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:57:16 | LL | mut qux: Foo::Baz => {} - | ^ -------- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | mut qux::Foo::Baz => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:68:12 | LL | Foo:Bar::Baz => {} - | ^-------- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | Foo::Bar::Baz => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:74:12 + --> $DIR/issue-87086-colon-path-sep.rs:75:12 | LL | Foo:Bar => {} - | ^--- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error[E0433]: failed to resolve: `Bar` is a variant, not a module + --> $DIR/issue-87086-colon-path-sep.rs:68:13 | -help: maybe write a path separator here - | -LL | Foo::Bar => {} - | ~~ +LL | Foo:Bar::Baz => {} + | ^^^ `Bar` is a variant, not a module -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors +For more information about this error, try `rustc --explain E0433`.