Skip to content

Commit 93e9dac

Browse files
Rollup merge of rust-lang#107478 - compiler-errors:anon-enum-tys-are-ambiguous, r=estebank
Revert "Teach parser to understand fake anonymous enum syntax" and related commits anonymous enum types are currently ambiguous in positions like: * `|` operator: `a as fn() -> B | C` * closure args: `|_: as fn() -> A | B` I first tried to thread around `RecoverAnonEnum` into all these positions, but the resulting complexity in the compiler is IMO not worth it, or at least worth a bit more thinking time. In the mean time, let's revert this syntax for now, so we can go back to the drawing board. Fixes rust-lang#107461 cc: `@estebank` `@cjgillot` rust-lang#106960 --- ### Squashed revert commits: Revert "review comment: Remove AST AnonTy" This reverts commit 020cca8. Revert "Ensure macros are not affected" This reverts commit 12d18e4. Revert "Emit fewer errors on patterns with possible type ascription" This reverts commit c847a01. Revert "Teach parser to understand fake anonymous enum syntax" This reverts commit 2d82420.
2 parents 9d959ea + 250f530 commit 93e9dac

File tree

10 files changed

+72
-265
lines changed

10 files changed

+72
-265
lines changed

compiler/rustc_ast/src/visit.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -403,8 +403,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
403403
walk_list!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref);
404404
visitor.visit_ty(&mutable_type.ty)
405405
}
406-
TyKind::Tup(tys) => {
407-
walk_list!(visitor, visit_ty, tys);
406+
TyKind::Tup(tuple_element_types) => {
407+
walk_list!(visitor, visit_ty, tuple_element_types);
408408
}
409409
TyKind::BareFn(function_declaration) => {
410410
walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);

compiler/rustc_parse/src/parser/diagnostics.rs

+13-39
Original file line numberDiff line numberDiff line change
@@ -2394,7 +2394,7 @@ impl<'a> Parser<'a> {
23942394

23952395
/// Some special error handling for the "top-level" patterns in a match arm,
23962396
/// `for` loop, `let`, &c. (in contrast to subpatterns within such).
2397-
pub(crate) fn maybe_recover_colon_colon_in_pat_typo_or_anon_enum(
2397+
pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
23982398
&mut self,
23992399
mut first_pat: P<Pat>,
24002400
expected: Expected,
@@ -2405,41 +2405,26 @@ impl<'a> Parser<'a> {
24052405
if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..))
24062406
|| !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
24072407
{
2408-
let mut snapshot_type = self.create_snapshot_for_diagnostic();
2409-
snapshot_type.bump(); // `:`
2410-
match snapshot_type.parse_ty() {
2411-
Err(inner_err) => {
2412-
inner_err.cancel();
2413-
}
2414-
Ok(ty) => {
2415-
let Err(mut err) = self.expected_one_of_not_found(&[], &[]) else {
2416-
return first_pat;
2417-
};
2418-
err.span_label(ty.span, "specifying the type of a pattern isn't supported");
2419-
self.restore_snapshot(snapshot_type);
2420-
let span = first_pat.span.to(ty.span);
2421-
first_pat = self.mk_pat(span, PatKind::Wild);
2422-
err.emit();
2423-
}
2424-
}
24252408
return first_pat;
24262409
}
24272410
// The pattern looks like it might be a path with a `::` -> `:` typo:
24282411
// `match foo { bar:baz => {} }`
2429-
let colon_span = self.token.span;
2412+
let span = self.token.span;
24302413
// We only emit "unexpected `:`" error here if we can successfully parse the
24312414
// whole pattern correctly in that case.
2432-
let mut snapshot_pat = self.create_snapshot_for_diagnostic();
2433-
let mut snapshot_type = self.create_snapshot_for_diagnostic();
2415+
let snapshot = self.create_snapshot_for_diagnostic();
24342416

24352417
// Create error for "unexpected `:`".
24362418
match self.expected_one_of_not_found(&[], &[]) {
24372419
Err(mut err) => {
2438-
snapshot_pat.bump(); // Skip the `:`.
2439-
snapshot_type.bump(); // Skip the `:`.
2440-
match snapshot_pat.parse_pat_no_top_alt(expected) {
2420+
self.bump(); // Skip the `:`.
2421+
match self.parse_pat_no_top_alt(expected) {
24412422
Err(inner_err) => {
2423+
// Carry on as if we had not done anything, callers will emit a
2424+
// reasonable error.
24422425
inner_err.cancel();
2426+
err.cancel();
2427+
self.restore_snapshot(snapshot);
24432428
}
24442429
Ok(mut pat) => {
24452430
// We've parsed the rest of the pattern.
@@ -2503,33 +2488,22 @@ impl<'a> Parser<'a> {
25032488
_ => {}
25042489
}
25052490
if show_sugg {
2506-
err.span_suggestion_verbose(
2507-
colon_span.until(self.look_ahead(1, |t| t.span)),
2491+
err.span_suggestion(
2492+
span,
25082493
"maybe write a path separator here",
25092494
"::",
25102495
Applicability::MaybeIncorrect,
25112496
);
25122497
} else {
25132498
first_pat = self.mk_pat(new_span, PatKind::Wild);
25142499
}
2515-
self.restore_snapshot(snapshot_pat);
2500+
err.emit();
25162501
}
25172502
}
2518-
match snapshot_type.parse_ty() {
2519-
Err(inner_err) => {
2520-
inner_err.cancel();
2521-
}
2522-
Ok(ty) => {
2523-
err.span_label(ty.span, "specifying the type of a pattern isn't supported");
2524-
self.restore_snapshot(snapshot_type);
2525-
let new_span = first_pat.span.to(ty.span);
2526-
first_pat = self.mk_pat(new_span, PatKind::Wild);
2527-
}
2528-
}
2529-
err.emit();
25302503
}
25312504
_ => {
25322505
// Carry on as if we had not done anything. This should be unreachable.
2506+
self.restore_snapshot(snapshot);
25332507
}
25342508
};
25352509
first_pat

compiler/rustc_parse/src/parser/pat.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ impl<'a> Parser<'a> {
118118

119119
// Check if the user wrote `foo:bar` instead of `foo::bar`.
120120
if ra == RecoverColon::Yes {
121-
first_pat =
122-
self.maybe_recover_colon_colon_in_pat_typo_or_anon_enum(first_pat, expected);
121+
first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, expected);
123122
}
124123

125124
if let Some(leading_vert_span) = leading_vert_span {

compiler/rustc_parse/src/parser/ty.rs

+3-62
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use rustc_ast::{
1111
self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime,
1212
MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
1313
};
14-
use rustc_ast_pretty::pprust;
1514
use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
1615
use rustc_span::source_map::Span;
1716
use rustc_span::symbol::{kw, sym, Ident};
@@ -44,24 +43,17 @@ pub(super) enum AllowPlus {
4443
No,
4544
}
4645

47-
#[derive(PartialEq, Clone, Copy)]
46+
#[derive(PartialEq)]
4847
pub(super) enum RecoverQPath {
4948
Yes,
5049
No,
5150
}
5251

53-
#[derive(PartialEq, Clone, Copy)]
5452
pub(super) enum RecoverQuestionMark {
5553
Yes,
5654
No,
5755
}
5856

59-
#[derive(PartialEq, Clone, Copy)]
60-
pub(super) enum RecoverAnonEnum {
61-
Yes,
62-
No,
63-
}
64-
6557
/// Signals whether parsing a type should recover `->`.
6658
///
6759
/// More specifically, when parsing a function like:
@@ -94,7 +86,7 @@ impl RecoverReturnSign {
9486
}
9587

9688
// Is `...` (`CVarArgs`) legal at this level of type parsing?
97-
#[derive(PartialEq, Clone, Copy)]
89+
#[derive(PartialEq)]
9890
enum AllowCVariadic {
9991
Yes,
10092
No,
@@ -119,7 +111,6 @@ impl<'a> Parser<'a> {
119111
RecoverReturnSign::Yes,
120112
None,
121113
RecoverQuestionMark::Yes,
122-
RecoverAnonEnum::No,
123114
)
124115
}
125116

@@ -134,7 +125,6 @@ impl<'a> Parser<'a> {
134125
RecoverReturnSign::Yes,
135126
Some(ty_params),
136127
RecoverQuestionMark::Yes,
137-
RecoverAnonEnum::No,
138128
)
139129
}
140130

@@ -149,7 +139,6 @@ impl<'a> Parser<'a> {
149139
RecoverReturnSign::Yes,
150140
None,
151141
RecoverQuestionMark::Yes,
152-
RecoverAnonEnum::Yes,
153142
)
154143
}
155144

@@ -167,7 +156,6 @@ impl<'a> Parser<'a> {
167156
RecoverReturnSign::Yes,
168157
None,
169158
RecoverQuestionMark::Yes,
170-
RecoverAnonEnum::No,
171159
)
172160
}
173161

@@ -181,7 +169,6 @@ impl<'a> Parser<'a> {
181169
RecoverReturnSign::Yes,
182170
None,
183171
RecoverQuestionMark::No,
184-
RecoverAnonEnum::No,
185172
)
186173
}
187174

@@ -193,7 +180,6 @@ impl<'a> Parser<'a> {
193180
RecoverReturnSign::Yes,
194181
None,
195182
RecoverQuestionMark::No,
196-
RecoverAnonEnum::No,
197183
)
198184
}
199185

@@ -206,7 +192,6 @@ impl<'a> Parser<'a> {
206192
RecoverReturnSign::OnlyFatArrow,
207193
None,
208194
RecoverQuestionMark::Yes,
209-
RecoverAnonEnum::No,
210195
)
211196
}
212197

@@ -226,7 +211,6 @@ impl<'a> Parser<'a> {
226211
recover_return_sign,
227212
None,
228213
RecoverQuestionMark::Yes,
229-
RecoverAnonEnum::Yes,
230214
)?;
231215
FnRetTy::Ty(ty)
232216
} else if recover_return_sign.can_recover(&self.token.kind) {
@@ -248,7 +232,6 @@ impl<'a> Parser<'a> {
248232
recover_return_sign,
249233
None,
250234
RecoverQuestionMark::Yes,
251-
RecoverAnonEnum::Yes,
252235
)?;
253236
FnRetTy::Ty(ty)
254237
} else {
@@ -264,7 +247,6 @@ impl<'a> Parser<'a> {
264247
recover_return_sign: RecoverReturnSign,
265248
ty_generics: Option<&Generics>,
266249
recover_question_mark: RecoverQuestionMark,
267-
recover_anon_enum: RecoverAnonEnum,
268250
) -> PResult<'a, P<Ty>> {
269251
let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
270252
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
@@ -348,50 +330,9 @@ impl<'a> Parser<'a> {
348330
AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
349331
AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
350332
}
351-
if RecoverQuestionMark::Yes == recover_question_mark {
333+
if let RecoverQuestionMark::Yes = recover_question_mark {
352334
ty = self.maybe_recover_from_question_mark(ty);
353335
}
354-
if recover_anon_enum == RecoverAnonEnum::Yes
355-
&& self.check_noexpect(&token::BinOp(token::Or))
356-
&& self.look_ahead(1, |t| t.can_begin_type())
357-
{
358-
let mut pipes = vec![self.token.span];
359-
let mut types = vec![ty];
360-
loop {
361-
if !self.eat(&token::BinOp(token::Or)) {
362-
break;
363-
}
364-
pipes.push(self.prev_token.span);
365-
types.push(self.parse_ty_common(
366-
allow_plus,
367-
allow_c_variadic,
368-
recover_qpath,
369-
recover_return_sign,
370-
ty_generics,
371-
recover_question_mark,
372-
RecoverAnonEnum::No,
373-
)?);
374-
}
375-
let mut err = self.struct_span_err(pipes, "anonymous enums are not supported");
376-
for ty in &types {
377-
err.span_label(ty.span, "");
378-
}
379-
err.help(&format!(
380-
"create a named `enum` and use it here instead:\nenum Name {{\n{}\n}}",
381-
types
382-
.iter()
383-
.enumerate()
384-
.map(|(i, t)| format!(
385-
" Variant{}({}),",
386-
i + 1, // Lets not confuse people with zero-indexing :)
387-
pprust::to_string(|s| s.print_type(&t)),
388-
))
389-
.collect::<Vec<_>>()
390-
.join("\n"),
391-
));
392-
err.emit();
393-
return Ok(self.mk_ty(lo.to(self.prev_token.span), TyKind::Err));
394-
}
395336
if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
396337
}
397338

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// check-pass
2+
3+
macro_rules! test_expr {
4+
($expr:expr) => {};
5+
}
6+
7+
macro_rules! test_ty {
8+
($a:ty | $b:ty) => {};
9+
}
10+
11+
fn main() {
12+
test_expr!(a as fn() -> B | C);
13+
// Do not break the `|` operator.
14+
15+
test_expr!(|_: fn() -> B| C | D);
16+
// Do not break `-> Ret` in closure args.
17+
18+
test_ty!(A | B);
19+
// We can't support anon enums in arbitrary positions.
20+
21+
test_ty!(fn() -> A | B);
22+
// Don't break fn ptrs.
23+
24+
test_ty!(impl Fn() -> A | B);
25+
// Don't break parenthesized generics.
26+
}

tests/ui/parser/anon-enums.rs

-17
This file was deleted.

0 commit comments

Comments
 (0)