diff --git a/Cargo.lock b/Cargo.lock index cb245ce0ff82..40583d7ae966 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3575,6 +3575,7 @@ dependencies = [ "rustc_errors", "rustc_hir", "rustc_index", + "rustc_macros", "rustc_middle", "rustc_query_system", "rustc_session", diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 39ba62ef2ffc..474aff2e2aac 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -15,6 +15,7 @@ rustc_target = { path = "../rustc_target" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } rustc_middle = { path = "../rustc_middle" } +rustc_macros = { path = "../rustc_macros" } rustc_query_system = { path = "../rustc_query_system" } rustc_span = { path = "../rustc_span" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs new file mode 100644 index 000000000000..8701491c9eb3 --- /dev/null +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -0,0 +1,29 @@ +use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic}; +use rustc_macros::SessionDiagnostic; +use rustc_span::Span; + +#[derive(SessionDiagnostic, Clone, Copy)] +#[error(ast_lowering::generic_type_with_parentheses, code = "E0214")] +pub struct GenericTypeWithParentheses { + #[primary_span] + #[label] + pub span: Span, + #[subdiagnostic] + pub sub: Option, +} + +#[derive(Clone, Copy)] +pub struct UseAngleBrackets { + pub open_param: Span, + pub close_param: Span, +} + +impl AddSubdiagnostic for UseAngleBrackets { + fn add_to_diagnostic(self, diag: &mut Diagnostic) { + diag.multipart_suggestion( + fluent::ast_lowering::use_angle_brackets, + vec![(self.open_param, String::from("<")), (self.close_param, String::from(">"))], + Applicability::MaybeIncorrect, + ); + } +} diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1ac1d689efbd..c1d9a7e690e6 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -75,6 +75,7 @@ macro_rules! arena_vec { mod asm; mod block; +mod errors; mod expr; mod index; mod item; diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 393be3b454c3..5874d08a94fe 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -1,11 +1,11 @@ use crate::ImplTraitPosition; +use super::errors::{GenericTypeWithParentheses, UseAngleBrackets}; use super::ResolverAstLoweringExt; use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs}; use super::{ImplTraitContext, LoweringContext, ParamMode}; use rustc_ast::{self as ast, *}; -use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::GenericArg; @@ -185,7 +185,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> hir::PathSegment<'hir> { debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,); let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args { - let msg = "parenthesized type parameters may only be used with a `Fn` trait"; match **generic_args { GenericArgs::AngleBracketed(ref data) => { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) @@ -193,10 +192,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), ParenthesizedGenericArgs::Err => { - let mut err = struct_span_err!(self.tcx.sess, data.span, E0214, "{}", msg); - err.span_label(data.span, "only `Fn` traits may use parentheses"); // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait` - if !data.inputs.is_empty() { + let sub = if !data.inputs.is_empty() { // Start of the span to the 1st character of 1st argument let open_param = data.inputs_span.shrink_to_lo().to(data .inputs @@ -212,16 +209,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .span .shrink_to_hi() .to(data.inputs_span.shrink_to_hi()); - err.multipart_suggestion( - &format!("use angle brackets instead",), - vec![ - (open_param, String::from("<")), - (close_param, String::from(">")), - ], - Applicability::MaybeIncorrect, - ); - } - err.emit(); + + Some(UseAngleBrackets { open_param, close_param }) + } else { + None + }; + self.tcx.sess.emit_err(GenericTypeWithParentheses { span: data.span, sub }); ( self.lower_angle_bracketed_parameter_data( &data.as_angle_bracketed_args(), diff --git a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl b/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl new file mode 100644 index 000000000000..ac7fc37e37dd --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl @@ -0,0 +1,5 @@ +ast_lowering_generic_type_with_parentheses = + parenthesized type parameters may only be used with a `Fn` trait + .label = only `Fn` traits may use parentheses + +ast_lowering_use_angle_brackets = use angle brackets instead diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 3569c7f06306..31455d47698c 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_lowering => "../locales/en-US/ast_lowering.ftl", ast_passes => "../locales/en-US/ast_passes.ftl", borrowck => "../locales/en-US/borrowck.ftl", builtin_macros => "../locales/en-US/builtin_macros.ftl",