From 2d824206655bfb26cb5eed43490ee396542b153e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 15 Jan 2023 22:36:46 +0000 Subject: [PATCH 1/4] Teach parser to understand fake anonymous enum syntax Parse `-> Ty | OtherTy`. Parse type ascription in top level patterns. --- compiler/rustc_ast/src/ast.rs | 3 + compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 4 +- compiler/rustc_ast_lowering/src/lib.rs | 1 + compiler/rustc_ast_pretty/src/pprust/state.rs | 3 + .../rustc_parse/src/parser/diagnostics.rs | 50 +++++++++--- compiler/rustc_parse/src/parser/pat.rs | 3 +- compiler/rustc_parse/src/parser/ty.rs | 67 ++++++++++++++- compiler/rustc_passes/src/hir_stats.rs | 1 + src/tools/rustfmt/src/types.rs | 4 +- tests/ui/parser/anon-enums.rs | 19 +++++ tests/ui/parser/anon-enums.stderr | 81 +++++++++++++++++++ .../issues/issue-87086-colon-path-sep.stderr | 72 ++++++++++++----- 13 files changed, 270 insertions(+), 40 deletions(-) create mode 100644 tests/ui/parser/anon-enums.rs create mode 100644 tests/ui/parser/anon-enums.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 7de594719ddc4..3aad51325dcd6 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2096,6 +2096,9 @@ pub enum TyKind { Err, /// Placeholder for a `va_list`. CVarArgs, + /// Placeholder for "anonymous enums", which don't exist, but keeping their + /// information around lets us produce better diagnostics. + AnonEnum(Vec>), } impl TyKind { diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 77f342d1eb322..894885cf0fea7 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -470,7 +470,7 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { vis.visit_fn_decl(decl); vis.visit_span(decl_span); } - TyKind::Tup(tys) => visit_vec(tys, |ty| vis.visit_ty(ty)), + TyKind::AnonEnum(tys) | TyKind::Tup(tys) => visit_vec(tys, |ty| vis.visit_ty(ty)), TyKind::Paren(ty) => vis.visit_ty(ty), TyKind::Path(qself, path) => { vis.visit_qself(qself); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e8823eff83afe..1ab70f0309c01 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -400,8 +400,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(tuple_element_types) => { - walk_list!(visitor, visit_ty, tuple_element_types); + TyKind::AnonEnum(tys) | TyKind::Tup(tys) => { + walk_list!(visitor, visit_ty, tys); } TyKind::BareFn(function_declaration) => { walk_list!(visitor, visit_generic_param, &function_declaration.generic_params); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 41d4a5679f1a0..a60d02002da33 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1235,6 +1235,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let kind = match &t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => hir::TyKind::Err, + TyKind::AnonEnum(_) => hir::TyKind::Err, TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Ref(region, mt) => { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 6a8064b0e874e..3f9b96a6158a1 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1041,6 +1041,9 @@ impl<'a> State<'a> { } self.pclose(); } + ast::TyKind::AnonEnum(elts) => { + self.strsep("|", false, Inconsistent, elts, |s, ty| s.print_type(ty)); + } ast::TyKind::Paren(typ) => { self.popen(); self.print_type(typ); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 4c918c6702ed9..07bd76dc39ba9 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2372,7 +2372,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( + pub(crate) fn maybe_recover_colon_colon_in_pat_typo_or_anon_enum( &mut self, mut first_pat: P, expected: Expected, @@ -2383,26 +2383,41 @@ 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 span = self.token.span; + let colon_span = self.token.span; // We only emit "unexpected `:`" error here if we can successfully parse the // whole pattern correctly in that case. - let snapshot = self.create_snapshot_for_diagnostic(); + let mut snapshot_pat = self.create_snapshot_for_diagnostic(); + let mut snapshot_type = self.create_snapshot_for_diagnostic(); // Create error for "unexpected `:`". match self.expected_one_of_not_found(&[], &[]) { Err(mut err) => { - self.bump(); // Skip the `:`. - match self.parse_pat_no_top_alt(expected) { + snapshot_pat.bump(); // Skip the `:`. + snapshot_type.bump(); // Skip the `:`. + match snapshot_pat.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. @@ -2466,8 +2481,8 @@ impl<'a> Parser<'a> { _ => {} } if show_sugg { - err.span_suggestion( - span, + err.span_suggestion_verbose( + colon_span.until(self.look_ahead(1, |t| t.span)), "maybe write a path separator here", "::", Applicability::MaybeIncorrect, @@ -2475,13 +2490,22 @@ impl<'a> Parser<'a> { } else { first_pat = self.mk_pat(new_span, PatKind::Wild); } - err.emit(); + self.restore_snapshot(snapshot_pat); } } + 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); + } + } + 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 e73a17ced7deb..e5411538eea22 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -116,7 +116,8 @@ 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(first_pat, expected); + first_pat = + self.maybe_recover_colon_colon_in_pat_typo_or_anon_enum(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 a6f702e542869..72994df6f9f46 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -11,6 +11,7 @@ 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::{pluralize, struct_span_err, Applicability, PResult}; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym, Ident}; @@ -43,17 +44,24 @@ pub(super) enum AllowPlus { No, } -#[derive(PartialEq)] +#[derive(PartialEq, Clone, Copy)] 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: @@ -86,7 +94,7 @@ impl RecoverReturnSign { } // Is `...` (`CVarArgs`) legal at this level of type parsing? -#[derive(PartialEq)] +#[derive(PartialEq, Clone, Copy)] enum AllowCVariadic { Yes, No, @@ -111,6 +119,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, + RecoverAnonEnum::No, ) } @@ -125,6 +134,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, Some(ty_params), RecoverQuestionMark::Yes, + RecoverAnonEnum::No, ) } @@ -139,6 +149,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, + RecoverAnonEnum::Yes, ) } @@ -156,6 +167,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, + RecoverAnonEnum::No, ) } @@ -169,6 +181,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::No, + RecoverAnonEnum::No, ) } @@ -180,6 +193,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::No, + RecoverAnonEnum::No, ) } @@ -192,6 +206,7 @@ impl<'a> Parser<'a> { RecoverReturnSign::OnlyFatArrow, None, RecoverQuestionMark::Yes, + RecoverAnonEnum::No, ) } @@ -211,6 +226,7 @@ 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) { @@ -232,6 +248,7 @@ impl<'a> Parser<'a> { recover_return_sign, None, RecoverQuestionMark::Yes, + RecoverAnonEnum::Yes, )?; FnRetTy::Ty(ty) } else { @@ -247,6 +264,7 @@ 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); @@ -325,14 +343,55 @@ impl<'a> Parser<'a> { let mut ty = self.mk_ty(span, kind); // Try to recover from use of `+` with incorrect priority. - if matches!(allow_plus, AllowPlus::Yes) { + if allow_plus == AllowPlus::Yes { self.maybe_recover_from_bad_type_plus(&ty)?; } else { self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty); } - if let RecoverQuestionMark::Yes = recover_question_mark { + if 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::AnonEnum(types))); + } if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) } } diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index b86d2316820ce..312bd8839e0d0 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -579,6 +579,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { [ Slice, Array, + AnonEnum, Ptr, Ref, BareFn, diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index c1991e8d2c808..f065ec680d724 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -839,7 +839,9 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::CVarArgs => Some("...".to_owned()), - ast::TyKind::Err => Some(context.snippet(self.span).to_owned()), + ast::TyKind::AnonEnum(_) | ast::TyKind::Err => { + Some(context.snippet(self.span).to_owned()) + } ast::TyKind::Typeof(ref anon_const) => rewrite_call( context, "typeof", diff --git a/tests/ui/parser/anon-enums.rs b/tests/ui/parser/anon-enums.rs new file mode 100644 index 0000000000000..a8b5e8359d996 --- /dev/null +++ b/tests/ui/parser/anon-enums.rs @@ -0,0 +1,19 @@ +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 + //~^ ERROR failed to resolve + true => 42., + false => 0.333, + } +} + +fn main() { + match foo(true) { + 42: i32 => (), //~ ERROR expected + _: f64 => (), //~ ERROR expected + x: i32 => (), //~ ERROR expected + //~^ ERROR failed to resolve + } +} diff --git a/tests/ui/parser/anon-enums.stderr b/tests/ui/parser/anon-enums.stderr new file mode 100644 index 0000000000000..4febf2df0dc72 --- /dev/null +++ b/tests/ui/parser/anon-enums.stderr @@ -0,0 +1,81 @@ +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:14:11 + | +LL | 42: i32 => (), + | ^ --- specifying the type of a pattern isn't supported + | | + | expected one of `...`, `..=`, `..`, or `|` + +error: expected `|`, found `:` + --> $DIR/anon-enums.rs:15:10 + | +LL | _: f64 => (), + | ^ --- specifying the type of a pattern isn't supported + | | + | expected `|` + +error: expected one of `@` or `|`, found `:` + --> $DIR/anon-enums.rs:16: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[E0433]: failed to resolve: use of undeclared crate or module `x` + --> $DIR/anon-enums.rs:5:9 + | +LL | x: i32 => x, + | ^ use of undeclared crate or module `x` + +error[E0433]: failed to resolve: use of undeclared crate or module `x` + --> $DIR/anon-enums.rs:16:9 + | +LL | x: i32 => (), + | ^ use of undeclared crate or module `x` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0433`. 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 2050a16beb349..ed05bfe8b0a32 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr @@ -2,82 +2,118 @@ 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: `::` + | +help: maybe write a path separator here + | +LL | Foo::Bar => {} + | ~~ 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: `::` + | +help: maybe write a path separator here + | +LL | qux::Foo::Bar => {} + | ~~ 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: `::` + | +help: maybe write a path separator here + | +LL | qux::Foo::Baz => {} + | ~~ 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: `::` + | +help: maybe write a path separator here + | +LL | qux::Foo::Baz if true => {} + | ~~ 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: `::` + | +help: maybe write a path separator here + | +LL | if let Foo::Bar = f() { + | ~~ 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: `::` + | +help: maybe write a path separator here + | +LL | ref qux::Foo::Baz => {} + | ~~ 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: `::` + | +help: maybe write a path separator here + | +LL | mut qux::Foo::Baz => {} + | ~~ 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: `::` + | +help: maybe write a path separator here + | +LL | Foo::Bar::Baz => {} + | ~~ error: expected one of `@` or `|`, found `:` --> $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: `::` + | +help: maybe write a path separator here + | +LL | Foo::Bar => {} + | ~~ error[E0433]: failed to resolve: `Bar` is a variant, not a module --> $DIR/issue-87086-colon-path-sep.rs:68:13 From c847a01a3b1f620c4fdb98c75805033e768975d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 17 Jan 2023 01:50:45 +0000 Subject: [PATCH 2/4] Emit fewer errors on patterns with possible type ascription --- .../rustc_parse/src/parser/diagnostics.rs | 2 ++ tests/ui/parser/anon-enums.rs | 2 -- tests/ui/parser/anon-enums.stderr | 21 ++++--------------- .../issues/issue-87086-colon-path-sep.rs | 1 - .../issues/issue-87086-colon-path-sep.stderr | 11 ++-------- 5 files changed, 8 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 07bd76dc39ba9..eda7046c748e5 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2500,6 +2500,8 @@ impl<'a> Parser<'a> { 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(); diff --git a/tests/ui/parser/anon-enums.rs b/tests/ui/parser/anon-enums.rs index a8b5e8359d996..56b8a3d43bedf 100644 --- a/tests/ui/parser/anon-enums.rs +++ b/tests/ui/parser/anon-enums.rs @@ -3,7 +3,6 @@ fn foo(x: bool | i32) -> i32 | f64 { //~| ERROR anonymous enums are not supported match x { x: i32 => x, //~ ERROR expected - //~^ ERROR failed to resolve true => 42., false => 0.333, } @@ -14,6 +13,5 @@ fn main() { 42: i32 => (), //~ ERROR expected _: f64 => (), //~ ERROR expected x: i32 => (), //~ ERROR expected - //~^ ERROR failed to resolve } } diff --git a/tests/ui/parser/anon-enums.stderr b/tests/ui/parser/anon-enums.stderr index 4febf2df0dc72..8415822566091 100644 --- a/tests/ui/parser/anon-enums.stderr +++ b/tests/ui/parser/anon-enums.stderr @@ -36,7 +36,7 @@ LL | x::i32 => x, | ~~ error: expected one of `...`, `..=`, `..`, or `|`, found `:` - --> $DIR/anon-enums.rs:14:11 + --> $DIR/anon-enums.rs:13:11 | LL | 42: i32 => (), | ^ --- specifying the type of a pattern isn't supported @@ -44,7 +44,7 @@ LL | 42: i32 => (), | expected one of `...`, `..=`, `..`, or `|` error: expected `|`, found `:` - --> $DIR/anon-enums.rs:15:10 + --> $DIR/anon-enums.rs:14:10 | LL | _: f64 => (), | ^ --- specifying the type of a pattern isn't supported @@ -52,7 +52,7 @@ LL | _: f64 => (), | expected `|` error: expected one of `@` or `|`, found `:` - --> $DIR/anon-enums.rs:16:10 + --> $DIR/anon-enums.rs:15:10 | LL | x: i32 => (), | ^ --- specifying the type of a pattern isn't supported @@ -64,18 +64,5 @@ help: maybe write a path separator here LL | x::i32 => (), | ~~ -error[E0433]: failed to resolve: use of undeclared crate or module `x` - --> $DIR/anon-enums.rs:5:9 - | -LL | x: i32 => x, - | ^ use of undeclared crate or module `x` - -error[E0433]: failed to resolve: use of undeclared crate or module `x` - --> $DIR/anon-enums.rs:16:9 - | -LL | x: i32 => (), - | ^ use of undeclared crate or module `x` - -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0433`. 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 0b7b67496d6f3..e1ea38f2795df 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs @@ -68,7 +68,6 @@ 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 ed05bfe8b0a32..63b072ac4cdc6 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr @@ -103,7 +103,7 @@ LL | Foo::Bar::Baz => {} | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:75:12 + --> $DIR/issue-87086-colon-path-sep.rs:74:12 | LL | Foo:Bar => {} | ^--- specifying the type of a pattern isn't supported @@ -115,12 +115,5 @@ help: maybe write a path separator here LL | Foo::Bar => {} | ~~ -error[E0433]: failed to resolve: `Bar` is a variant, not a module - --> $DIR/issue-87086-colon-path-sep.rs:68:13 - | -LL | Foo:Bar::Baz => {} - | ^^^ `Bar` is a variant, not a module - -error: aborting due to 10 previous errors +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0433`. From 12d18e403139eeeeb339e8611b2bed4910864edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 17 Jan 2023 17:02:09 +0000 Subject: [PATCH 3/4] Ensure macros are not affected --- tests/ui/parser/fake-anon-enums-in-macros.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/ui/parser/fake-anon-enums-in-macros.rs diff --git a/tests/ui/parser/fake-anon-enums-in-macros.rs b/tests/ui/parser/fake-anon-enums-in-macros.rs new file mode 100644 index 0000000000000..38fe8dee23829 --- /dev/null +++ b/tests/ui/parser/fake-anon-enums-in-macros.rs @@ -0,0 +1,20 @@ +// 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); +} From 020cca8d36cb678e3ddc2ead41364be314d19e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 23 Jan 2023 14:29:53 +0000 Subject: [PATCH 4/4] review comment: Remove AST AnonTy --- compiler/rustc_ast/src/ast.rs | 3 --- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 1 - compiler/rustc_ast_pretty/src/pprust/state.rs | 3 --- compiler/rustc_parse/src/parser/ty.rs | 2 +- compiler/rustc_passes/src/hir_stats.rs | 1 - src/tools/rustfmt/src/types.rs | 4 +--- 8 files changed, 4 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 3aad51325dcd6..7de594719ddc4 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2096,9 +2096,6 @@ pub enum TyKind { Err, /// Placeholder for a `va_list`. CVarArgs, - /// Placeholder for "anonymous enums", which don't exist, but keeping their - /// information around lets us produce better diagnostics. - AnonEnum(Vec>), } impl TyKind { diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 894885cf0fea7..77f342d1eb322 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -470,7 +470,7 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { vis.visit_fn_decl(decl); vis.visit_span(decl_span); } - TyKind::AnonEnum(tys) | TyKind::Tup(tys) => visit_vec(tys, |ty| vis.visit_ty(ty)), + TyKind::Tup(tys) => visit_vec(tys, |ty| vis.visit_ty(ty)), TyKind::Paren(ty) => vis.visit_ty(ty), TyKind::Path(qself, path) => { vis.visit_qself(qself); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 1ab70f0309c01..feb5187536ffa 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -400,7 +400,7 @@ 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::AnonEnum(tys) | TyKind::Tup(tys) => { + TyKind::Tup(tys) => { walk_list!(visitor, visit_ty, tys); } TyKind::BareFn(function_declaration) => { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a60d02002da33..41d4a5679f1a0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1235,7 +1235,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let kind = match &t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => hir::TyKind::Err, - TyKind::AnonEnum(_) => hir::TyKind::Err, TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Ref(region, mt) => { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 3f9b96a6158a1..6a8064b0e874e 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1041,9 +1041,6 @@ impl<'a> State<'a> { } self.pclose(); } - ast::TyKind::AnonEnum(elts) => { - self.strsep("|", false, Inconsistent, elts, |s, ty| s.print_type(ty)); - } ast::TyKind::Paren(typ) => { self.popen(); self.print_type(typ); diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 72994df6f9f46..43e6eac438ba5 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -390,7 +390,7 @@ impl<'a> Parser<'a> { .join("\n"), )); err.emit(); - return Ok(self.mk_ty(lo.to(self.prev_token.span), TyKind::AnonEnum(types))); + 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/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 312bd8839e0d0..b86d2316820ce 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -579,7 +579,6 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { [ Slice, Array, - AnonEnum, Ptr, Ref, BareFn, diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index f065ec680d724..c1991e8d2c808 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -839,9 +839,7 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::CVarArgs => Some("...".to_owned()), - ast::TyKind::AnonEnum(_) | ast::TyKind::Err => { - Some(context.snippet(self.span).to_owned()) - } + ast::TyKind::Err => Some(context.snippet(self.span).to_owned()), ast::TyKind::Typeof(ref anon_const) => rewrite_call( context, "typeof",