diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 902b4b1a1ecfe..502765e03e764 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -13,7 +13,7 @@ use rustc_ast::walk_list; use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability}; +use rustc_errors::{fluent, IntoDiagnostic}; use rustc_macros::Subdiagnostic; use rustc_parse::validate_attr; use rustc_session::lint::builtin::{ @@ -30,9 +30,6 @@ use std::ops::{Deref, DerefMut}; use crate::errors::*; -const MORE_EXTERN: &str = - "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html"; - /// Is `self` allowed semantically as the first parameter in an `FnDecl`? enum SelfSemantic { Yes, @@ -40,7 +37,7 @@ enum SelfSemantic { } /// What is the context that prevents using `~const`? -enum DisallowTildeConstContext<'a> { +pub(crate) enum DisallowTildeConstContext<'a> { TraitObject, Fn(FnKind<'a>), } @@ -247,10 +244,6 @@ impl<'a> AstValidator<'a> { } } - fn err_handler(&self) -> &rustc_errors::Handler { - &self.session.diagnostic() - } - fn check_lifetime(&self, ident: Ident) { let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty]; if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() { @@ -404,62 +397,46 @@ impl<'a> AstValidator<'a> { } } - fn check_type_no_bounds(&self, bounds: &[GenericBound], ctx: &str) { + fn check_type_no_bounds(&self, bounds: &[GenericBound], create_diag: impl FnOnce(Span) -> D) + where + D: IntoDiagnostic<'a>, + { let span = match bounds { [] => return, [b0] => b0.span(), [b0, .., bl] => b0.span().to(bl.span()), }; - self.err_handler() - .struct_span_err(span, &format!("bounds on `type`s in {} have no effect", ctx)) - .emit(); + self.session.emit_err(create_diag(span)); } fn check_foreign_ty_genericless(&self, generics: &Generics, where_span: Span) { - let cannot_have = |span, descr, remove_descr| { - self.err_handler() - .struct_span_err( - span, - &format!("`type`s inside `extern` blocks cannot have {}", descr), - ) - .span_suggestion( - span, - &format!("remove the {}", remove_descr), - "", - Applicability::MaybeIncorrect, - ) - .span_label(self.current_extern_span(), "`extern` block begins here") - .note(MORE_EXTERN) - .emit(); - }; - if !generics.params.is_empty() { - cannot_have(generics.span, "generic parameters", "generic parameters"); + self.session.emit_err(ForeignTyWithGenericParam { + span: generics.span, + extern_span: self.current_extern_span(), + }); } if !generics.where_clause.predicates.is_empty() { - cannot_have(where_span, "`where` clauses", "`where` clause"); + self.session.emit_err(ForeignTyWithWhereClause { + span: where_span, + extern_span: self.current_extern_span(), + }); } } - fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option) { + fn check_foreign_kind_bodyless( + &self, + ident: Ident, + create_diag: impl FnOnce(Span, Span, Span) -> D, + body: Option, + ) where + D: IntoDiagnostic<'a>, + { let Some(body) = body else { return; }; - self.err_handler() - .struct_span_err(ident.span, &format!("incorrect `{}` inside `extern` block", kind)) - .span_label(ident.span, "cannot have a body") - .span_label(body, "the invalid body") - .span_label( - self.current_extern_span(), - format!( - "`extern` blocks define existing foreign {0}s and {0}s \ - inside of them cannot have a body", - kind - ), - ) - .note(MORE_EXTERN) - .emit(); + self.session.emit_err(create_diag(ident.span, body, self.current_extern_span())); } /// An `fn` in `extern { ... }` cannot have a body `{ ... }`. @@ -467,26 +444,11 @@ impl<'a> AstValidator<'a> { let Some(body) = body else { return; }; - self.err_handler() - .struct_span_err(ident.span, "incorrect function inside `extern` block") - .span_label(ident.span, "cannot have a body") - .span_suggestion( - body.span, - "remove the invalid body", - ";", - Applicability::MaybeIncorrect, - ) - .help( - "you might have meant to write a function accessible through FFI, \ - which can be done by writing `extern fn` outside of the `extern` block", - ) - .span_label( - self.current_extern_span(), - "`extern` blocks define existing foreign functions and functions \ - inside of them cannot have a body", - ) - .note(MORE_EXTERN) - .emit(); + self.session.emit_err(ForeignFnWithBody { + span: ident.span, + body_span: body.span, + extern_span: self.current_extern_span(), + }); } fn current_extern_span(&self) -> Span { @@ -496,34 +458,21 @@ impl<'a> AstValidator<'a> { /// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`. fn check_foreign_fn_headerless(&self, ident: Ident, span: Span, header: FnHeader) { if header.has_qualifiers() { - self.err_handler() - .struct_span_err(ident.span, "functions in `extern` blocks cannot have qualifiers") - .span_label(self.current_extern_span(), "in this `extern` block") - .span_suggestion_verbose( - span.until(ident.span.shrink_to_lo()), - "remove the qualifiers", - "fn ", - Applicability::MaybeIncorrect, - ) - .emit(); + self.session.emit_err(ForeignFnWithQualifier { + span: ident.span, + extern_span: self.current_extern_span(), + replace_span: span.until(ident.span.shrink_to_lo()), + }); } } /// An item in `extern { ... }` cannot use non-ascii identifier. fn check_foreign_item_ascii_only(&self, ident: Ident) { if !ident.as_str().is_ascii() { - let n = 83942; - self.err_handler() - .struct_span_err( - ident.span, - "items in `extern` blocks cannot use non-ascii identifiers", - ) - .span_label(self.current_extern_span(), "in this `extern` block") - .note(&format!( - "this limitation may be lifted in the future; see issue #{} for more information", - n, n, - )) - .emit(); + self.session.emit_err(ForeignItemNonAscii { + span: ident.span, + extern_span: self.current_extern_span(), + }); } } @@ -546,24 +495,19 @@ impl<'a> AstValidator<'a> { for Param { ty, span, .. } in &fk.decl().inputs { if let TyKind::CVarArgs = ty.kind { - self.err_handler() - .struct_span_err( - *span, - "only foreign or `unsafe extern \"C\"` functions may be C-variadic", - ) - .emit(); + self.session.emit_err(ForbiddenCVarArgs { span: *span }); } } } - fn check_item_named(&self, ident: Ident, kind: &str) { + fn check_item_named(&self, ident: Ident, create_diag: impl FnOnce(Span) -> D) + where + D: IntoDiagnostic<'a>, + { if ident.name != kw::Underscore { return; } - self.err_handler() - .struct_span_err(ident.span, &format!("`{}` items in this context need a name", kind)) - .span_label(ident.span, format!("`_` is not a valid name for this `{}` item", kind)) - .emit(); + self.session.emit_err(create_diag(ident.span)); } fn check_nomangle_item_asciionly(&self, ident: Ident, item_span: Span) { @@ -571,76 +515,35 @@ impl<'a> AstValidator<'a> { return; } let head_span = self.session.source_map().guess_head_span(item_span); - struct_span_err!( - self.session, - head_span, - E0754, - "`#[no_mangle]` requires ASCII identifier" - ) - .emit(); + self.session.emit_err(NomangleItemNonAscii { span: head_span }); } fn check_mod_file_item_asciionly(&self, ident: Ident) { if ident.name.as_str().is_ascii() { return; } - struct_span_err!( - self.session, - ident.span, - E0754, - "trying to load file for module `{}` with non-ascii identifier name", - ident.name - ) - .help("consider using `#[path]` attribute to specify filesystem path") - .emit(); + self.session.emit_err(ModFileItemNonAscii { span: ident.span, name: ident.name }); } fn deny_generic_params(&self, generics: &Generics, ident_span: Span) { if !generics.params.is_empty() { - struct_span_err!( - self.session, - generics.span, - E0567, - "auto traits cannot have generic parameters" - ) - .span_label(ident_span, "auto trait cannot have generic parameters") - .span_suggestion( - generics.span, - "remove the parameters", - "", - Applicability::MachineApplicable, - ) - .emit(); + self.session.emit_err(AutoTraitWithGenericParam { span: generics.span, ident_span }); } } - fn emit_e0568(&self, span: Span, ident_span: Span) { - struct_span_err!( - self.session, - span, - E0568, - "auto traits cannot have super traits or lifetime bounds" - ) - .span_label(ident_span, "auto trait cannot have super traits or lifetime bounds") - .span_suggestion( - span, - "remove the super traits or lifetime bounds", - "", - Applicability::MachineApplicable, - ) - .emit(); - } - fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) { if let [.., last] = &bounds[..] { let span = ident_span.shrink_to_hi().to(last.span()); - self.emit_e0568(span, ident_span); + self.session.emit_err(AutoTraitWithSuperTraitOrWhereClause { span, ident_span }); } } fn deny_where_clause(&self, where_clause: &WhereClause, ident_span: Span) { if !where_clause.predicates.is_empty() { - self.emit_e0568(where_clause.span, ident_span); + self.session.emit_err(AutoTraitWithSuperTraitOrWhereClause { + span: where_clause.span, + ident_span, + }); } } @@ -648,20 +551,11 @@ impl<'a> AstValidator<'a> { if !trait_items.is_empty() { let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect(); let total_span = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span); - struct_span_err!( - self.session, + self.session.emit_err(AutoTraitWithAssocItem { spans, - E0380, - "auto traits cannot have associated items" - ) - .span_suggestion( - total_span, - "remove these associated items", - "", - Applicability::MachineApplicable, - ) - .span_label(ident_span, "auto trait cannot have associated items") - .emit(); + replace_span: total_span, + ident_span, + }); } } @@ -704,32 +598,21 @@ impl<'a> AstValidator<'a> { AngleBracketedArg::Constraint(c) => Either::Left(c.span), AngleBracketedArg::Arg(a) => Either::Right(a.span()), }); + let last_arg_span = *arg_spans.last().unwrap(); + let first_constraint_span = constraint_spans[0]; let args_len = arg_spans.len(); - let constraint_len = constraint_spans.len(); + let constraints_len = constraint_spans.len(); // ...and then error: - self.err_handler() - .struct_span_err( - arg_spans.clone(), - "generic arguments must come before the first constraint", - ) - .span_label(constraint_spans[0], &format!("constraint{}", pluralize!(constraint_len))) - .span_label( - *arg_spans.iter().last().unwrap(), - &format!("generic argument{}", pluralize!(args_len)), - ) - .span_labels(constraint_spans, "") - .span_labels(arg_spans, "") - .span_suggestion_verbose( - data.span, - &format!( - "move the constraint{} after the generic argument{}", - pluralize!(constraint_len), - pluralize!(args_len) - ), - self.correct_generic_order_suggestion(&data), - Applicability::MachineApplicable, - ) - .emit(); + self.session.emit_err(GenericArgAfterConstraint { + arg_spans: arg_spans.clone(), + constraint_spans, + last_arg_span, + first_constraint_span, + replace_span: data.span, + args_len, + constraints_len, + correct_order: self.correct_generic_order_suggestion(&data), + }); } fn visit_ty_common(&mut self, ty: &'a Ty) { @@ -737,13 +620,7 @@ impl<'a> AstValidator<'a> { TyKind::BareFn(bfty) => { self.check_fn_decl(&bfty.decl, SelfSemantic::No); Self::check_decl_no_pat(&bfty.decl, |span, _, _| { - struct_span_err!( - self.session, - span, - E0561, - "patterns aren't allowed in function pointer types" - ) - .emit(); + self.session.emit_err(FnPtrTyWithPat { span }); }); self.check_late_bound_lifetime_defs(&bfty.generic_params); if let Extern::Implicit(_) = bfty.ext { @@ -756,13 +633,9 @@ impl<'a> AstValidator<'a> { for bound in bounds { if let GenericBound::Outlives(lifetime) = bound { if any_lifetime_bounds { - struct_span_err!( - self.session, - lifetime.ident.span, - E0226, - "only a single explicit lifetime bound is permitted" - ) - .emit(); + self.session.emit_err(MultipleExplicitLifetimeBound { + span: lifetime.ident.span, + }); break; } any_lifetime_bounds = true; @@ -771,29 +644,15 @@ impl<'a> AstValidator<'a> { } TyKind::ImplTrait(_, bounds) => { if self.is_impl_trait_banned { - struct_span_err!( - self.session, - ty.span, - E0667, - "`impl Trait` is not allowed in path parameters" - ) - .emit(); + self.session.emit_err(ImplTraitTyInPathParam { span: ty.span }); } - if let Some(outer_impl_trait_sp) = self.outer_impl_trait { - struct_span_err!( - self.session, - ty.span, - E0666, - "nested `impl Trait` is not allowed" - ) - .span_label(outer_impl_trait_sp, "outer `impl Trait`") - .span_label(ty.span, "nested `impl Trait` here") - .emit(); + if let Some(outer_span) = self.outer_impl_trait { + self.session.emit_err(ImplTraitTyNested { nested_span: ty.span, outer_span }); } if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) { - self.err_handler().span_err(ty.span, "at least one trait must be specified"); + self.session.emit_err(ImplTraitTyWithoutTraitBound { span: ty.span }); } } _ => {} @@ -814,7 +673,7 @@ impl<'a> AstValidator<'a> { MISSING_ABI, id, span, - "extern declarations without an explicit ABI are deprecated", + fluent::ast_passes_deprecated_extern_missing_abi, BuiltinLintDiagnostics::MissingAbi(span, abi::Abi::FALLBACK), ) } @@ -823,11 +682,7 @@ impl<'a> AstValidator<'a> { /// Checks that generic parameters are in the correct order, /// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`) -fn validate_generic_param_order( - handler: &rustc_errors::Handler, - generics: &[GenericParam], - span: Span, -) { +fn validate_generic_param_order(session: &Session, generics: &[GenericParam], span: Span) { let mut max_param: Option = None; let mut out_of_order = FxHashMap::default(); let mut param_idents = Vec::with_capacity(generics.len()); @@ -886,21 +741,14 @@ fn validate_generic_param_order( ordered_params += ">"; - for (param_ord, (max_param, spans)) in &out_of_order { - let mut err = handler.struct_span_err( - spans.clone(), - &format!( - "{} parameters must be declared prior to {} parameters", - param_ord, max_param, - ), - ); - err.span_suggestion( - span, - "reorder the parameters: lifetimes, then consts and types", - &ordered_params, - Applicability::MachineApplicable, - ); - err.emit(); + for (param_ord, (max_param, spans)) in out_of_order { + session.emit_err(GenericParamWrongOrder { + spans, + param_kind: param_ord, + max_param_kind: max_param, + replace_span: span, + correct_order: ordered_params.clone(), + }); } } } @@ -1014,25 +862,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.with_in_trait_impl(true, Some(*constness), |this| { this.invalid_visibility(&item.vis, None); if let TyKind::Err = self_ty.kind { - this.err_handler() - .struct_span_err( - item.span, - "`impl Trait for .. {}` is an obsolete syntax", - ) - .help("use `auto trait Trait {}` instead") - .emit(); + this.session.emit_err(ObsoleteAutoTraitSyntax { span: item.span }); } if let (&Unsafe::Yes(span), &ImplPolarity::Negative(sp)) = (unsafety, polarity) { - struct_span_err!( - this.session, - sp.to(t.path.span), - E0198, - "negative impls cannot be unsafe" - ) - .span_label(sp, "negative because of this") - .span_label(span, "unsafe because of this") - .emit(); + this.session.emit_err(UnsafeNegativeImpl { + span: sp.to(t.path.span), + negative_span: sp, + unsafe_span: span, + }); } this.visit_vis(&item.vis); @@ -1060,35 +898,27 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self_ty, items: _, }) => { - let error = |annotation_span, annotation| { - let mut err = self.err_handler().struct_span_err( - self_ty.span, - &format!("inherent impls cannot be {}", annotation), - ); - err.span_label(annotation_span, &format!("{} because of this", annotation)); - err.span_label(self_ty.span, "inherent impl for this type"); - err - }; - self.invalid_visibility( &item.vis, Some(InvalidVisibilityNote::IndividualImplItems), ); if let &Unsafe::Yes(span) = unsafety { - error(span, "unsafe").code(error_code!(E0197)).emit(); + self.session + .emit_err(UnsafeInherentImpl { span: self_ty.span, unsafe_span: span }); } if let &ImplPolarity::Negative(span) = polarity { - error(span, "negative").emit(); + self.session + .emit_err(NegativeInherentImpl { span: self_ty.span, negative_span: span }); } if let &Defaultness::Default(def_span) = defaultness { - error(def_span, "`default`") - .note("only trait implementations may be annotated with `default`") - .emit(); + self.session.emit_err(DefaultInherentImpl { + span: self_ty.span, + default_span: def_span, + }); } if let &Const::Yes(span) = constness { - error(span, "`const`") - .note("only trait implementations may be annotated with `const`") - .emit(); + self.session + .emit_err(ConstInherentImpl { span: self_ty.span, const_span: span }); } } ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => { @@ -1130,7 +960,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { Some(InvalidVisibilityNote::IndividualForeignItems), ); if let &Unsafe::Yes(span) = unsafety { - self.err_handler().span_err(span, "extern block cannot be declared unsafe"); + self.session.emit_err(UnsafeExternBlock { span }); } if abi.is_none() { self.maybe_lint_missing_abi(item.span, item.id); @@ -1170,7 +1000,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::Mod(unsafety, mod_kind) => { if let &Unsafe::Yes(span) = unsafety { - self.err_handler().span_err(span, "module cannot be declared unsafe"); + self.session.emit_err(UnsafeModule { span }); } // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584). if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) @@ -1181,7 +1011,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::Union(vdata, ..) => { if vdata.fields().is_empty() { - self.err_handler().span_err(item.span, "unions cannot have zero fields"); + self.session.emit_err(EmptyUnion { span: item.span }); } } ItemKind::Const(def, .., None) => { @@ -1205,16 +1035,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { replace_span: self.ending_semi_or_hi(item.span), }); } - self.check_type_no_bounds(bounds, "this context"); + self.check_type_no_bounds(bounds, |span| TyAliasWithBound { span }); if where_clauses.1.0 { - let mut err = self.err_handler().struct_span_err( - where_clauses.1.1, - "where clauses are not allowed after the type for type aliases", - ); - err.note( - "see issue #89122 for more information", - ); - err.emit(); + self.session.emit_err(TyAliasWithWhereClause { span: where_clauses.1.1 }); } } _ => {} @@ -1240,13 +1063,29 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .. }) => { self.check_defaultness(fi.span, *defaultness); - self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span)); - self.check_type_no_bounds(bounds, "`extern` blocks"); + self.check_foreign_kind_bodyless( + fi.ident, + |span, body_span, extern_span| ForeignTyWithBody { + span, + body_span, + extern_span, + }, + ty.as_ref().map(|b| b.span), + ); + self.check_type_no_bounds(bounds, |span| ForeignTyWithBound { span }); self.check_foreign_ty_genericless(generics, where_clauses.0.1); self.check_foreign_item_ascii_only(fi.ident); } ForeignItemKind::Static(_, _, body) => { - self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span)); + self.check_foreign_kind_bodyless( + fi.ident, + |span, body_span, extern_span| ForeignStaticWithBody { + span, + body_span, + extern_span, + }, + body.as_ref().map(|b| b.span), + ); self.check_foreign_item_ascii_only(fi.ident); } ForeignItemKind::MacCall(..) => {} @@ -1296,18 +1135,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { if let Some(span) = prev_param_default { - let mut err = self.err_handler().struct_span_err( - span, - "generic parameters with a default must be trailing", - ); - err.emit(); + self.session.emit_err(GenericParamWithDefaultNotTrailing { span }); break; } } } } - validate_generic_param_order(self.err_handler(), &generics.params, generics.span); + validate_generic_param_order(self.session, &generics.params, generics.span); for predicate in &generics.where_clause.predicates { if let WherePredicate::EqPredicate(predicate) = predicate { @@ -1331,13 +1166,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match bound { GenericBound::Trait(t, _) => { if !t.bound_generic_params.is_empty() { - struct_span_err!( - self.err_handler(), - t.span, - E0316, - "nested quantification of lifetimes" - ) - .emit(); + self.session.emit_err(LifetimeNestedQuantification { + span: t.span, + }); } } GenericBound::Outlives(_) => {} @@ -1362,32 +1193,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let GenericBound::Trait(poly, modify) = bound { match (ctxt, modify) { (BoundKind::SuperTraits, TraitBoundModifier::Maybe) => { - let mut err = self - .err_handler() - .struct_span_err(poly.span, "`?Trait` is not permitted in supertraits"); - let path_str = pprust::path_to_string(&poly.trait_ref.path); - err.note(&format!("traits are `?{}` by default", path_str)); - err.emit(); + self.session.emit_err(SuperTraitWithMaybe { + span: poly.span, + path_str: pprust::path_to_string(&poly.trait_ref.path), + }); } (BoundKind::TraitObject, TraitBoundModifier::Maybe) => { - let mut err = self.err_handler().struct_span_err( - poly.span, - "`?Trait` is not permitted in trait object types", - ); - err.emit(); + self.session.emit_err(TraitObjectWithMaybe { span: poly.span }); } (_, TraitBoundModifier::MaybeConst) if let Some(reason) = &self.disallow_tilde_const => { - let mut err = self.err_handler().struct_span_err(bound.span(), "`~const` is not allowed here"); - match reason { - DisallowTildeConstContext::TraitObject => err.note("trait objects cannot have `~const` trait bounds"), - DisallowTildeConstContext::Fn(FnKind::Closure(..)) => err.note("closures cannot have `~const` trait bounds"), - DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => err.span_note(ident.span, "this function is not `const`, so it cannot have `~const` trait bounds"), - }; - err.emit(); + self.session.emit_err(ForbiddenMaybeConst { span: bound.span(), reason }); } (_, TraitBoundModifier::MaybeConstMaybe) => { - self.err_handler() - .span_err(bound.span(), "`~const` and `?` are mutually exclusive"); + self.session.emit_err(MaybeConstWithMaybeTrait { span: bound.span() }); } _ => {} } @@ -1426,15 +1244,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .. }) = fk.header() { - self.err_handler() - .struct_span_err( - vec![*cspan, *aspan], - "functions cannot be both `const` and `async`", - ) - .span_label(*cspan, "`const` because of this") - .span_label(*aspan, "`async` because of this") - .span_label(span, "") // Point at the fn header. - .emit(); + self.session.emit_err(ConstAsyncFn { + spans: vec![*cspan, *aspan], + const_span: *cspan, + async_span: *aspan, + fn_span: span, + }); } if let FnKind::Closure(ClosureBinder::For { generic_params, .. }, ..) = fk { @@ -1456,20 +1271,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // Functions without bodies cannot have patterns. if let FnKind::Fn(ctxt, _, sig, _, _, None) = fk { Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| { - let (code, msg, label) = match ctxt { - FnCtxt::Foreign => ( - error_code!(E0130), - "patterns aren't allowed in foreign function declarations", - "pattern not allowed in foreign function", - ), - _ => ( - error_code!(E0642), - "patterns aren't allowed in functions without bodies", - "pattern not allowed in function without body", - ), - }; if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) { if let Some(ident) = ident { + let msg = match ctxt { + FnCtxt::Foreign => fluent::ast_passes_patterns_in_foreign_fns, + _ => fluent::ast_passes_patterns_in_fns_without_body, + }; let diag = BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident); self.lint_buffer.buffer_lint_with_diagnostic( PATTERNS_IN_FNS_WITHOUT_BODY, @@ -1480,11 +1287,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ) } } else { - self.err_handler() - .struct_span_err(span, msg) - .span_label(span, label) - .code(code) - .emit(); + match ctxt { + FnCtxt::Foreign => self.session.emit_err(PatternsInForeignFns { span }), + _ => self.session.emit_err(PatternsInFnsWithoutBody { span }), + }; } }); } @@ -1534,12 +1340,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .. }) => { if ty.is_none() { - self.session.emit_err(AssocTypeWithoutBody { + self.session.emit_err(ImplAssocTyWithoutBody { span: item.span, replace_span: self.ending_semi_or_hi(item.span), }); } - self.check_type_no_bounds(bounds, "`impl`s"); + self.check_type_no_bounds(bounds, |span| ImplAssocTyWithBound { span }); if ty.is_some() { self.check_gat_where( item.id, @@ -1560,7 +1366,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } if let AssocItemKind::Const(..) = item.kind { - self.check_item_named(item.ident, "const"); + self.check_item_named(item.ident, |span| UnnamedAssocConst { span }); } match &item.kind { @@ -1606,129 +1412,120 @@ fn deny_equality_constraints( predicate: &WhereEqPredicate, generics: &Generics, ) { - let mut err = this.err_handler().struct_span_err( - predicate.span, - "equality constraints are not yet supported in `where` clauses", - ); - err.span_label(predicate.span, "not supported"); + let mut err = + EqualityConstraint { span: predicate.span, assoc_constraint_suggestion: Vec::new() }; // Given `::Bar = RhsTy`, suggest `A: Foo`. if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind { - if let TyKind::Path(None, path) = &qself.ty.kind { - match &path.segments[..] { - [PathSegment { ident, args: None, .. }] => { - for param in &generics.params { - if param.ident == *ident { - let param = ident; - match &full_path.segments[qself.position..] { - [PathSegment { ident, args, .. }] => { - // Make a new `Path` from `foo::Bar` to `Foo`. - let mut assoc_path = full_path.clone(); - // Remove `Bar` from `Foo::Bar`. - assoc_path.segments.pop(); - let len = assoc_path.segments.len() - 1; - let gen_args = args.as_deref().cloned(); - // Build ``. - let arg = AngleBracketedArg::Constraint(AssocConstraint { - id: rustc_ast::node_id::DUMMY_NODE_ID, - ident: *ident, - gen_args, - kind: AssocConstraintKind::Equality { - term: predicate.rhs_ty.clone().into(), - }, - span: ident.span, - }); - // Add `` to `Foo`. - match &mut assoc_path.segments[len].args { - Some(args) => match args.deref_mut() { - GenericArgs::Parenthesized(_) => continue, - GenericArgs::AngleBracketed(args) => { - args.args.push(arg); - } - }, - empty_args => { - *empty_args = AngleBracketedArgs { - span: ident.span, - args: vec![arg], - } - .into(); - } + if let TyKind::Path(None, qself_ty_path) = &qself.ty.kind { + if let [PathSegment { ident: qself_ty_ident, args: None, .. }] = + &qself_ty_path.segments[..] + { + if generics.params.iter().any(|param| param.ident == *qself_ty_ident) { + if let [PathSegment { ident: assoc_ty_ident, args: assoc_ty_args, .. }] = + &full_path.segments[qself.position..] + { + // Build ``. + let new_arg = AngleBracketedArg::Constraint(AssocConstraint { + id: rustc_ast::node_id::DUMMY_NODE_ID, + ident: *assoc_ty_ident, + gen_args: assoc_ty_args.as_deref().cloned(), + kind: AssocConstraintKind::Equality { + term: predicate.rhs_ty.clone().into(), + }, + span: assoc_ty_ident.span, + }); + + let bound_opt = { + // Make a new `Path` from `foo::Bar` to `Foo`. + let mut new_bound = full_path.clone(); + // Remove `Bar` from `Foo::Bar`. + new_bound.segments.pop(); + // Add `` to `Foo` if applicable and return. + match &mut new_bound.segments.last_mut().unwrap().args { + Some(args) => match args.deref_mut() { + GenericArgs::Parenthesized(_) => None, + GenericArgs::AngleBracketed(args) => { + args.args.push(new_arg); + Some(new_bound) } - err.span_suggestion_verbose( + }, + empty_args => { + *empty_args = AngleBracketedArgs { + span: assoc_ty_ident.span, + args: vec![new_arg], + } + .into(); + Some(new_bound) + } + } + }; + + if let Some(bound) = bound_opt { + err.assoc_constraint_suggestion.push( + EqualityConstraintToAssocConstraintSuggestion { + assoc_ty: assoc_ty_ident.to_string(), + suggestion: vec![( predicate.span, - &format!( - "if `{}` is an associated type you're trying to set, \ - use the associated type binding syntax", - ident - ), format!( "{}: {}", - param, - pprust::path_to_string(&assoc_path) + qself_ty_ident, + pprust::path_to_string(&bound) ), - Applicability::MaybeIncorrect, - ); - } - _ => {} - }; + )], + }, + ) } } } - _ => {} } } } // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo`. if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind { if let [potential_param, potential_assoc] = &full_path.segments[..] { - for param in &generics.params { - if param.ident == potential_param.ident { - for bound in ¶m.bounds { - if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound - { - if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] { - let assoc = pprust::path_to_string(&ast::Path::from_ident( - potential_assoc.ident, - )); - let ty = pprust::ty_to_string(&predicate.rhs_ty); - let (args, span) = match &trait_segment.args { - Some(args) => match args.deref() { - ast::GenericArgs::AngleBracketed(args) => { - let Some(arg) = args.args.last() else { - continue; - }; - ( - format!(", {} = {}", assoc, ty), - arg.span().shrink_to_hi(), - ) - } - _ => continue, - }, - None => ( - format!("<{} = {}>", assoc, ty), - trait_segment.span().shrink_to_hi(), - ), - }; - err.multipart_suggestion( - &format!( - "if `{}::{}` is an associated type you're trying to set, \ - use the associated type binding syntax", - trait_segment.ident, potential_assoc.ident, - ), - vec![(span, args), (predicate.span, String::new())], - Applicability::MaybeIncorrect, - ); - } + if let Some(param) = + generics.params.iter().find(|param| param.ident == potential_param.ident) + { + for bound in ¶m.bounds { + if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound { + if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] { + let assoc = potential_assoc.ident; + let rhs = pprust::ty_to_string(&predicate.rhs_ty); + let (add_loc, add_str) = match &trait_segment.args { + Some(args) => match args.deref() { + ast::GenericArgs::AngleBracketed(args) => { + let Some(arg) = args.args.last() else { + continue; + }; + ( + arg.span().shrink_to_hi(), + format!(", {} = {}", assoc, rhs), + ) + } + _ => continue, + }, + None => ( + trait_segment.span().shrink_to_hi(), + format!("<{} = {}>", assoc, rhs), + ), + }; + err.assoc_constraint_suggestion.push( + EqualityConstraintToAssocConstraintSuggestion { + assoc_ty: format!("{}::{}", trait_segment.ident, assoc), + suggestion: vec![ + (add_loc, add_str), + (predicate.span, String::new()), + ], + }, + ); } } } } } } - err.note( - "see issue #20041 for more information", - ); - err.emit(); + this.session.emit_err(err); } pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool { diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 09e262452b11d..3e7ac966c30d7 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -1,9 +1,11 @@ //! Errors emitted by ast_passes. +use rustc_ast::{visit::FnKind, ParamKindOrd}; +use rustc_errors::{fluent, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessage}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; -use crate::ast_validation::ForbiddenLetReason; +use crate::ast_validation::{DisallowTildeConstContext, ForbiddenLetReason}; #[derive(Diagnostic)] #[diag(ast_passes_forbidden_let)] @@ -160,8 +162,8 @@ pub struct AssocFnWithoutBody { } #[derive(Diagnostic)] -#[diag(ast_passes_assoc_type_without_body)] -pub struct AssocTypeWithoutBody { +#[diag(ast_passes_impl_assoc_ty_without_body)] +pub struct ImplAssocTyWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " = ;", applicability = "has-placeholders")] @@ -224,3 +226,455 @@ pub enum ExternBlockSuggestion { abi: Symbol, }, } + +#[derive(Diagnostic)] +#[diag(ast_passes_ty_alias_with_bound)] +pub struct TyAliasWithBound { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_foreign_ty_with_bound)] +pub struct ForeignTyWithBound { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_impl_assoc_ty_with_bound)] +pub struct ImplAssocTyWithBound { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_foreign_ty_with_generic_param)] +#[note(more_extern_note)] +pub struct ForeignTyWithGenericParam { + #[primary_span] + #[suggestion(code = "", applicability = "maybe-incorrect")] + pub span: Span, + #[label(extern_block_label)] + pub extern_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_foreign_ty_with_where_clause)] +#[note(more_extern_note)] +pub struct ForeignTyWithWhereClause { + #[primary_span] + #[suggestion(code = "", applicability = "maybe-incorrect")] + pub span: Span, + #[label(extern_block_label)] + pub extern_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_foreign_ty_with_body)] +#[note(more_extern_note)] +pub struct ForeignTyWithBody { + #[primary_span] + #[label] + pub span: Span, + #[label(body_label)] + pub body_span: Span, + #[label(extern_block_label)] + pub extern_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_foreign_static_with_body)] +#[note(more_extern_note)] +pub struct ForeignStaticWithBody { + #[primary_span] + #[label] + pub span: Span, + #[label(body_label)] + pub body_span: Span, + #[label(extern_block_label)] + pub extern_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_foreign_fn_with_body)] +#[help] +#[note(more_extern_note)] +pub struct ForeignFnWithBody { + #[primary_span] + #[label] + pub span: Span, + #[suggestion(code = ";", applicability = "maybe-incorrect")] + pub body_span: Span, + #[label(extern_block_label)] + pub extern_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_foreign_fn_with_qualifier)] +pub struct ForeignFnWithQualifier { + #[primary_span] + pub span: Span, + #[label(extern_block_label)] + pub extern_span: Span, + #[suggestion(style = "verbose", code = "fn ", applicability = "maybe-incorrect")] + pub replace_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_foreign_item_non_ascii)] +#[note] +pub struct ForeignItemNonAscii { + #[primary_span] + pub span: Span, + #[label(extern_block_label)] + pub extern_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_forbidden_c_var_args)] +pub struct ForbiddenCVarArgs { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_unnamed_assoc_const)] +pub struct UnnamedAssocConst { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_nomangle_item_non_ascii, code = "E0754")] +pub struct NomangleItemNonAscii { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_mod_file_item_non_ascii, code = "E0754")] +#[help] +pub struct ModFileItemNonAscii { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_auto_trait_with_generic_param, code = "E0567")] +pub struct AutoTraitWithGenericParam { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub span: Span, + #[label(ident_label)] + pub ident_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_auto_trait_with_super_trait_or_where_clause, code = "E0568")] +pub struct AutoTraitWithSuperTraitOrWhereClause { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub span: Span, + #[label(ident_label)] + pub ident_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_auto_trait_with_assoc_item, code = "E0380")] +pub struct AutoTraitWithAssocItem { + #[primary_span] + pub spans: Vec, + #[suggestion(code = "", applicability = "machine-applicable")] + pub replace_span: Span, + #[label(ident_label)] + pub ident_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_generic_arg_after_constraint)] +pub struct GenericArgAfterConstraint { + #[primary_span] + pub arg_spans: Vec, + #[label(constraints_label)] + pub constraint_spans: Vec, + #[label(last_arg_label)] + pub last_arg_span: Span, + #[label(first_constraint_label)] + pub first_constraint_span: Span, + #[suggestion( + style = "verbose", + code = "{correct_order}", + applicability = "machine-applicable" + )] + pub replace_span: Span, + pub args_len: usize, + pub constraints_len: usize, + pub correct_order: String, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_fn_ptr_ty_with_pat, code = "E0561")] +pub struct FnPtrTyWithPat { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_multiple_explicit_lifetime_bound, code = "E0226")] +pub struct MultipleExplicitLifetimeBound { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_impl_trait_ty_in_path_param, code = "E0667")] +pub struct ImplTraitTyInPathParam { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_impl_trait_ty_nested, code = "E0666")] +pub struct ImplTraitTyNested { + #[primary_span] + #[label(nested_label)] + pub nested_span: Span, + #[label(outer_label)] + pub outer_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_impl_trait_ty_without_trait_bound)] +pub struct ImplTraitTyWithoutTraitBound { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_generic_param_wrong_order)] +pub struct GenericParamWrongOrder { + #[primary_span] + pub spans: Vec, + pub param_kind: ParamKindOrd, + pub max_param_kind: ParamKindOrd, + #[suggestion(code = "{correct_order}", applicability = "machine-applicable")] + pub replace_span: Span, + pub correct_order: String, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_obsolete_auto_trait_syntax)] +#[help] +pub struct ObsoleteAutoTraitSyntax { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_unsafe_negative_impl, code = "E0198")] +pub struct UnsafeNegativeImpl { + #[primary_span] + pub span: Span, + #[label(negative_label)] + pub negative_span: Span, + #[label(unsafe_label)] + pub unsafe_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_unsafe_inherent_impl, code = "E0197")] +pub struct UnsafeInherentImpl { + #[primary_span] + #[label(ty_label)] + pub span: Span, + #[label(unsafe_label)] + pub unsafe_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_negative_inherent_impl)] +pub struct NegativeInherentImpl { + #[primary_span] + #[label(ty_label)] + pub span: Span, + #[label(negative_label)] + pub negative_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_default_inherent_impl)] +#[note] +pub struct DefaultInherentImpl { + #[primary_span] + #[label(ty_label)] + pub span: Span, + #[label(default_label)] + pub default_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_const_inherent_impl)] +#[note] +pub struct ConstInherentImpl { + #[primary_span] + #[label(ty_label)] + pub span: Span, + #[label(const_label)] + pub const_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_unsafe_extern_block)] +pub struct UnsafeExternBlock { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_unsafe_module)] +pub struct UnsafeModule { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_empty_union)] +pub struct EmptyUnion { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_ty_alias_with_where_clause)] +#[note] +pub struct TyAliasWithWhereClause { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_generic_param_with_default_not_trailing)] +pub struct GenericParamWithDefaultNotTrailing { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_lifetime_nested_quantification, code = "E0316")] +pub struct LifetimeNestedQuantification { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_super_trait_with_maybe)] +#[note] +pub struct SuperTraitWithMaybe { + #[primary_span] + pub span: Span, + pub path_str: String, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_trait_object_with_maybe)] +pub struct TraitObjectWithMaybe { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_forbidden_maybe_const)] +pub struct ForbiddenMaybeConst<'a, 'b> { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub(crate) reason: &'a DisallowTildeConstContext<'b>, +} + +impl<'a> AddToDiagnostic for &'a DisallowTildeConstContext<'_> { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { + match self { + DisallowTildeConstContext::TraitObject => { + diag.note(fluent::trait_object); + } + DisallowTildeConstContext::Fn(FnKind::Closure(..)) => { + diag.note(fluent::closure); + } + DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => { + diag.span_note(ident.span, fluent::fn_not_const); + } + } + } +} + +#[derive(Diagnostic)] +#[diag(ast_passes_maybe_const_with_maybe_trait)] +pub struct MaybeConstWithMaybeTrait { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_const_async_fn)] +pub struct ConstAsyncFn { + #[primary_span] + pub spans: Vec, + #[label(const_label)] + pub const_span: Span, + #[label(async_label)] + pub async_span: Span, + #[label(fn_label)] + pub fn_span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_patterns_in_foreign_fns, code = "E0130")] +pub struct PatternsInForeignFns { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_patterns_in_fns_without_body, code = "E0642")] +pub struct PatternsInFnsWithoutBody { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_equality_constraint)] +#[note] +pub struct EqualityConstraint { + #[primary_span] + #[label] + pub span: Span, + #[subdiagnostic] + pub assoc_constraint_suggestion: Vec, +} + +pub struct EqualityConstraintToAssocConstraintSuggestion { + pub assoc_ty: String, + pub suggestion: Vec<(Span, String)>, +} + +impl AddToDiagnostic for EqualityConstraintToAssocConstraintSuggestion { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { + diag.set_arg("assoc_ty", self.assoc_ty); + diag.multipart_suggestion( + fluent::assoc_constraint_suggestion, + self.suggestion, + Applicability::MaybeIncorrect, + ); + } +} diff --git a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl index 5f28839f136d6..a5d83b0c33d26 100644 --- a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl @@ -1,3 +1,6 @@ +-ast_passes_more_extern = + for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + ast_passes_forbidden_let = `let` expressions are not supported here .note = only supported directly in conditions of `if` and `while` expressions @@ -69,7 +72,7 @@ ast_passes_assoc_fn_without_body = associated function in `impl` without body .suggestion = provide a definition for the function -ast_passes_assoc_type_without_body = +ast_passes_impl_assoc_ty_without_body = associated type in `impl` without body .suggestion = provide a definition for the type @@ -90,3 +93,221 @@ ast_passes_fn_without_body = .suggestion = provide a definition for the function ast_passes_extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block + +ast_passes_ty_alias_with_bound = + bounds on `type`s in this context have no effect + +ast_passes_foreign_ty_with_bound = + bounds on `type`s in `extern` blocks have no effect + +ast_passes_impl_assoc_ty_with_bound = + bounds on `type`s in `impl`s have no effect + +ast_passes_foreign_ty_with_generic_param = + `type`s inside `extern` blocks cannot have generic parameters + .suggestion = remove the generic parameters + .extern_block_label = `extern` block begins here + .more_extern_note = {-ast_passes_more_extern} + +ast_passes_foreign_ty_with_where_clause = + `type`s inside `extern` blocks cannot have `where` clauses + .suggestion = remove the `where` clause + .extern_block_label = `extern` block begins here + .more_extern_note = {-ast_passes_more_extern} + +ast_passes_foreign_ty_with_body = + incorrect `type` inside `extern` block + .label = cannot have a body + .body_label = the invalid body + .extern_block_label = `extern` blocks define existing foreign types and types inside of them cannot have a body + .more_extern_note = {-ast_passes_more_extern} + +ast_passes_foreign_static_with_body = + incorrect `static` inside `extern` block + .label = cannot have a body + .body_label = the invalid body + .extern_block_label = `extern` blocks define existing foreign statics and statics inside of them cannot have a body + .more_extern_note = {-ast_passes_more_extern} + +ast_passes_foreign_fn_with_body = + incorrect function inside `extern` block + .label = cannot have a body + .suggestion = remove the invalid body + .help = you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + .extern_block_label = `extern` blocks define existing foreign functions and functions inside of them cannot have a body + .more_extern_note = {-ast_passes_more_extern} + +ast_passes_foreign_fn_with_qualifier = + functions in `extern` blocks cannot have qualifiers + .extern_block_label = in this `extern` block + .suggestion = remove the qualifiers + +ast_passes_foreign_item_non_ascii = + items in `extern` blocks cannot use non-ascii identifiers + .extern_block_label = in this `extern` block + .note = this limitation may be lifted in the future; see issue #83942 for more information + +ast_passes_forbidden_c_var_args = + only foreign or `unsafe extern "C"` functions may be C-variadic + +ast_passes_unnamed_assoc_const = + `const` items in this context need a name + .label = `_` is not a valid name for this `const` item + +ast_passes_nomangle_item_non_ascii = + `#[no_mangle]` requires ASCII identifier + +ast_passes_mod_file_item_non_ascii = + trying to load file for module `{$name}` with non-ascii identifier name + .help = consider using `#[path]` attribute to specify filesystem path + +ast_passes_auto_trait_with_generic_param = + auto traits cannot have generic parameters + .ident_label = auto trait cannot have generic parameters + .suggestion = remove the parameters + +ast_passes_auto_trait_with_super_trait_or_where_clause = + auto traits cannot have super traits or lifetime bounds + .ident_label = auto trait cannot have super traits or lifetime bounds + .suggestion = remove the super traits or lifetime bounds + +ast_passes_auto_trait_with_assoc_item = + auto traits cannot have associated items + .suggestion = remove these associated items + .ident_label = auto trait cannot have associated items + +ast_passes_generic_arg_after_constraint = + generic arguments must come before the first constraint + .first_constraint_label = { $constraints_len -> + [one] constraint + *[other] constraints + } + .last_arg_label = { $args_len -> + [one] generic argument + *[other] generic arguments + } + .constraints_label = {""} + .args_label = {""} + .suggestion = move the { $constraints_len -> + [one] constraint + *[other] constraints + } after the { $args_len -> + [one] generic argument + *[other] generic arguments + } + +ast_passes_fn_ptr_ty_with_pat = + patterns aren't allowed in function pointer types + +ast_passes_multiple_explicit_lifetime_bound = + only a single explicit lifetime bound is permitted + +ast_passes_impl_trait_ty_in_path_param = + `impl Trait` is not allowed in path parameters + +ast_passes_impl_trait_ty_nested = + nested `impl Trait` is not allowed + .outer_label = outer `impl Trait` + .nested_label = nested `impl Trait` here + +ast_passes_impl_trait_ty_without_trait_bound = + at least one trait must be specified + +ast_passes_deprecated_extern_missing_abi = + extern declarations without an explicit ABI are deprecated + +ast_passes_generic_param_wrong_order = + { $param_kind -> + [lifetime] lifetime + *[type_or_const] type and const + } parameters must be declared prior to { $max_param_kind -> + [lifetime] lifetime + *[type_or_const] type and const + } parameters + .suggestion = reorder the parameters: lifetimes, then consts and types + +ast_passes_obsolete_auto_trait_syntax = + `impl Trait for .. {"{}"}` is an obsolete syntax + .help = use `auto trait Trait {"{}"}` instead + +ast_passes_unsafe_negative_impl = + negative impls cannot be unsafe + .negative_label = negative because of this + .unsafe_label = unsafe because of this + +ast_passes_unsafe_inherent_impl = + inherent impls cannot be unsafe + .unsafe_label = unsafe because of this + .ty_label = inherent impl for this type + +ast_passes_negative_inherent_impl = + inherent impls cannot be negative + .negative_label = negative because of this + .ty_label = inherent impl for this type + +ast_passes_default_inherent_impl = + inherent impls cannot be `default` + .default_label = `default` because of this + .ty_label = inherent impl for this type + .note = only trait implementations may be annotated with `default` + +ast_passes_const_inherent_impl = + inherent impls cannot be `const` + .const_label = `const` because of this + .ty_label = inherent impl for this type + .note = only trait implementations may be annotated with `const` + +ast_passes_unsafe_extern_block = + extern block cannot be declared unsafe + +ast_passes_unsafe_module = + module cannot be declared unsafe + +ast_passes_empty_union = + unions cannot have zero fields + +ast_passes_ty_alias_with_where_clause = + where clauses are not allowed after the type for type aliases + .note = see issue #89122 for more information + +ast_passes_generic_param_with_default_not_trailing = + generic parameters with a default must be trailing + +ast_passes_lifetime_nested_quantification = + nested quantification of lifetimes + +ast_passes_super_trait_with_maybe = + `?Trait` is not permitted in supertraits + .note = traits are `?{$path_str}` by default + +ast_passes_trait_object_with_maybe = + `?Trait` is not permitted in trait object types + +ast_passes_forbidden_maybe_const = + `~const` is not allowed here + .trait_object = trait objects cannot have `~const` trait bounds + .closure = closures cannot have `~const` trait bounds + .fn_not_const = this function is not `const`, so it cannot have `~const` trait bounds + +ast_passes_maybe_const_with_maybe_trait = + `~const` and `?` are mutually exclusive + +ast_passes_const_async_fn = + functions cannot be both `const` and `async` + .const_label = `const` because of this + .async_label = `async` because of this + .fn_label = {""} + +ast_passes_patterns_in_foreign_fns = + patterns aren't allowed in foreign function declarations + .label = pattern not allowed in foreign function + +ast_passes_patterns_in_fns_without_body = + patterns aren't allowed in functions without bodies + .label = pattern not allowed in function without body + +ast_passes_equality_constraint = + equality constraints are not yet supported in `where` clauses + .label = not supported + .assoc_constraint_suggestion = if `{$assoc_ty}` is an associated type you're trying to set, use the associated type binding syntax + .note = see issue #20041 for more information diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index dad5e98aac021..d902d261122b6 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -147,6 +147,15 @@ impl IntoDiagnosticArg for hir::ConstContext { } } +impl IntoDiagnosticArg for ast::ParamKindOrd { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Borrowed(match self { + ast::ParamKindOrd::Lifetime => "lifetime", + ast::ParamKindOrd::TypeOrConst => "type_or_const", + })) + } +} + impl IntoDiagnosticArg for ast::Path { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(&self)))