diff --git a/Cargo.lock b/Cargo.lock index 3a35985836c..cb245ce0ff8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3595,6 +3595,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", + "rustc_macros", "rustc_parse", "rustc_session", "rustc_span", diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 22742b2adbd..37eff9207c1 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -11,6 +11,7 @@ rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } +rustc_macros = { path = "../rustc_macros" } rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index e61dfef7bd3..f8eca6a9337 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -27,6 +27,8 @@ use rustc_target::spec::abi; use std::mem; use std::ops::{Deref, DerefMut}; +use crate::errors::ForbiddenLet; + const MORE_EXTERN: &str = "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html"; @@ -117,23 +119,7 @@ impl<'a> AstValidator<'a> { /// Emits an error banning the `let` expression provided in the given location. fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) { - let err = "`let` expressions are not supported here"; - let mut diag = self.session.struct_span_err(expr.span, err); - diag.note("only supported directly in conditions of `if` and `while` expressions"); - match forbidden_let_reason { - ForbiddenLetReason::GenericForbidden => {} - ForbiddenLetReason::NotSupportedOr(span) => { - diag.span_note(span, "`||` operators are not supported in let chain expressions"); - } - ForbiddenLetReason::NotSupportedParentheses(span) => { - diag.span_note( - span, - "`let`s wrapped in parentheses are not supported in a context with let \ - chains", - ); - } - } - diag.emit(); + self.session.emit_err(ForbiddenLet { span: expr.span, reason: forbidden_let_reason }); } fn check_gat_where( @@ -1876,7 +1862,7 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> /// Used to forbid `let` expressions in certain syntactic locations. #[derive(Clone, Copy)] -enum ForbiddenLetReason { +pub(crate) enum ForbiddenLetReason { /// `let` is not valid and the source environment is not important GenericForbidden, /// A let chain with the `||` operator diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs new file mode 100644 index 00000000000..397acd3b609 --- /dev/null +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -0,0 +1,32 @@ +//! Errors emitted by ast_passes. + +use rustc_errors::fluent; +use rustc_errors::{AddSubdiagnostic, Diagnostic}; +use rustc_macros::SessionDiagnostic; +use rustc_span::Span; + +use crate::ast_validation::ForbiddenLetReason; + +#[derive(SessionDiagnostic)] +#[error(ast_passes::forbidden_let)] +#[note] +pub struct ForbiddenLet { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub(crate) reason: ForbiddenLetReason, +} + +impl AddSubdiagnostic for ForbiddenLetReason { + fn add_to_diagnostic(self, diag: &mut Diagnostic) { + match self { + Self::GenericForbidden => {} + Self::NotSupportedOr(span) => { + diag.span_note(span, fluent::ast_passes::not_supported_or); + } + Self::NotSupportedParentheses(span) => { + diag.span_note(span, fluent::ast_passes::not_supported_parentheses); + }, + } + } +} diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 2bc3b6f3616..6a826298985 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -12,6 +12,7 @@ #![recursion_limit = "256"] pub mod ast_validation; +mod errors; pub mod feature_gate; pub mod node_count; pub mod show_span; diff --git a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl new file mode 100644 index 00000000000..4f4235b6c81 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl @@ -0,0 +1,5 @@ +ast_passes_forbidden_let = + `let` expressions are not supported here + .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 diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index ee978f04be2..3569c7f0630 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -32,6 +32,7 @@ pub use unic_langid::{langid, LanguageIdentifier}; // Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module. fluent_messages! { + ast_passes => "../locales/en-US/ast_passes.ftl", borrowck => "../locales/en-US/borrowck.ftl", builtin_macros => "../locales/en-US/builtin_macros.ftl", const_eval => "../locales/en-US/const_eval.ftl",