From cd03fe18d8a24434c1510d08c88231fbe9d6b8bf Mon Sep 17 00:00:00 2001 From: EdwinRy Date: Thu, 2 Jun 2022 18:22:25 +0100 Subject: [PATCH] Suggest replace parentheses with angle brackets --- compiler/rustc_ast_lowering/src/lib.rs | 46 +++++++++++++++---- .../gat-trait-path-parenthesised-args.rs | 5 ++ .../gat-trait-path-parenthesised-args.stderr | 31 ++++++++++++- 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e59bc9aa6b399..2a41aeca8d7ec 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -46,7 +46,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_errors::struct_span_err; +use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{DefId, DefPathHash, LocalDefId, CRATE_DEF_ID}; @@ -901,7 +901,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { mut itctx: ImplTraitContext<'_, 'hir>, ) -> hir::TypeBinding<'hir> { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); - // lower generic arguments of identifier in constraint let gen_args = if let Some(ref gen_args) = constraint.gen_args { let gen_args_ctor = match gen_args { @@ -914,12 +913,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .0 } GenericArgs::Parenthesized(ref data) => { - let mut err = self.sess.struct_span_err( - gen_args.span(), - "parenthesized generic arguments cannot be used in associated type constraints" - ); - // FIXME: try to write a suggestion here - err.emit(); + self.assoc_ty_contraint_param_error_emit(data); self.lower_angle_bracketed_parameter_data( &data.as_angle_bracketed_args(), ParamMode::Explicit, @@ -1033,6 +1027,42 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } + fn assoc_ty_contraint_param_error_emit(&self, data: &ParenthesizedArgs) -> () { + let mut err = self.sess.struct_span_err( + data.span, + "parenthesized generic arguments cannot be used in associated type constraints", + ); + // Suggest removing empty parentheses: "Trait()" -> "Trait" + if data.inputs.is_empty() { + let parentheses_span = + data.inputs_span.shrink_to_lo().to(data.inputs_span.shrink_to_hi()); + err.multipart_suggestion( + "remove these parentheses", + vec![(parentheses_span, String::new())], + Applicability::MaybeIncorrect, + ); + } + // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait` + else { + // Start of parameters to the 1st argument + let open_param = data.inputs_span.shrink_to_lo().to(data + .inputs + .first() + .unwrap() + .span + .shrink_to_lo()); + // End of last argument to end of parameters + let close_param = + data.inputs.last().unwrap().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(); + } + fn lower_generic_arg( &mut self, arg: &ast::GenericArg, diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs index f01da8c61ed1d..c55b0530c9da8 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs +++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs @@ -10,4 +10,9 @@ fn foo<'a>(arg: Box>) {} //~| ERROR this associated type takes 0 generic arguments but 1 generic argument //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + +fn bar<'a>(arg: Box>) {} + //~^ ERROR: parenthesized generic arguments cannot be used + //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + fn main() {} diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr index 6014a02c4d96f..162214063e7d2 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr +++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr @@ -9,6 +9,19 @@ error: parenthesized generic arguments cannot be used in associated type constra | LL | fn foo<'a>(arg: Box>) {} | ^^^^^ + | +help: use angle brackets instead + | +LL | fn foo<'a>(arg: Box = &'a ()>>) {} + | ~ ~ + +error: parenthesized generic arguments cannot be used in associated type constraints + --> $DIR/gat-trait-path-parenthesised-args.rs:14:27 + | +LL | fn bar<'a>(arg: Box>) {} + | ^-- + | | + | help: remove these parentheses error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied --> $DIR/gat-trait-path-parenthesised-args.rs:7:27 @@ -40,6 +53,22 @@ note: associated type defined here, with 0 generic parameters LL | type Y<'a>; | ^ -error: aborting due to 4 previous errors +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/gat-trait-path-parenthesised-args.rs:14:27 + | +LL | fn bar<'a>(arg: Box>) {} + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-parenthesised-args.rs:4:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn bar<'a>(arg: Box>) {} + | ++ + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0107`.