about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs46
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs5
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr31
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 e59bc9aa6b3..2a41aeca8d7 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<params...>`
+        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 f01da8c61ed..c55b0530c9d 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<dyn X<Y('a) = &'a ()>>) {}
   //~| 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<dyn X<Y() = ()>>) {}
+  //~^ 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 6014a02c4d9..162214063e7 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<dyn X<Y('a) = &'a ()>>) {}
    |                           ^^^^^
+   |
+help: use angle brackets instead
+   |
+LL | fn foo<'a>(arg: Box<dyn X<Y<'a> = &'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<dyn X<Y() = ()>>) {}
+   |                           ^--
+   |                            |
+   |                            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<dyn X<Y() = ()>>) {}
+   |                           ^ 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<dyn X<Y('a) = ()>>) {}
+   |                             ++
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0107`.