diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index f8eca6a9337..fee876489f7 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, pluralize, struct_span_err, Applicability, Diagnostic}; +use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability, Diagnostic}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::{ DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY, @@ -27,7 +27,7 @@ use rustc_target::spec::abi; use std::mem; use std::ops::{Deref, DerefMut}; -use crate::errors::ForbiddenLet; +use crate::errors::*; const MORE_EXTERN: &str = "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html"; @@ -149,7 +149,7 @@ impl<'a> AstValidator<'a> { DEPRECATED_WHERE_CLAUSE_LOCATION, id, where_clauses.0.1, - "where clause not allowed here", + fluent::ast_passes::deprecated_where_clause_location, BuiltinLintDiagnostics::DeprecatedWhereclauseLocation( where_clauses.1.1.shrink_to_hi(), suggestion, @@ -179,10 +179,7 @@ impl<'a> AstValidator<'a> { AssocConstraintKind::Equality { .. } => {} AssocConstraintKind::Bound { .. } => { if self.is_assoc_ty_bound_banned { - self.err_handler().span_err( - constraint.span, - "associated type bounds are not allowed within structs, enums, or unions", - ); + self.session.emit_err(ForbiddenAssocConstraint { span: constraint.span }); } } } @@ -254,31 +251,26 @@ impl<'a> AstValidator<'a> { 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() { - self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names"); + self.session.emit_err(KeywordLifetime { span: ident.span }); } } fn check_label(&self, ident: Ident) { if ident.without_first_quote().is_reserved() { - self.err_handler() - .span_err(ident.span, &format!("invalid label name `{}`", ident.name)); + self.session.emit_err(InvalidLabel { span: ident.span, name: ident.name }); } } - fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) { + fn invalid_visibility(&self, vis: &Visibility, note: Option) { if let VisibilityKind::Inherited = vis.kind { return; } - let mut err = - struct_span_err!(self.session, vis.span, E0449, "unnecessary visibility qualifier"); - if vis.kind.is_pub() { - err.span_label(vis.span, "`pub` not permitted here because it's implied"); - } - if let Some(note) = note { - err.note(note); - } - err.emit(); + self.session.emit_err(InvalidVisibility { + span: vis.span, + implied: if vis.kind.is_pub() { Some(vis.span) } else { None }, + note, + }); } fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option, bool)) { @@ -1154,7 +1146,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.invalid_visibility( &item.vis, - Some("place qualifiers on individual impl items instead"), + Some(InvalidVisibilityNote::IndividualImplItems), ); if let Unsafe::Yes(span) = unsafety { error(span, "unsafe").code(error_code!(E0197)).emit(); @@ -1222,7 +1214,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { let old_item = mem::replace(&mut self.extern_mod, Some(item)); self.invalid_visibility( &item.vis, - Some("place qualifiers on individual foreign items instead"), + Some(InvalidVisibilityNote::IndividualForeignItems), ); if let Unsafe::Yes(span) = unsafety { self.err_handler().span_err(span, "extern block cannot be declared unsafe"); diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 397acd3b609..0d5a41771ea 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -2,8 +2,8 @@ use rustc_errors::fluent; use rustc_errors::{AddSubdiagnostic, Diagnostic}; -use rustc_macros::SessionDiagnostic; -use rustc_span::Span; +use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; +use rustc_span::{Span, Symbol}; use crate::ast_validation::ForbiddenLetReason; @@ -30,3 +30,44 @@ impl AddSubdiagnostic for ForbiddenLetReason { } } } + +#[derive(SessionDiagnostic)] +#[error(ast_passes::forbidden_assoc_constraint)] +pub struct ForbiddenAssocConstraint { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(ast_passes::keyword_lifetime)] +pub struct KeywordLifetime { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(ast_passes::invalid_label)] +pub struct InvalidLabel { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[error(ast_passes::invalid_visibility, code = "E0449")] +pub struct InvalidVisibility { + #[primary_span] + pub span: Span, + #[label(ast_passes::implied)] + pub implied: Option, + #[subdiagnostic] + pub note: Option, +} + +#[derive(SessionSubdiagnostic)] +pub enum InvalidVisibilityNote { + #[note(ast_passes::individual_impl_items)] + IndividualImplItems, + #[note(ast_passes::individual_foreign_items)] + IndividualForeignItems, +} 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 4f4235b6c81..153a91cc7e2 100644 --- a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl @@ -3,3 +3,21 @@ ast_passes_forbidden_let = .note = only supported directly in conditions of `if` and `while` expressions .not_supported_or = `||` operators are not supported in let chain expressions .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains + +ast_passes_deprecated_where_clause_location = + where clause not allowed here + +ast_passes_forbidden_assoc_constraint = + associated type bounds are not allowed within structs, enums, or unions + +ast_passes_keyword_lifetime = + lifetimes cannot use keyword names + +ast_passes_invalid_label = + invalid label name `{$name}` + +ast_passes_invalid_visibility = + unnecessary visibility qualifier + .implied = `pub` not permitted here because it's implied + .individual_impl_items = place qualifiers on individual impl items instead + .individual_foreign_items = place qualifiers on individual foreign items instead diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 32b653f669b..609a7894d86 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -537,7 +537,7 @@ impl LintBuffer { lint: &'static Lint, id: NodeId, sp: impl Into, - msg: &str, + msg: impl Into, ) { self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal) } @@ -547,7 +547,7 @@ impl LintBuffer { lint: &'static Lint, id: NodeId, sp: impl Into, - msg: &str, + msg: impl Into, diagnostic: BuiltinLintDiagnostics, ) { self.add_lint(lint, id, sp.into(), msg, diagnostic)