diff options
Diffstat (limited to 'compiler/rustc_parse/src/parser/item.rs')
-rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 222 |
1 files changed, 98 insertions, 124 deletions
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 6422b8ac1..3783ec41b 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -71,7 +71,7 @@ impl<'a> Parser<'a> { if !self.eat(term) { let token_str = super::token_descr(&self.token); if !self.maybe_consume_incorrect_semicolon(&items) { - let msg = &format!("expected item, found {token_str}"); + let msg = format!("expected item, found {token_str}"); let mut err = self.struct_span_err(self.token.span, msg); let label = if self.is_kw_followed_by_ident(kw::Let) { "consider using `const` or `static` instead of `let` for global variables" @@ -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(), + }); } } @@ -265,6 +265,9 @@ impl<'a> Parser<'a> { // UNION ITEM self.bump(); // `union` self.parse_item_union()? + } else if self.is_builtin() { + // BUILTIN# ITEM + return self.parse_item_builtin(); } else if self.eat_keyword(kw::Macro) { // MACROS 2.0 ITEM self.parse_item_decl_macro(lo)? @@ -310,14 +313,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) => { @@ -441,6 +437,11 @@ impl<'a> Parser<'a> { } } + fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemInfo>> { + // To be expanded + return Ok(None); + } + /// Parses an item macro, e.g., `item!();`. fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> { let path = self.parse_path(PathStyle::Mod)?; // `foo::bar` @@ -450,7 +451,7 @@ impl<'a> Parser<'a> { Ok(args) => { self.eat_semi_for_macro_if_needed(&args); self.complain_if_pub_macro(vis, false); - Ok(MacCall { path, args, prior_type_ascription: self.last_type_ascription }) + Ok(MacCall { path, args }) } Err(mut err) => { @@ -602,10 +603,24 @@ impl<'a> Parser<'a> { let path = match ty_first.kind { // This notably includes paths passed through `ty` macro fragments (#46438). TyKind::Path(None, path) => path, - _ => { - self.sess.emit_err(errors::ExpectedTraitInTraitImplFoundType { - span: ty_first.span, - }); + other => { + if let TyKind::ImplTrait(_, bounds) = other + && let [bound] = bounds.as_slice() + { + // Suggest removing extra `impl` keyword: + // `impl<T: Default> impl Default for Wrapper<T>` + // ^^^^^ + let extra_impl_kw = ty_first.span.until(bound.span()); + self.sess + .emit_err(errors::ExtraImplKeywordInTraitImpl { + extra_impl_kw, + impl_trait_span: ty_first.span + }); + } else { + self.sess.emit_err(errors::ExpectedTraitInTraitImplFoundType { + span: ty_first.span, + }); + } err_path(ty_first.span) } }; @@ -684,7 +699,7 @@ impl<'a> Parser<'a> { // ``` && self .span_to_snippet(self.prev_token.span) - .map_or(false, |snippet| snippet == "}") + .is_ok_and(|snippet| snippet == "}") && self.token.kind == token::Semi; let mut semicolon_span = self.token.span; if !is_unnecessary_semicolon { @@ -795,11 +810,7 @@ impl<'a> Parser<'a> { // Parse optional colon and supertrait bounds. let had_colon = self.eat(&token::Colon); let span_at_colon = self.prev_token.span; - let bounds = if had_colon { - self.parse_generic_bounds(Some(self.prev_token.span))? - } else { - Vec::new() - }; + let bounds = if had_colon { self.parse_generic_bounds()? } else { Vec::new() }; let span_before_eq = self.prev_token.span; if self.eat(&token::Eq) { @@ -809,7 +820,7 @@ impl<'a> Parser<'a> { self.sess.emit_err(errors::BoundsNotAllowedOnTraitAliases { span }); } - let bounds = self.parse_generic_bounds(None)?; + let bounds = self.parse_generic_bounds()?; generics.where_clause = self.parse_where_clause()?; self.expect_semi()?; @@ -890,7 +901,7 @@ impl<'a> Parser<'a> { // Parse optional colon and param bounds. let bounds = - if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() }; + if self.eat(&token::Colon) { self.parse_generic_bounds()? } else { Vec::new() }; let before_where_clause = self.parse_where_clause()?; let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; @@ -963,15 +974,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 +1138,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 } @@ -1282,6 +1284,7 @@ impl<'a> Parser<'a> { } } + let prev_span = self.prev_token.span; let id = self.parse_ident()?; let mut generics = self.parse_generics()?; generics.where_clause = self.parse_where_clause()?; @@ -1293,10 +1296,28 @@ impl<'a> Parser<'a> { (thin_vec![], false) } else { self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()).map_err( - |mut e| { - e.span_label(id.span, "while parsing this enum"); + |mut err| { + err.span_label(id.span, "while parsing this enum"); + if self.token == token::Colon { + let snapshot = self.create_snapshot_for_diagnostic(); + self.bump(); + match self.parse_ty() { + Ok(_) => { + err.span_suggestion_verbose( + prev_span, + "perhaps you meant to use `struct` here", + "struct".to_string(), + Applicability::MaybeIncorrect, + ); + } + Err(e) => { + e.cancel(); + } + } + self.restore_snapshot(snapshot); + } self.recover_stmt(); - e + err }, )? }; @@ -1445,7 +1466,7 @@ impl<'a> Parser<'a> { VariantData::Struct(fields, recovered) } else { let token_str = super::token_descr(&self.token); - let msg = &format!("expected `where` or `{{` after union name, found {token_str}"); + let msg = format!("expected `where` or `{{` after union name, found {token_str}"); let mut err = self.struct_span_err(self.token.span, msg); err.span_label(self.token.span, "expected `where` or `{` after union name"); return Err(err); @@ -1481,7 +1502,7 @@ impl<'a> Parser<'a> { self.eat(&token::CloseDelim(Delimiter::Brace)); } else { let token_str = super::token_descr(&self.token); - let msg = &format!( + let msg = format!( "expected {}`{{` after struct name, found {}", if parsed_where { "" } else { "`where`, or " }, token_str @@ -1618,7 +1639,7 @@ impl<'a> Parser<'a> { let sp = self.prev_token.span.shrink_to_hi(); let mut err = self.struct_span_err( sp, - &format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)), + format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)), ); // Try to recover extra trailing angle brackets @@ -1713,27 +1734,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), @@ -1770,7 +1777,7 @@ impl<'a> Parser<'a> { Ok(_) => { let mut err = self.struct_span_err( lo.to(self.prev_token.span), - &format!("functions are not allowed in {adt_ty} definitions"), + format!("functions are not allowed in {adt_ty} definitions"), ); err.help( "unlike in C++, Java, and C#, functions are declared in `impl` blocks", @@ -1789,7 +1796,7 @@ impl<'a> Parser<'a> { Ok((ident, _)) => { let mut err = self.struct_span_err( lo.with_hi(ident.span.hi()), - &format!("structs are not allowed in {adt_ty} definitions"), + format!("structs are not allowed in {adt_ty} definitions"), ); err.help("consider creating a new `struct` definition instead of nesting"); err @@ -1871,14 +1878,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 +1906,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 +1926,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 +1974,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 +2118,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 { @@ -2289,11 +2265,11 @@ impl<'a> Parser<'a> { err.span_suggestion( self.token.uninterpolated_span(), - &format!("`{original_kw}` already used earlier, remove this one"), + format!("`{original_kw}` already used earlier, remove this one"), "", Applicability::MachineApplicable, ) - .span_note(original_sp, &format!("`{original_kw}` first seen here")); + .span_note(original_sp, format!("`{original_kw}` first seen here")); } // The keyword has not been seen yet, suggest correct placement in the function front matter else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw { @@ -2304,7 +2280,7 @@ impl<'a> Parser<'a> { err.span_suggestion( correct_pos_sp.to(misplaced_qual_sp), - &format!("`{misplaced_qual}` must come before `{current_qual}`"), + format!("`{misplaced_qual}` must come before `{current_qual}`"), format!("{misplaced_qual} {current_qual}"), Applicability::MachineApplicable, ).note("keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`"); @@ -2328,7 +2304,7 @@ impl<'a> Parser<'a> { if matches!(orig_vis.kind, VisibilityKind::Inherited) { err.span_suggestion( sp_start.to(self.prev_token.span), - &format!("visibility `{vs}` must come before `{snippet}`"), + format!("visibility `{vs}` must come before `{snippet}`"), format!("{vs} {snippet}"), Applicability::MachineApplicable, ); @@ -2577,14 +2553,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(_)) + ) } } |