From a65937ea9f055b50aa9dd47f21695481b61e2dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 18 Oct 2023 21:26:33 +0000 Subject: [PATCH 1/2] Silence resolve errors if there were parse errors Fix #74863. --- compiler/rustc_parse/src/parser/item.rs | 13 ++++++-- compiler/rustc_parse/src/parser/mod.rs | 1 + compiler/rustc_parse/src/parser/pat.rs | 2 ++ .../rustc_resolve/src/late/diagnostics.rs | 4 +++ compiler/rustc_session/src/parse.rs | 4 +++ tests/ui/associated-consts/issue-105330.rs | 2 +- .../ui/associated-consts/issue-105330.stderr | 10 ++---- tests/ui/parser/fn-field-parse-error-ice.rs | 1 - .../ui/parser/fn-field-parse-error-ice.stderr | 9 +----- ...id-resolve-errors-caused-by-parse-error.rs | 18 +++++++++++ ...esolve-errors-caused-by-parse-error.stderr | 18 +++++++++++ .../recover-assoc-const-constraint.rs | 0 .../recover-assoc-const-constraint.stderr | 0 .../recover-assoc-eq-missing-term.rs | 0 .../recover-assoc-eq-missing-term.stderr | 0 .../recover-assoc-lifetime-constraint.rs | 0 .../recover-assoc-lifetime-constraint.stderr | 0 .../recover-const-async-fn-ptr.rs | 0 .../recover-const-async-fn-ptr.stderr | 0 tests/ui/parser/{ => recover}/recover-enum.rs | 0 .../parser/{ => recover}/recover-enum.stderr | 0 .../ui/parser/{ => recover}/recover-enum2.rs | 0 .../parser/{ => recover}/recover-enum2.stderr | 0 ...a-angle-brackets-in-struct-with-a-field.rs | 0 ...gle-brackets-in-struct-with-a-field.stderr | 0 .../recover-field-extra-angle-brackets.rs | 0 .../recover-field-extra-angle-brackets.stderr | 0 .../{ => recover}/recover-field-semi.rs | 0 .../{ => recover}/recover-field-semi.stderr | 0 .../recover-fn-ptr-with-generics.rs | 2 -- .../recover-fn-ptr-with-generics.stderr | 31 ++++++------------- .../recover-fn-trait-from-fn-kw.rs | 0 .../recover-fn-trait-from-fn-kw.stderr | 0 .../recover-for-loop-parens-around-head.rs | 0 ...recover-for-loop-parens-around-head.stderr | 0 .../{ => recover}/recover-from-bad-variant.rs | 0 .../recover-from-bad-variant.stderr | 0 .../{ => recover}/recover-from-homoglyph.rs | 0 .../recover-from-homoglyph.stderr | 0 .../recover-labeled-non-block-expr.fixed | 0 .../recover-labeled-non-block-expr.rs | 0 .../recover-labeled-non-block-expr.stderr | 0 .../recover-missing-semi-before-item.fixed | 0 .../recover-missing-semi-before-item.rs | 0 .../recover-missing-semi-before-item.stderr | 0 .../{ => recover}/recover-missing-semi.rs | 0 .../{ => recover}/recover-missing-semi.stderr | 0 .../recover-quantified-closure.rs | 0 .../recover-quantified-closure.stderr | 0 .../{ => recover}/recover-range-pats.rs | 0 .../{ => recover}/recover-range-pats.stderr | 0 .../{ => recover}/recover-ref-dyn-mut.rs | 0 .../{ => recover}/recover-ref-dyn-mut.stderr | 0 .../ui/parser/{ => recover}/recover-struct.rs | 0 .../{ => recover}/recover-struct.stderr | 0 .../parser/{ => recover}/recover-tuple-pat.rs | 0 .../{ => recover}/recover-tuple-pat.stderr | 0 .../ui/parser/{ => recover}/recover-tuple.rs | 0 .../parser/{ => recover}/recover-tuple.stderr | 0 .../recover-unticked-labels.fixed | 0 .../{ => recover}/recover-unticked-labels.rs | 0 .../recover-unticked-labels.stderr | 0 ...re-clause-before-tuple-struct-body-0.fixed | 0 ...where-clause-before-tuple-struct-body-0.rs | 0 ...e-clause-before-tuple-struct-body-0.stderr | 0 ...where-clause-before-tuple-struct-body-1.rs | 0 ...e-clause-before-tuple-struct-body-1.stderr | 0 67 files changed, 71 insertions(+), 44 deletions(-) create mode 100644 tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.rs create mode 100644 tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.stderr rename tests/ui/parser/{ => recover}/recover-assoc-const-constraint.rs (100%) rename tests/ui/parser/{ => recover}/recover-assoc-const-constraint.stderr (100%) rename tests/ui/parser/{ => recover}/recover-assoc-eq-missing-term.rs (100%) rename tests/ui/parser/{ => recover}/recover-assoc-eq-missing-term.stderr (100%) rename tests/ui/parser/{ => recover}/recover-assoc-lifetime-constraint.rs (100%) rename tests/ui/parser/{ => recover}/recover-assoc-lifetime-constraint.stderr (100%) rename tests/ui/parser/{ => recover}/recover-const-async-fn-ptr.rs (100%) rename tests/ui/parser/{ => recover}/recover-const-async-fn-ptr.stderr (100%) rename tests/ui/parser/{ => recover}/recover-enum.rs (100%) rename tests/ui/parser/{ => recover}/recover-enum.stderr (100%) rename tests/ui/parser/{ => recover}/recover-enum2.rs (100%) rename tests/ui/parser/{ => recover}/recover-enum2.stderr (100%) rename tests/ui/parser/{ => recover}/recover-field-extra-angle-brackets-in-struct-with-a-field.rs (100%) rename tests/ui/parser/{ => recover}/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr (100%) rename tests/ui/parser/{ => recover}/recover-field-extra-angle-brackets.rs (100%) rename tests/ui/parser/{ => recover}/recover-field-extra-angle-brackets.stderr (100%) rename tests/ui/parser/{ => recover}/recover-field-semi.rs (100%) rename tests/ui/parser/{ => recover}/recover-field-semi.stderr (100%) rename tests/ui/parser/{ => recover}/recover-fn-ptr-with-generics.rs (91%) rename tests/ui/parser/{ => recover}/recover-fn-ptr-with-generics.stderr (73%) rename tests/ui/parser/{ => recover}/recover-fn-trait-from-fn-kw.rs (100%) rename tests/ui/parser/{ => recover}/recover-fn-trait-from-fn-kw.stderr (100%) rename tests/ui/parser/{ => recover}/recover-for-loop-parens-around-head.rs (100%) rename tests/ui/parser/{ => recover}/recover-for-loop-parens-around-head.stderr (100%) rename tests/ui/parser/{ => recover}/recover-from-bad-variant.rs (100%) rename tests/ui/parser/{ => recover}/recover-from-bad-variant.stderr (100%) rename tests/ui/parser/{ => recover}/recover-from-homoglyph.rs (100%) rename tests/ui/parser/{ => recover}/recover-from-homoglyph.stderr (100%) rename tests/ui/parser/{ => recover}/recover-labeled-non-block-expr.fixed (100%) rename tests/ui/parser/{ => recover}/recover-labeled-non-block-expr.rs (100%) rename tests/ui/parser/{ => recover}/recover-labeled-non-block-expr.stderr (100%) rename tests/ui/parser/{ => recover}/recover-missing-semi-before-item.fixed (100%) rename tests/ui/parser/{ => recover}/recover-missing-semi-before-item.rs (100%) rename tests/ui/parser/{ => recover}/recover-missing-semi-before-item.stderr (100%) rename tests/ui/parser/{ => recover}/recover-missing-semi.rs (100%) rename tests/ui/parser/{ => recover}/recover-missing-semi.stderr (100%) rename tests/ui/parser/{ => recover}/recover-quantified-closure.rs (100%) rename tests/ui/parser/{ => recover}/recover-quantified-closure.stderr (100%) rename tests/ui/parser/{ => recover}/recover-range-pats.rs (100%) rename tests/ui/parser/{ => recover}/recover-range-pats.stderr (100%) rename tests/ui/parser/{ => recover}/recover-ref-dyn-mut.rs (100%) rename tests/ui/parser/{ => recover}/recover-ref-dyn-mut.stderr (100%) rename tests/ui/parser/{ => recover}/recover-struct.rs (100%) rename tests/ui/parser/{ => recover}/recover-struct.stderr (100%) rename tests/ui/parser/{ => recover}/recover-tuple-pat.rs (100%) rename tests/ui/parser/{ => recover}/recover-tuple-pat.stderr (100%) rename tests/ui/parser/{ => recover}/recover-tuple.rs (100%) rename tests/ui/parser/{ => recover}/recover-tuple.stderr (100%) rename tests/ui/parser/{ => recover}/recover-unticked-labels.fixed (100%) rename tests/ui/parser/{ => recover}/recover-unticked-labels.rs (100%) rename tests/ui/parser/{ => recover}/recover-unticked-labels.stderr (100%) rename tests/ui/parser/{ => recover}/recover-where-clause-before-tuple-struct-body-0.fixed (100%) rename tests/ui/parser/{ => recover}/recover-where-clause-before-tuple-struct-body-0.rs (100%) rename tests/ui/parser/{ => recover}/recover-where-clause-before-tuple-struct-body-0.stderr (100%) rename tests/ui/parser/{ => recover}/recover-where-clause-before-tuple-struct-body-1.rs (100%) rename tests/ui/parser/{ => recover}/recover-where-clause-before-tuple-struct-body-1.stderr (100%) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 982f601c0d5a2..ebfc4e5850ac1 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -152,7 +152,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let mut def = self.parse_defaultness(); - let kind = self.parse_item_kind( + let kind = match self.parse_item_kind( &mut attrs, mac_allowed, lo, @@ -160,7 +160,13 @@ impl<'a> Parser<'a> { &mut def, fn_parse_mode, Case::Sensitive, - )?; + ) { + Ok(kind) => kind, + Err(err) => { + self.sess.parse_errors_encountered.set(true); + return Err(err); + } + }; if let Some((ident, kind)) = kind { self.error_on_unconsumed_default(def, &kind); let span = lo.to(self.prev_token.span); @@ -726,6 +732,7 @@ impl<'a> Parser<'a> { let is_let = self.token.is_keyword(kw::Let); let mut err = self.struct_span_err(non_item_span, "non-item in item list"); + self.sess.parse_errors_encountered.set(true); self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes); if is_let { err.span_suggestion( @@ -752,6 +759,7 @@ impl<'a> Parser<'a> { } Ok(Some(item)) => items.extend(item), Err(mut err) => { + self.sess.parse_errors_encountered.set(true); self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes); err.span_label(open_brace_span, "while parsing this item list starting here") .span_label(self.prev_token.span, "the item list ends here") @@ -1618,6 +1626,7 @@ impl<'a> Parser<'a> { while self.token != token::CloseDelim(Delimiter::Brace) { let field = self.parse_field_def(adt_ty).map_err(|e| { self.consume_block(Delimiter::Brace, ConsumeClosingDelim::No); + self.sess.parse_errors_encountered.set(true); recovered = true; e }); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 597303cae73e2..3e5bcbadb80e6 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1459,6 +1459,7 @@ pub(crate) fn make_unclosed_delims_error( if let Some(sp) = unmatched.unclosed_span { spans.push(sp); }; + sess.parse_errors_encountered.set(true); let err = MismatchedClosingDelimiter { spans, delimiter: pprust::token_kind_to_string(&token::CloseDelim(found_delim)).to_string(), diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 3e4e927891072..7af0a7e5dcb9b 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -870,6 +870,7 @@ impl<'a> Parser<'a> { let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| { e.span_label(path.span, "while parsing the fields for this pattern"); e.emit(); + self.sess.parse_errors_encountered.set(true); self.recover_stmt(); (ThinVec::new(), true) }); @@ -1104,6 +1105,7 @@ impl<'a> Parser<'a> { } } } + self.sess.parse_errors_encountered.set(true); err.emit(); } Ok((fields, etc)) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a5f8f61f3db50..d47e0f37983af 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -430,6 +430,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { base_error.msg.clone(), code, ); + if self.r.tcx.sess.parse_sess.parse_errors_encountered.get() { + // We've encountered parse errors that can cause resolution errors, so we silence them. + err.delay_as_bug(); + } self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span); diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index abb0ab5630c13..c14ec51603323 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -23,6 +23,7 @@ use rustc_span::source_map::{FilePathMapping, SourceMap}; use rustc_span::{Span, Symbol}; use rustc_ast::attr::AttrIdGenerator; +use std::cell::Cell; use std::str; /// The set of keys (and, optionally, values) that define the compilation @@ -222,6 +223,8 @@ pub struct ParseSess { pub proc_macro_quoted_spans: AppendOnlyVec, /// Used to generate new `AttrId`s. Every `AttrId` is unique. pub attr_id_generator: AttrIdGenerator, + /// Whether any parse errors have occurred. Used to silence resolution errors. + pub parse_errors_encountered: Cell, } impl ParseSess { @@ -252,6 +255,7 @@ impl ParseSess { assume_incomplete_release: false, proc_macro_quoted_spans: Default::default(), attr_id_generator: AttrIdGenerator::new(), + parse_errors_encountered: Cell::new(false), } } diff --git a/tests/ui/associated-consts/issue-105330.rs b/tests/ui/associated-consts/issue-105330.rs index 86e45f10b0e16..1d63af3c256f4 100644 --- a/tests/ui/associated-consts/issue-105330.rs +++ b/tests/ui/associated-consts/issue-105330.rs @@ -3,7 +3,7 @@ pub trait TraitWAssocConst { } pub struct Demo {} -impl TraitWAssocConst for impl Demo { //~ ERROR E0404 +impl TraitWAssocConst for impl Demo { //~^ ERROR E0562 pubconst A: str = 32; //~ ERROR expected one of } diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr index 200856caa2518..fcf77078fe21a 100644 --- a/tests/ui/associated-consts/issue-105330.stderr +++ b/tests/ui/associated-consts/issue-105330.stderr @@ -9,12 +9,6 @@ LL | pubconst A: str = 32; LL | } | - the item list ends here -error[E0404]: expected trait, found struct `Demo` - --> $DIR/issue-105330.rs:6:32 - | -LL | impl TraitWAssocConst for impl Demo { - | ^^^^ not a trait - error[E0658]: associated const equality is incomplete --> $DIR/issue-105330.rs:11:28 | @@ -117,7 +111,7 @@ note: required by a bound in `foo` LL | fn foo>() { | ^^^^ required by this bound in `foo` -error: aborting due to 11 previous errors +error: aborting due to 10 previous errors -Some errors have detailed explanations: E0131, E0271, E0277, E0404, E0562, E0618, E0658. +Some errors have detailed explanations: E0131, E0271, E0277, E0562, E0618, E0658. For more information about an error, try `rustc --explain E0131`. diff --git a/tests/ui/parser/fn-field-parse-error-ice.rs b/tests/ui/parser/fn-field-parse-error-ice.rs index 188257ea53a31..4b9bd55362268 100644 --- a/tests/ui/parser/fn-field-parse-error-ice.rs +++ b/tests/ui/parser/fn-field-parse-error-ice.rs @@ -4,7 +4,6 @@ struct Baz { inner : dyn fn () //~^ ERROR expected `,`, or `}`, found keyword `fn` //~| ERROR expected identifier, found keyword `fn` - //~| ERROR cannot find type `dyn` in this scope } fn main() {} diff --git a/tests/ui/parser/fn-field-parse-error-ice.stderr b/tests/ui/parser/fn-field-parse-error-ice.stderr index 3bf68e8cc04fe..e273e42adcc92 100644 --- a/tests/ui/parser/fn-field-parse-error-ice.stderr +++ b/tests/ui/parser/fn-field-parse-error-ice.stderr @@ -17,12 +17,5 @@ help: escape `fn` to use it as an identifier LL | inner : dyn r#fn () | ++ -error[E0412]: cannot find type `dyn` in this scope - --> $DIR/fn-field-parse-error-ice.rs:4:13 - | -LL | inner : dyn fn () - | ^^^ not found in this scope - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.rs b/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.rs new file mode 100644 index 0000000000000..61fa1305a155f --- /dev/null +++ b/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.rs @@ -0,0 +1,18 @@ +struct Website { + url: String, + title: Option, +} + +fn main() { + let website = Website { + url: "http://www.example.com".into(), + title: Some("Example Domain".into()), + }; + + if let Website { url, Some(title) } = website { //~ ERROR expected `,` + println!("[{}]({})", title, url); + } + if let Website { url, #, title } = website { //~ ERROR expected one of `!` or `[`, found `,` + println!("[{}]({})", title, url); + } +} diff --git a/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.stderr b/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.stderr new file mode 100644 index 0000000000000..1e7821c548498 --- /dev/null +++ b/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.stderr @@ -0,0 +1,18 @@ +error: expected `,` + --> $DIR/avoid-resolve-errors-caused-by-parse-error.rs:12:31 + | +LL | if let Website { url, Some(title) } = website { + | ------- ^ + | | + | while parsing the fields for this pattern + +error: expected one of `!` or `[`, found `,` + --> $DIR/avoid-resolve-errors-caused-by-parse-error.rs:15:28 + | +LL | if let Website { url, #, title } = website { + | ------- ^ expected one of `!` or `[` + | | + | while parsing the fields for this pattern + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/recover-assoc-const-constraint.rs b/tests/ui/parser/recover/recover-assoc-const-constraint.rs similarity index 100% rename from tests/ui/parser/recover-assoc-const-constraint.rs rename to tests/ui/parser/recover/recover-assoc-const-constraint.rs diff --git a/tests/ui/parser/recover-assoc-const-constraint.stderr b/tests/ui/parser/recover/recover-assoc-const-constraint.stderr similarity index 100% rename from tests/ui/parser/recover-assoc-const-constraint.stderr rename to tests/ui/parser/recover/recover-assoc-const-constraint.stderr diff --git a/tests/ui/parser/recover-assoc-eq-missing-term.rs b/tests/ui/parser/recover/recover-assoc-eq-missing-term.rs similarity index 100% rename from tests/ui/parser/recover-assoc-eq-missing-term.rs rename to tests/ui/parser/recover/recover-assoc-eq-missing-term.rs diff --git a/tests/ui/parser/recover-assoc-eq-missing-term.stderr b/tests/ui/parser/recover/recover-assoc-eq-missing-term.stderr similarity index 100% rename from tests/ui/parser/recover-assoc-eq-missing-term.stderr rename to tests/ui/parser/recover/recover-assoc-eq-missing-term.stderr diff --git a/tests/ui/parser/recover-assoc-lifetime-constraint.rs b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs similarity index 100% rename from tests/ui/parser/recover-assoc-lifetime-constraint.rs rename to tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs diff --git a/tests/ui/parser/recover-assoc-lifetime-constraint.stderr b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr similarity index 100% rename from tests/ui/parser/recover-assoc-lifetime-constraint.stderr rename to tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr diff --git a/tests/ui/parser/recover-const-async-fn-ptr.rs b/tests/ui/parser/recover/recover-const-async-fn-ptr.rs similarity index 100% rename from tests/ui/parser/recover-const-async-fn-ptr.rs rename to tests/ui/parser/recover/recover-const-async-fn-ptr.rs diff --git a/tests/ui/parser/recover-const-async-fn-ptr.stderr b/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr similarity index 100% rename from tests/ui/parser/recover-const-async-fn-ptr.stderr rename to tests/ui/parser/recover/recover-const-async-fn-ptr.stderr diff --git a/tests/ui/parser/recover-enum.rs b/tests/ui/parser/recover/recover-enum.rs similarity index 100% rename from tests/ui/parser/recover-enum.rs rename to tests/ui/parser/recover/recover-enum.rs diff --git a/tests/ui/parser/recover-enum.stderr b/tests/ui/parser/recover/recover-enum.stderr similarity index 100% rename from tests/ui/parser/recover-enum.stderr rename to tests/ui/parser/recover/recover-enum.stderr diff --git a/tests/ui/parser/recover-enum2.rs b/tests/ui/parser/recover/recover-enum2.rs similarity index 100% rename from tests/ui/parser/recover-enum2.rs rename to tests/ui/parser/recover/recover-enum2.rs diff --git a/tests/ui/parser/recover-enum2.stderr b/tests/ui/parser/recover/recover-enum2.stderr similarity index 100% rename from tests/ui/parser/recover-enum2.stderr rename to tests/ui/parser/recover/recover-enum2.stderr diff --git a/tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.rs b/tests/ui/parser/recover/recover-field-extra-angle-brackets-in-struct-with-a-field.rs similarity index 100% rename from tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.rs rename to tests/ui/parser/recover/recover-field-extra-angle-brackets-in-struct-with-a-field.rs diff --git a/tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr b/tests/ui/parser/recover/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr similarity index 100% rename from tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr rename to tests/ui/parser/recover/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr diff --git a/tests/ui/parser/recover-field-extra-angle-brackets.rs b/tests/ui/parser/recover/recover-field-extra-angle-brackets.rs similarity index 100% rename from tests/ui/parser/recover-field-extra-angle-brackets.rs rename to tests/ui/parser/recover/recover-field-extra-angle-brackets.rs diff --git a/tests/ui/parser/recover-field-extra-angle-brackets.stderr b/tests/ui/parser/recover/recover-field-extra-angle-brackets.stderr similarity index 100% rename from tests/ui/parser/recover-field-extra-angle-brackets.stderr rename to tests/ui/parser/recover/recover-field-extra-angle-brackets.stderr diff --git a/tests/ui/parser/recover-field-semi.rs b/tests/ui/parser/recover/recover-field-semi.rs similarity index 100% rename from tests/ui/parser/recover-field-semi.rs rename to tests/ui/parser/recover/recover-field-semi.rs diff --git a/tests/ui/parser/recover-field-semi.stderr b/tests/ui/parser/recover/recover-field-semi.stderr similarity index 100% rename from tests/ui/parser/recover-field-semi.stderr rename to tests/ui/parser/recover/recover-field-semi.stderr diff --git a/tests/ui/parser/recover-fn-ptr-with-generics.rs b/tests/ui/parser/recover/recover-fn-ptr-with-generics.rs similarity index 91% rename from tests/ui/parser/recover-fn-ptr-with-generics.rs rename to tests/ui/parser/recover/recover-fn-ptr-with-generics.rs index 31de418be5f70..6f1de639d3ad5 100644 --- a/tests/ui/parser/recover-fn-ptr-with-generics.rs +++ b/tests/ui/parser/recover/recover-fn-ptr-with-generics.rs @@ -4,8 +4,6 @@ fn main() { type Identity = fn(T) -> T; //~^ ERROR function pointer types may not have generic parameters - //~| ERROR cannot find type `T` in this scope - //~| ERROR cannot find type `T` in this scope let _: fn(); //~^ ERROR function pointer types may not have generic parameters diff --git a/tests/ui/parser/recover-fn-ptr-with-generics.stderr b/tests/ui/parser/recover/recover-fn-ptr-with-generics.stderr similarity index 73% rename from tests/ui/parser/recover-fn-ptr-with-generics.stderr rename to tests/ui/parser/recover/recover-fn-ptr-with-generics.stderr index 069fcffe9a0df..b2360ef105f01 100644 --- a/tests/ui/parser/recover-fn-ptr-with-generics.stderr +++ b/tests/ui/parser/recover/recover-fn-ptr-with-generics.stderr @@ -17,7 +17,7 @@ LL | type Identity = fn(T) -> T; | ^^^ error: function pointer types may not have generic parameters - --> $DIR/recover-fn-ptr-with-generics.rs:10:14 + --> $DIR/recover-fn-ptr-with-generics.rs:8:14 | LL | let _: fn(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL + let _: for<'e, 'f> fn(); | error: function pointer types may not have generic parameters - --> $DIR/recover-fn-ptr-with-generics.rs:13:26 + --> $DIR/recover-fn-ptr-with-generics.rs:11:26 | LL | let _: for<'outer> fn<'inner>(); | ^^^^^^^^ @@ -41,7 +41,7 @@ LL + let _: for<'outer, 'inner> fn(); | error: function pointer types may not have generic parameters - --> $DIR/recover-fn-ptr-with-generics.rs:16:20 + --> $DIR/recover-fn-ptr-with-generics.rs:14:20 | LL | let _: for<> fn<'r>(); | ^^^^ @@ -53,13 +53,13 @@ LL + let _: for<'r> fn(); | error: function pointer types may not have generic parameters - --> $DIR/recover-fn-ptr-with-generics.rs:19:18 + --> $DIR/recover-fn-ptr-with-generics.rs:17:18 | LL | type Hmm = fn<>(); | ^^ error: function pointer types may not have generic parameters - --> $DIR/recover-fn-ptr-with-generics.rs:22:21 + --> $DIR/recover-fn-ptr-with-generics.rs:20:21 | LL | let _: extern fn<'a: 'static>(); | ^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL + let _: for<'a> extern fn(); | error: function pointer types may not have generic parameters - --> $DIR/recover-fn-ptr-with-generics.rs:26:35 + --> $DIR/recover-fn-ptr-with-generics.rs:24:35 | LL | let _: for<'any> extern "C" fn<'u>(); | ^^^^ @@ -83,29 +83,16 @@ LL + let _: for<'any, 'u> extern "C" fn(); | error: expected identifier, found `>` - --> $DIR/recover-fn-ptr-with-generics.rs:29:32 + --> $DIR/recover-fn-ptr-with-generics.rs:27:32 | LL | type QuiteBroken = fn(); | ^ expected identifier -error[E0412]: cannot find type `T` in this scope - --> $DIR/recover-fn-ptr-with-generics.rs:5:27 - | -LL | type Identity = fn(T) -> T; - | ^ not found in this scope - -error[E0412]: cannot find type `T` in this scope - --> $DIR/recover-fn-ptr-with-generics.rs:5:33 - | -LL | type Identity = fn(T) -> T; - | ^ not found in this scope - error: lifetime bounds cannot be used in this context - --> $DIR/recover-fn-ptr-with-generics.rs:22:26 + --> $DIR/recover-fn-ptr-with-generics.rs:20:26 | LL | let _: extern fn<'a: 'static>(); | ^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 10 previous errors -For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/parser/recover-fn-trait-from-fn-kw.rs b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.rs similarity index 100% rename from tests/ui/parser/recover-fn-trait-from-fn-kw.rs rename to tests/ui/parser/recover/recover-fn-trait-from-fn-kw.rs diff --git a/tests/ui/parser/recover-fn-trait-from-fn-kw.stderr b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr similarity index 100% rename from tests/ui/parser/recover-fn-trait-from-fn-kw.stderr rename to tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr diff --git a/tests/ui/parser/recover-for-loop-parens-around-head.rs b/tests/ui/parser/recover/recover-for-loop-parens-around-head.rs similarity index 100% rename from tests/ui/parser/recover-for-loop-parens-around-head.rs rename to tests/ui/parser/recover/recover-for-loop-parens-around-head.rs diff --git a/tests/ui/parser/recover-for-loop-parens-around-head.stderr b/tests/ui/parser/recover/recover-for-loop-parens-around-head.stderr similarity index 100% rename from tests/ui/parser/recover-for-loop-parens-around-head.stderr rename to tests/ui/parser/recover/recover-for-loop-parens-around-head.stderr diff --git a/tests/ui/parser/recover-from-bad-variant.rs b/tests/ui/parser/recover/recover-from-bad-variant.rs similarity index 100% rename from tests/ui/parser/recover-from-bad-variant.rs rename to tests/ui/parser/recover/recover-from-bad-variant.rs diff --git a/tests/ui/parser/recover-from-bad-variant.stderr b/tests/ui/parser/recover/recover-from-bad-variant.stderr similarity index 100% rename from tests/ui/parser/recover-from-bad-variant.stderr rename to tests/ui/parser/recover/recover-from-bad-variant.stderr diff --git a/tests/ui/parser/recover-from-homoglyph.rs b/tests/ui/parser/recover/recover-from-homoglyph.rs similarity index 100% rename from tests/ui/parser/recover-from-homoglyph.rs rename to tests/ui/parser/recover/recover-from-homoglyph.rs diff --git a/tests/ui/parser/recover-from-homoglyph.stderr b/tests/ui/parser/recover/recover-from-homoglyph.stderr similarity index 100% rename from tests/ui/parser/recover-from-homoglyph.stderr rename to tests/ui/parser/recover/recover-from-homoglyph.stderr diff --git a/tests/ui/parser/recover-labeled-non-block-expr.fixed b/tests/ui/parser/recover/recover-labeled-non-block-expr.fixed similarity index 100% rename from tests/ui/parser/recover-labeled-non-block-expr.fixed rename to tests/ui/parser/recover/recover-labeled-non-block-expr.fixed diff --git a/tests/ui/parser/recover-labeled-non-block-expr.rs b/tests/ui/parser/recover/recover-labeled-non-block-expr.rs similarity index 100% rename from tests/ui/parser/recover-labeled-non-block-expr.rs rename to tests/ui/parser/recover/recover-labeled-non-block-expr.rs diff --git a/tests/ui/parser/recover-labeled-non-block-expr.stderr b/tests/ui/parser/recover/recover-labeled-non-block-expr.stderr similarity index 100% rename from tests/ui/parser/recover-labeled-non-block-expr.stderr rename to tests/ui/parser/recover/recover-labeled-non-block-expr.stderr diff --git a/tests/ui/parser/recover-missing-semi-before-item.fixed b/tests/ui/parser/recover/recover-missing-semi-before-item.fixed similarity index 100% rename from tests/ui/parser/recover-missing-semi-before-item.fixed rename to tests/ui/parser/recover/recover-missing-semi-before-item.fixed diff --git a/tests/ui/parser/recover-missing-semi-before-item.rs b/tests/ui/parser/recover/recover-missing-semi-before-item.rs similarity index 100% rename from tests/ui/parser/recover-missing-semi-before-item.rs rename to tests/ui/parser/recover/recover-missing-semi-before-item.rs diff --git a/tests/ui/parser/recover-missing-semi-before-item.stderr b/tests/ui/parser/recover/recover-missing-semi-before-item.stderr similarity index 100% rename from tests/ui/parser/recover-missing-semi-before-item.stderr rename to tests/ui/parser/recover/recover-missing-semi-before-item.stderr diff --git a/tests/ui/parser/recover-missing-semi.rs b/tests/ui/parser/recover/recover-missing-semi.rs similarity index 100% rename from tests/ui/parser/recover-missing-semi.rs rename to tests/ui/parser/recover/recover-missing-semi.rs diff --git a/tests/ui/parser/recover-missing-semi.stderr b/tests/ui/parser/recover/recover-missing-semi.stderr similarity index 100% rename from tests/ui/parser/recover-missing-semi.stderr rename to tests/ui/parser/recover/recover-missing-semi.stderr diff --git a/tests/ui/parser/recover-quantified-closure.rs b/tests/ui/parser/recover/recover-quantified-closure.rs similarity index 100% rename from tests/ui/parser/recover-quantified-closure.rs rename to tests/ui/parser/recover/recover-quantified-closure.rs diff --git a/tests/ui/parser/recover-quantified-closure.stderr b/tests/ui/parser/recover/recover-quantified-closure.stderr similarity index 100% rename from tests/ui/parser/recover-quantified-closure.stderr rename to tests/ui/parser/recover/recover-quantified-closure.stderr diff --git a/tests/ui/parser/recover-range-pats.rs b/tests/ui/parser/recover/recover-range-pats.rs similarity index 100% rename from tests/ui/parser/recover-range-pats.rs rename to tests/ui/parser/recover/recover-range-pats.rs diff --git a/tests/ui/parser/recover-range-pats.stderr b/tests/ui/parser/recover/recover-range-pats.stderr similarity index 100% rename from tests/ui/parser/recover-range-pats.stderr rename to tests/ui/parser/recover/recover-range-pats.stderr diff --git a/tests/ui/parser/recover-ref-dyn-mut.rs b/tests/ui/parser/recover/recover-ref-dyn-mut.rs similarity index 100% rename from tests/ui/parser/recover-ref-dyn-mut.rs rename to tests/ui/parser/recover/recover-ref-dyn-mut.rs diff --git a/tests/ui/parser/recover-ref-dyn-mut.stderr b/tests/ui/parser/recover/recover-ref-dyn-mut.stderr similarity index 100% rename from tests/ui/parser/recover-ref-dyn-mut.stderr rename to tests/ui/parser/recover/recover-ref-dyn-mut.stderr diff --git a/tests/ui/parser/recover-struct.rs b/tests/ui/parser/recover/recover-struct.rs similarity index 100% rename from tests/ui/parser/recover-struct.rs rename to tests/ui/parser/recover/recover-struct.rs diff --git a/tests/ui/parser/recover-struct.stderr b/tests/ui/parser/recover/recover-struct.stderr similarity index 100% rename from tests/ui/parser/recover-struct.stderr rename to tests/ui/parser/recover/recover-struct.stderr diff --git a/tests/ui/parser/recover-tuple-pat.rs b/tests/ui/parser/recover/recover-tuple-pat.rs similarity index 100% rename from tests/ui/parser/recover-tuple-pat.rs rename to tests/ui/parser/recover/recover-tuple-pat.rs diff --git a/tests/ui/parser/recover-tuple-pat.stderr b/tests/ui/parser/recover/recover-tuple-pat.stderr similarity index 100% rename from tests/ui/parser/recover-tuple-pat.stderr rename to tests/ui/parser/recover/recover-tuple-pat.stderr diff --git a/tests/ui/parser/recover-tuple.rs b/tests/ui/parser/recover/recover-tuple.rs similarity index 100% rename from tests/ui/parser/recover-tuple.rs rename to tests/ui/parser/recover/recover-tuple.rs diff --git a/tests/ui/parser/recover-tuple.stderr b/tests/ui/parser/recover/recover-tuple.stderr similarity index 100% rename from tests/ui/parser/recover-tuple.stderr rename to tests/ui/parser/recover/recover-tuple.stderr diff --git a/tests/ui/parser/recover-unticked-labels.fixed b/tests/ui/parser/recover/recover-unticked-labels.fixed similarity index 100% rename from tests/ui/parser/recover-unticked-labels.fixed rename to tests/ui/parser/recover/recover-unticked-labels.fixed diff --git a/tests/ui/parser/recover-unticked-labels.rs b/tests/ui/parser/recover/recover-unticked-labels.rs similarity index 100% rename from tests/ui/parser/recover-unticked-labels.rs rename to tests/ui/parser/recover/recover-unticked-labels.rs diff --git a/tests/ui/parser/recover-unticked-labels.stderr b/tests/ui/parser/recover/recover-unticked-labels.stderr similarity index 100% rename from tests/ui/parser/recover-unticked-labels.stderr rename to tests/ui/parser/recover/recover-unticked-labels.stderr diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.fixed b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed similarity index 100% rename from tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.fixed rename to tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.rs b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs similarity index 100% rename from tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.rs rename to tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.stderr b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr similarity index 100% rename from tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.stderr rename to tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.rs b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-1.rs similarity index 100% rename from tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.rs rename to tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-1.rs diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.stderr b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-1.stderr similarity index 100% rename from tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.stderr rename to tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-1.stderr From 0418cca060058d8787c5b625154e0b6e24854634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 18 Oct 2023 21:28:08 +0000 Subject: [PATCH 2/2] Detect when sub-pattern within struct pattern is missing ident --- compiler/rustc_parse/src/parser/pat.rs | 30 +++++++++++++++++-- ...id-resolve-errors-caused-by-parse-error.rs | 2 +- ...esolve-errors-caused-by-parse-error.stderr | 11 +++++-- tests/ui/resolve/issue-54379.rs | 2 +- tests/ui/resolve/issue-54379.stderr | 11 +++++-- 5 files changed, 46 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 7af0a7e5dcb9b..8bfb4a6bb61b5 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -964,12 +964,38 @@ impl<'a> Parser<'a> { return Err(err); } }; + let prev = self.prev_token.span; let lo = self.token.span; // check that a comma comes after every field if !ate_comma { - let err = ExpectedCommaAfterPatternField { span: self.token.span } - .into_diagnostic(&self.sess.span_diagnostic); + let mut snapshot = self.create_snapshot_for_diagnostic(); + let err = match snapshot.parse_pat_allow_top_alt( + None, + RecoverComma::No, + RecoverColon::No, + CommaRecoveryMode::EitherTupleOrPipe, + ) { + Ok(pat) => { + // We've got `Struct { Some(foo) }` where the user forgot the field ident. + let span = prev.to(pat.span); + let mut err = + self.struct_span_err(span, "missing field name before pattern"); + err.span_label(span, "this pattern needs to be preceeded by a field name"); + err.span_suggestion_verbose( + prev.shrink_to_lo(), + "you might have meant to add a field", + "field_name: ".to_string(), + Applicability::HasPlaceholders, + ); + err + } + Err(err) => { + err.cancel(); + ExpectedCommaAfterPatternField { span: self.token.span } + .into_diagnostic(&self.sess.span_diagnostic) + } + }; if let Some(mut delayed) = delayed_err { delayed.emit(); } diff --git a/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.rs b/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.rs index 61fa1305a155f..94cda1bf7c1d8 100644 --- a/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.rs +++ b/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.rs @@ -9,7 +9,7 @@ fn main() { title: Some("Example Domain".into()), }; - if let Website { url, Some(title) } = website { //~ ERROR expected `,` + if let Website { url, Some(title) } = website { //~ ERROR missing field name before pattern println!("[{}]({})", title, url); } if let Website { url, #, title } = website { //~ ERROR expected one of `!` or `[`, found `,` diff --git a/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.stderr b/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.stderr index 1e7821c548498..f6ed8476e9d17 100644 --- a/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.stderr +++ b/tests/ui/parser/recover/avoid-resolve-errors-caused-by-parse-error.stderr @@ -1,10 +1,15 @@ -error: expected `,` - --> $DIR/avoid-resolve-errors-caused-by-parse-error.rs:12:31 +error: missing field name before pattern + --> $DIR/avoid-resolve-errors-caused-by-parse-error.rs:12:27 | LL | if let Website { url, Some(title) } = website { - | ------- ^ + | ------- ^^^^^^^^^^^ this pattern needs to be preceeded by a field name | | | while parsing the fields for this pattern + | +help: you might have meant to add a field + | +LL | if let Website { url, field_name: Some(title) } = website { + | +++++++++++ error: expected one of `!` or `[`, found `,` --> $DIR/avoid-resolve-errors-caused-by-parse-error.rs:15:28 diff --git a/tests/ui/resolve/issue-54379.rs b/tests/ui/resolve/issue-54379.rs index 807c54393f29b..f79302ef1cebf 100644 --- a/tests/ui/resolve/issue-54379.rs +++ b/tests/ui/resolve/issue-54379.rs @@ -7,7 +7,7 @@ fn main() { match thing { MyStruct { .., Some(_) } => {}, - //~^ ERROR expected `,` + //~^ ERROR missing field name before pattern //~| ERROR expected `}`, found `,` _ => {} } diff --git a/tests/ui/resolve/issue-54379.stderr b/tests/ui/resolve/issue-54379.stderr index 750727273eb1f..588755176e7c1 100644 --- a/tests/ui/resolve/issue-54379.stderr +++ b/tests/ui/resolve/issue-54379.stderr @@ -7,13 +7,18 @@ LL | MyStruct { .., Some(_) } => {}, | | expected `}` | `..` must be at the end and cannot have a trailing comma -error: expected `,` - --> $DIR/issue-54379.rs:9:28 +error: missing field name before pattern + --> $DIR/issue-54379.rs:9:24 | LL | MyStruct { .., Some(_) } => {}, - | -------- ^ + | -------- ^^^^^^^ this pattern needs to be preceeded by a field name | | | while parsing the fields for this pattern + | +help: you might have meant to add a field + | +LL | MyStruct { .., field_name: Some(_) } => {}, + | +++++++++++ error: aborting due to 2 previous errors