diff options
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 313 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/lexer/mod.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/lib.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/attr.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/generics.rs | 37 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 133 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/nonterminal.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/path.rs | 43 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 72 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/validate_attr.rs | 29 |
13 files changed, 438 insertions, 280 deletions
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 069217165fa..f286707a9c0 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2332,3 +2332,316 @@ pub(crate) struct BadReturnTypeNotationDotDot { #[suggestion(code = "", applicability = "maybe-incorrect")] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(parse_bad_assoc_type_bounds)] +pub(crate) struct BadAssocTypeBounds { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_attr_after_generic)] +pub(crate) struct AttrAfterGeneric { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_attr_without_generics)] +pub(crate) struct AttrWithoutGenerics { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_where_generics)] +pub(crate) struct WhereOnGenerics { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_generics_in_path)] +pub(crate) struct GenericsInPath { + #[primary_span] + pub span: Vec<Span>, +} + +#[derive(Diagnostic)] +#[diag(parse_assoc_lifetime)] +#[help] +pub(crate) struct AssocLifetime { + #[primary_span] + pub span: Span, + #[label] + pub lifetime: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_tilde_const_lifetime)] +pub(crate) struct TildeConstLifetime { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_maybe_lifetime)] +pub(crate) struct MaybeLifetime { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_parenthesized_lifetime)] +pub(crate) struct ParenthesizedLifetime { + #[primary_span] + pub span: Span, + #[suggestion(style = "short", applicability = "machine-applicable", code = "{snippet}")] + pub sugg: Option<Span>, + pub snippet: String, +} + +#[derive(Diagnostic)] +#[diag(parse_const_bounds_missing_tilde)] +pub(crate) struct ConstMissingTilde { + #[primary_span] + pub span: Span, + #[suggestion(code = "~", applicability = "machine-applicable")] + pub start: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_underscore_literal_suffix)] +pub(crate) struct UnderscoreLiteralSuffix { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_expect_label_found_ident)] +pub(crate) struct ExpectedLabelFoundIdent { + #[primary_span] + pub span: Span, + #[suggestion(code = "'", applicability = "machine-applicable", style = "short")] + pub start: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_inappropriate_default)] +#[note] +pub(crate) struct InappropriateDefault { + #[primary_span] + #[label] + pub span: Span, + pub article: &'static str, + pub descr: &'static str, +} + +#[derive(Diagnostic)] +#[diag(parse_recover_import_as_use)] +pub(crate) struct RecoverImportAsUse { + #[primary_span] + #[suggestion(code = "use", applicability = "machine-applicable", style = "short")] + pub span: Span, + pub token_name: String, +} + +#[derive(Diagnostic)] +#[diag(parse_single_colon_import_path)] +#[note] +pub(crate) struct SingleColonImportPath { + #[primary_span] + #[suggestion(code = "::", applicability = "machine-applicable", style = "short")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_bad_item_kind)] +#[help] +pub(crate) struct BadItemKind { + #[primary_span] + pub span: Span, + pub descr: &'static str, + pub ctx: &'static str, +} + +#[derive(Diagnostic)] +#[diag(parse_single_colon_struct_type)] +pub(crate) struct SingleColonStructType { + #[primary_span] + #[suggestion(code = "::", applicability = "maybe-incorrect", style = "verbose")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_equals_struct_default)] +pub(crate) struct EqualsStructDefault { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_macro_rules_missing_bang)] +pub(crate) struct MacroRulesMissingBang { + #[primary_span] + pub span: Span, + #[suggestion(code = "!", applicability = "machine-applicable", style = "verbose")] + pub hi: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_macro_name_remove_bang)] +pub(crate) struct MacroNameRemoveBang { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_macro_rules_visibility)] +pub(crate) struct MacroRulesVisibility<'a> { + #[primary_span] + #[suggestion(code = "#[macro_export]", applicability = "maybe-incorrect")] + pub span: Span, + pub vis: &'a str, +} + +#[derive(Diagnostic)] +#[diag(parse_macro_invocation_visibility)] +#[help] +pub(crate) struct MacroInvocationVisibility<'a> { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub span: Span, + pub vis: &'a str, +} + +#[derive(Diagnostic)] +#[diag(parse_nested_adt)] +pub(crate) struct NestedAdt<'a> { + #[primary_span] + pub span: Span, + #[suggestion(code = "", applicability = "maybe-incorrect")] + pub item: Span, + pub keyword: &'a str, + pub kw_str: Cow<'a, str>, +} + +#[derive(Diagnostic)] +#[diag(parse_function_body_equals_expr)] +pub(crate) struct FunctionBodyEqualsExpr { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: FunctionBodyEqualsExprSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +pub(crate) struct FunctionBodyEqualsExprSugg { + #[suggestion_part(code = "{{")] + pub eq: Span, + #[suggestion_part(code = " }}")] + pub semi: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_box_not_pat)] +pub(crate) struct BoxNotPat { + #[primary_span] + pub span: Span, + #[note] + pub kw: Span, + #[suggestion(code = "r#", applicability = "maybe-incorrect", style = "verbose")] + pub lo: Span, + pub descr: String, +} + +#[derive(Diagnostic)] +#[diag(parse_unmatched_angle)] +pub(crate) struct UnmatchedAngle { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub span: Span, + pub plural: bool, +} + +#[derive(Diagnostic)] +#[diag(parse_missing_plus_in_bounds)] +pub(crate) struct MissingPlusBounds { + #[primary_span] + pub span: Span, + #[suggestion(code = " +", applicability = "maybe-incorrect", style = "verbose")] + pub hi: Span, + pub sym: Symbol, +} + +#[derive(Diagnostic)] +#[diag(parse_incorrect_braces_trait_bounds)] +pub(crate) struct IncorrectBracesTraitBounds { + #[primary_span] + pub span: Vec<Span>, + #[subdiagnostic] + pub sugg: IncorrectBracesTraitBoundsSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +pub(crate) struct IncorrectBracesTraitBoundsSugg { + #[suggestion_part(code = " ")] + pub l: Span, + #[suggestion_part(code = "")] + pub r: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_kw_bad_case)] +pub(crate) struct KwBadCase<'a> { + #[primary_span] + #[suggestion(code = "{kw}", applicability = "machine-applicable")] + pub span: Span, + pub kw: &'a str, +} + +#[derive(Diagnostic)] +#[diag(parse_meta_bad_delim)] +pub(crate) struct MetaBadDelim { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: MetaBadDelimSugg, +} + +#[derive(Diagnostic)] +#[diag(parse_cfg_attr_bad_delim)] +pub(crate) struct CfgAttrBadDelim { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: MetaBadDelimSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_meta_bad_delim_suggestion, applicability = "machine-applicable")] +pub(crate) struct MetaBadDelimSugg { + #[suggestion_part(code = "(")] + pub open: Span, + #[suggestion_part(code = ")")] + pub close: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_malformed_cfg_attr)] +#[note] +pub(crate) struct MalformedCfgAttr { + #[primary_span] + #[suggestion(code = "{sugg}")] + pub span: Span, + pub sugg: &'static str, +} diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 9e856c9f212..a4a75fcb969 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -67,7 +67,7 @@ pub(crate) fn parse_token_trees<'a>( match token_trees { Ok(stream) if unmatched_delims.is_empty() => Ok(stream), _ => { - // Return error if there are unmatched delimiters or unclosng delimiters. + // Return error if there are unmatched delimiters or unclosed delimiters. // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch // because the delimiter mismatch is more likely to be the root cause of error @@ -209,11 +209,7 @@ impl<'a> StringReader<'a> { if string == "_" { self.sess .span_diagnostic - .struct_span_err( - self.mk_sp(suffix_start, self.pos), - "underscore literal suffix is not allowed", - ) - .emit(); + .emit_err(errors::UnderscoreLiteralSuffix { span: self.mk_sp(suffix_start, self.pos) }); None } else { Some(Symbol::intern(string)) diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 17466cd0e6d..61a1cdeb540 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -18,9 +18,9 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::{AttrItem, Attribute, MetaItem}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Applicability, Diagnostic, FatalError, Level, PResult}; +use rustc_errors::{Diagnostic, FatalError, Level, PResult}; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_macros::fluent_messages; +use rustc_fluent_macro::fluent_messages; use rustc_session::parse::ParseSess; use rustc_span::{FileName, SourceFile, Span}; @@ -243,8 +243,7 @@ pub fn parse_cfg_attr( ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens }) if !tokens.is_empty() => { - let msg = "wrong `cfg_attr` delimiters"; - crate::validate_attr::check_meta_bad_delim(parse_sess, dspan, delim, msg); + crate::validate_attr::check_cfg_attr_bad_delim(parse_sess, dspan, delim); match parse_in(parse_sess, tokens.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) { Ok(r) => return Some(r), Err(mut e) => { @@ -265,15 +264,5 @@ const CFG_ATTR_NOTE_REF: &str = "for more information, visit \ #the-cfg_attr-attribute>"; fn error_malformed_cfg_attr_missing(span: Span, parse_sess: &ParseSess) { - parse_sess - .span_diagnostic - .struct_span_err(span, "malformed `cfg_attr` attribute input") - .span_suggestion( - span, - "missing condition and attribute", - CFG_ATTR_GRAMMAR_HELP, - Applicability::HasPlaceholders, - ) - .note(CFG_ATTR_NOTE_REF) - .emit(); + parse_sess.emit_err(errors::MalformedCfgAttr { span, sugg: CFG_ATTR_GRAMMAR_HELP }); } diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index e3e7c63e344..e1db19557cf 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -45,10 +45,10 @@ impl<'a> Parser<'a> { Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span: prev_outer_attr_sp.unwrap(), }) - } else if let Some(prev_outer_attr_sp) = prev_outer_attr_sp { - Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) } else { - None + prev_outer_attr_sp.map(|prev_outer_attr_sp| { + InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp } + }) }; let inner_parse_policy = InnerAttrPolicy::Forbidden(inner_error_reason); just_parsed_doc_comment = false; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 03c82fbd329..27de9bd7268 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3151,14 +3151,10 @@ impl<'a> Parser<'a> { let label = format!("'{}", ident.name); let ident = Ident { name: Symbol::intern(&label), span: ident.span }; - self.struct_span_err(ident.span, "expected a label, found an identifier") - .span_suggestion( - ident.span, - "labels start with a tick", - label, - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(errors::ExpectedLabelFoundIdent { + span: ident.span, + start: ident.span.shrink_to_lo(), + }); Label { ident } } diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index f8ef1307c98..61a7ae93bfa 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -1,5 +1,5 @@ use crate::errors::{ - MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters, + self, MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters, UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody, WhereClauseBeforeTupleStructBodySugg, }; @@ -181,12 +181,9 @@ impl<'a> Parser<'a> { let snapshot = this.create_snapshot_for_diagnostic(); match this.parse_ty_where_predicate() { Ok(where_predicate) => { - this.struct_span_err( - where_predicate.span(), - "bounds on associated types do not belong here", - ) - .span_label(where_predicate.span(), "belongs in `where` clause") - .emit(); + this.sess.emit_err(errors::BadAssocTypeBounds { + span: where_predicate.span(), + }); // FIXME - try to continue parsing other generics? return Ok((None, TrailingToken::None)); } @@ -201,22 +198,11 @@ impl<'a> Parser<'a> { // Check for trailing attributes and stop parsing. if !attrs.is_empty() { if !params.is_empty() { - this.struct_span_err( - attrs[0].span, - "trailing attribute after generic parameter", - ) - .span_label(attrs[0].span, "attributes must go before parameters") - .emit(); + this.sess + .emit_err(errors::AttrAfterGeneric { span: attrs[0].span }); } else { - this.struct_span_err( - attrs[0].span, - "attribute without generic parameters", - ) - .span_label( - attrs[0].span, - "attributes are only permitted when preceding parameters", - ) - .emit(); + this.sess + .emit_err(errors::AttrWithoutGenerics { span: attrs[0].span }); } } return Ok((None, TrailingToken::None)); @@ -304,12 +290,7 @@ impl<'a> Parser<'a> { // change we parse those generics now, but report an error. if self.choose_generics_over_qpath(0) { let generics = self.parse_generics()?; - self.struct_span_err( - generics.span, - "generic parameters on `where` clauses are reserved for future use", - ) - .span_label(generics.span, "currently unsupported") - .emit(); + self.sess.emit_err(errors::WhereOnGenerics { span: generics.span }); } loop { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 6422b8ac1ba..9e003bfc097 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -181,11 +181,11 @@ impl<'a> Parser<'a> { /// Error in-case `default` was parsed in an in-appropriate context. fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) { if let Defaultness::Default(span) = def { - let msg = format!("{} {} cannot be `default`", kind.article(), kind.descr()); - self.struct_span_err(span, &msg) - .span_label(span, "`default` because of this") - .note("only associated `fn`, `const`, and `type` items can be `default`") - .emit(); + self.sess.emit_err(errors::InappropriateDefault { + span, + article: kind.article(), + descr: kind.descr(), + }); } } @@ -310,14 +310,7 @@ impl<'a> Parser<'a> { self.bump(); match self.parse_use_item() { Ok(u) => { - self.struct_span_err(span, format!("expected item, found {token_name}")) - .span_suggestion_short( - span, - "items are imported using the `use` keyword", - "use", - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(errors::RecoverImportAsUse { span, token_name }); Ok(Some(u)) } Err(e) => { @@ -963,15 +956,8 @@ impl<'a> Parser<'a> { } else { // Recover from using a colon as path separator. while self.eat_noexpect(&token::Colon) { - self.struct_span_err(self.prev_token.span, "expected `::`, found `:`") - .span_suggestion_short( - self.prev_token.span, - "use double colon", - "::", - Applicability::MachineApplicable, - ) - .note_once("import paths are delimited using `::`") - .emit(); + self.sess + .emit_err(errors::SingleColonImportPath { span: self.prev_token.span }); // We parse the rest of the path and append it to the original prefix. self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?; @@ -1134,13 +1120,11 @@ impl<'a> Parser<'a> { )) } - fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option<T> { + fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> { // FIXME(#100717): needs variant for each `ItemKind` (instead of using `ItemKind::descr()`) let span = self.sess.source_map().guess_head_span(span); let descr = kind.descr(); - self.struct_span_err(span, &format!("{descr} is not supported in {ctx}")) - .help(&format!("consider moving the {descr} out to a nearby module scope")) - .emit(); + self.sess.emit_err(errors::BadItemKind { span, descr, ctx }); None } @@ -1713,27 +1697,13 @@ impl<'a> Parser<'a> { self.expect_field_ty_separator()?; let ty = self.parse_ty()?; if self.token.kind == token::Colon && self.look_ahead(1, |tok| tok.kind != token::Colon) { - self.struct_span_err(self.token.span, "found single colon in a struct field type path") - .span_suggestion_verbose( - self.token.span, - "write a path separator here", - "::", - Applicability::MaybeIncorrect, - ) - .emit(); + self.sess.emit_err(errors::SingleColonStructType { span: self.token.span }); } if self.token.kind == token::Eq { self.bump(); let const_expr = self.parse_expr_anon_const()?; let sp = ty.span.shrink_to_hi().to(const_expr.value.span); - self.struct_span_err(sp, "default values on `struct` fields aren't supported") - .span_suggestion( - sp, - "remove this unsupported default value", - "", - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(errors::EqualsStructDefault { span: sp }); } Ok(FieldDef { span: lo.to(self.prev_token.span), @@ -1871,14 +1841,10 @@ impl<'a> Parser<'a> { return IsMacroRulesItem::Yes { has_bang: true }; } else if self.look_ahead(1, |t| (t.is_ident())) { // macro_rules foo - self.struct_span_err(macro_rules_span, "expected `!` after `macro_rules`") - .span_suggestion( - macro_rules_span, - "add a `!`", - "macro_rules!", - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(errors::MacroRulesMissingBang { + span: macro_rules_span, + hi: macro_rules_span.shrink_to_hi(), + }); return IsMacroRulesItem::Yes { has_bang: false }; } @@ -1903,9 +1869,7 @@ impl<'a> Parser<'a> { if self.eat(&token::Not) { // Handle macro_rules! foo! let span = self.prev_token.span; - self.struct_span_err(span, "macro names aren't followed by a `!`") - .span_suggestion(span, "remove the `!`", "", Applicability::MachineApplicable) - .emit(); + self.sess.emit_err(errors::MacroNameRemoveBang { span }); } let body = self.parse_delim_args()?; @@ -1925,25 +1889,9 @@ impl<'a> Parser<'a> { let vstr = pprust::vis_to_string(vis); let vstr = vstr.trim_end(); if macro_rules { - let msg = format!("can't qualify macro_rules invocation with `{vstr}`"); - self.struct_span_err(vis.span, &msg) - .span_suggestion( - vis.span, - "try exporting the macro", - "#[macro_export]", - Applicability::MaybeIncorrect, // speculative - ) - .emit(); + self.sess.emit_err(errors::MacroRulesVisibility { span: vis.span, vis: vstr }); } else { - self.struct_span_err(vis.span, "can't qualify macro invocation with `pub`") - .span_suggestion( - vis.span, - "remove the visibility", - "", - Applicability::MachineApplicable, - ) - .help(&format!("try adjusting the macro to put `{vstr}` inside the invocation")) - .emit(); + self.sess.emit_err(errors::MacroInvocationVisibility { span: vis.span, vis: vstr }); } } @@ -1989,18 +1937,12 @@ impl<'a> Parser<'a> { let kw_token = self.token.clone(); let kw_str = pprust::token_to_string(&kw_token); let item = self.parse_item(ForceCollect::No)?; - - self.struct_span_err( - kw_token.span, - &format!("`{kw_str}` definition cannot be nested inside `{keyword}`"), - ) - .span_suggestion( - item.unwrap().span, - &format!("consider creating a new `{kw_str}` definition instead of nesting"), - "", - Applicability::MaybeIncorrect, - ) - .emit(); + self.sess.emit_err(errors::NestedAdt { + span: kw_token.span, + item: item.unwrap().span, + kw_str, + keyword: keyword.as_str(), + }); // We successfully parsed the item but we must inform the caller about nested problem. return Ok(false); } @@ -2139,13 +2081,10 @@ impl<'a> Parser<'a> { let _ = self.parse_expr()?; self.expect_semi()?; // `;` let span = eq_sp.to(self.prev_token.span); - self.struct_span_err(span, "function body cannot be `= expression;`") - .multipart_suggestion( - "surround the expression with `{` and `}` instead of `=` and `;`", - vec![(eq_sp, "{".to_string()), (self.prev_token.span, " }".to_string())], - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(errors::FunctionBodyEqualsExpr { + span, + sugg: errors::FunctionBodyEqualsExprSugg { eq: eq_sp, semi: self.prev_token.span }, + }); (AttrVec::new(), Some(self.mk_block_err(span))) } else { let expected = if req_body { @@ -2577,14 +2516,12 @@ impl<'a> Parser<'a> { } fn recover_self_param(&mut self) -> bool { - match self - .parse_outer_attributes() - .and_then(|_| self.parse_self_param()) - .map_err(|e| e.cancel()) - { - Ok(Some(_)) => true, - _ => false, - } + matches!( + self.parse_outer_attributes() + .and_then(|_| self.parse_self_param()) + .map_err(|e| e.cancel()), + Ok(Some(_)) + ) } } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index aa57b804779..1c34e491f21 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -43,7 +43,7 @@ use thin_vec::ThinVec; use tracing::debug; use crate::errors::{ - IncorrectVisibilityRestriction, MismatchedClosingDelimiter, NonStringAbiLiteral, + self, IncorrectVisibilityRestriction, MismatchedClosingDelimiter, NonStringAbiLiteral, }; bitflags::bitflags! { @@ -663,15 +663,10 @@ impl<'a> Parser<'a> { if case == Case::Insensitive && let Some((ident, /* is_raw */ false)) = self.token.ident() && ident.as_str().to_lowercase() == kw.as_str().to_lowercase() { - self - .struct_span_err(ident.span, format!("keyword `{kw}` is written in a wrong case")) - .span_suggestion( - ident.span, - "write it in the correct case", - kw, - Applicability::MachineApplicable - ).emit(); - + self.sess.emit_err(errors::KwBadCase { + span: ident.span, + kw: kw.as_str() + }); self.bump(); return true; } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 7a4d53ed8bb..adb0d372a40 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -20,12 +20,10 @@ impl<'a> Parser<'a> { pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool { /// Checks whether the non-terminal may contain a single (non-keyword) identifier. fn may_be_ident(nt: &token::Nonterminal) -> bool { - match *nt { - token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_) => { - false - } - _ => true, - } + !matches!( + *nt, + token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_) + ) } match kind { diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 2246002f5d3..f2422fe307c 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1,6 +1,6 @@ use super::{ForceCollect, Parser, PathStyle, TrailingToken}; use crate::errors::{ - AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed, + self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed, DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt, ExpectedCommaAfterPatternField, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern, PatternOnWrongSideOfAt, RefMutOrderIncorrect, @@ -908,18 +908,13 @@ impl<'a> Parser<'a> { let box_span = self.prev_token.span; if self.isnt_pattern_start() { - self.struct_span_err( - self.token.span, - format!("expected pattern, found {}", super::token_descr(&self.token)), - ) - .span_note(box_span, "`box` is a reserved keyword") - .span_suggestion_verbose( - box_span.shrink_to_lo(), - "escape `box` to use it as an identifier", - "r#", - Applicability::MaybeIncorrect, - ) - .emit(); + let descr = super::token_descr(&self.token); + self.sess.emit_err(errors::BoxNotPat { + span: self.token.span, + kw: box_span, + lo: box_span.shrink_to_lo(), + descr, + }); // We cannot use `parse_pat_ident()` since it will complain `box` // is not an identifier. diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index c25c23d849f..ae73760bd8c 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -8,7 +8,7 @@ use rustc_ast::{ AssocConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, Path, PathSegment, QSelf, }; -use rustc_errors::{pluralize, Applicability, PResult}; +use rustc_errors::{Applicability, PResult}; use rustc_span::source_map::{BytePos, Span}; use rustc_span::symbol::{kw, sym, Ident}; use std::mem; @@ -150,16 +150,13 @@ impl<'a> Parser<'a> { // if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some()) { - parser - .struct_span_err( - path.segments - .iter() - .filter_map(|segment| segment.args.as_ref()) - .map(|arg| arg.span()) - .collect::<Vec<_>>(), - "unexpected generic arguments in path", - ) - .emit(); + let span = path + .segments + .iter() + .filter_map(|segment| segment.args.as_ref()) + .map(|arg| arg.span()) + .collect::<Vec<_>>(); + parser.sess.emit_err(errors::GenericsInPath { span }); } }; @@ -467,23 +464,10 @@ impl<'a> Parser<'a> { // i.e. no multibyte characters, in this range. let span = lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count)); - self.struct_span_err( - span, - &format!( - "unmatched angle bracket{}", - pluralize!(snapshot.unmatched_angle_bracket_count) - ), - ) - .span_suggestion( + self.sess.emit_err(errors::UnmatchedAngle { span, - &format!( - "remove extra angle bracket{}", - pluralize!(snapshot.unmatched_angle_bracket_count) - ), - "", - Applicability::MachineApplicable, - ) - .emit(); + plural: snapshot.unmatched_angle_bracket_count > 1, + }); // Try again without unmatched angle bracket characters. self.parse_angle_args(ty_generics) @@ -620,10 +604,7 @@ impl<'a> Parser<'a> { c.into() } Some(GenericArg::Lifetime(lt)) => { - self.struct_span_err(span, "associated lifetimes are not supported") - .span_label(lt.ident.span, "the lifetime is given here") - .help("if you meant to specify a trait object, write `dyn Trait + 'lifetime`") - .emit(); + self.sess.emit_err(errors::AssocLifetime { span, lifetime: lt.ident.span }); self.mk_ty(span, ast::TyKind::Err).into() } None => { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 400c8dbe9bc..3ceb3a2bef1 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1,7 +1,7 @@ use super::{Parser, PathStyle, TokenType}; use crate::errors::{ - DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType, + self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType, FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NegativeBoundsNotSupported, NegativeBoundsNotSupportedSugg, NestedCVariadicType, @@ -588,20 +588,14 @@ impl<'a> Parser<'a> { // Always parse bounds greedily for better error recovery. if self.token.is_lifetime() { self.look_ahead(1, |t| { - if let token::Ident(symname, _) = t.kind { + if let token::Ident(sym, _) = t.kind { // parse pattern with "'a Sized" we're supposed to give suggestion like // "'a + Sized" - self.struct_span_err( - self.token.span, - &format!("expected `+` between lifetime and {}", symname), - ) - .span_suggestion_verbose( - self.token.span.shrink_to_hi(), - "add `+`", - " +", - Applicability::MaybeIncorrect, - ) - .emit(); + self.sess.emit_err(errors::MissingPlusBounds { + span: self.token.span, + hi: self.token.span.shrink_to_hi(), + sym, + }); } }) } @@ -807,16 +801,11 @@ impl<'a> Parser<'a> { /// Emits an error if any trait bound modifiers were present. fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) { if let Some(span) = modifiers.maybe_const { - self.struct_span_err( - span, - "`~const` may only modify trait bounds, not lifetime bounds", - ) - .emit(); + self.sess.emit_err(errors::TildeConstLifetime { span }); } if let Some(span) = modifiers.maybe { - self.struct_span_err(span, "`?` may only modify trait bounds, not lifetime bounds") - .emit(); + self.sess.emit_err(errors::MaybeLifetime { span }); } } @@ -824,19 +813,14 @@ impl<'a> Parser<'a> { fn recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()> { let inner_span = inner_lo.to(self.prev_token.span); self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; - let mut err = self.struct_span_err( - lo.to(self.prev_token.span), - "parenthesized lifetime bounds are not supported", - ); - if let Ok(snippet) = self.span_to_snippet(inner_span) { - err.span_suggestion_short( - lo.to(self.prev_token.span), - "remove the parentheses", - snippet, - Applicability::MachineApplicable, - ); - } - err.emit(); + let span = lo.to(self.prev_token.span); + let (sugg, snippet) = if let Ok(snippet) = self.span_to_snippet(inner_span) { + (Some(span), snippet) + } else { + (None, String::new()) + }; + + self.sess.emit_err(errors::ParenthesizedLifetime { span, sugg, snippet }); Ok(()) } @@ -857,15 +841,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Const) { let span = self.prev_token.span; self.sess.gated_spans.gate(sym::const_trait_impl, span); - - self.struct_span_err(span, "const bounds must start with `~`") - .span_suggestion( - span.shrink_to_lo(), - "add `~`", - "~", - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() }); Some(span) } else { @@ -944,14 +920,10 @@ impl<'a> Parser<'a> { self.parse_remaining_bounds(bounds, true)?; self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; let sp = vec![lo, self.prev_token.span]; - let sugg = vec![(lo, String::from(" ")), (self.prev_token.span, String::new())]; - self.struct_span_err(sp, "incorrect braces around trait bounds") - .multipart_suggestion( - "remove the parentheses", - sugg, - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(errors::IncorrectBracesTraitBounds { + span: sp, + sugg: errors::IncorrectBracesTraitBoundsSugg { l: lo, r: self.prev_token.span }, + }); } else { self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; } diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 72402a20090..815b7c85679 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -1,6 +1,6 @@ //! Meta-syntax validation logic of attributes for post-expansion. -use crate::parse_in; +use crate::{errors, parse_in}; use rustc_ast::tokenstream::DelimSpan; use rustc_ast::MetaItemKind; @@ -45,7 +45,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta kind: match &item.args { AttrArgs::Empty => MetaItemKind::Word, AttrArgs::Delimited(DelimArgs { dspan, delim, tokens }) => { - check_meta_bad_delim(sess, *dspan, *delim, "wrong meta list delimiters"); + check_meta_bad_delim(sess, *dspan, *delim); let nmis = parse_in(sess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?; MetaItemKind::List(nmis) } @@ -68,7 +68,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta } } else { // The non-error case can happen with e.g. `#[foo = 1+1]`. The error case can - // happen with e.g. `#[foo = include_str!("non-existent-file.rs")]`; in that + // happen with e.g. `#[foo = include_str!("nonexistent-file.rs")]`; in that // case we delay the error because an earlier error will have already been // reported. let msg = format!("unexpected expression: `{}`", pprust::expr_to_string(expr)); @@ -84,19 +84,24 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta }) } -pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) { +pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter) { if let ast::MacDelimiter::Parenthesis = delim { return; } + sess.emit_err(errors::MetaBadDelim { + span: span.entire(), + sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close }, + }); +} - sess.span_diagnostic - .struct_span_err(span.entire(), msg) - .multipart_suggestion( - "the delimiters should be `(` and `)`", - vec![(span.open, "(".to_string()), (span.close, ")".to_string())], - Applicability::MachineApplicable, - ) - .emit(); +pub fn check_cfg_attr_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter) { + if let ast::MacDelimiter::Parenthesis = delim { + return; + } + sess.emit_err(errors::CfgAttrBadDelim { + span: span.entire(), + sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close }, + }); } /// Checks that the given meta-item is compatible with this `AttributeTemplate`. |
