]> git.lizzy.rs Git - rust.git/commitdiff
Provide extra note if synthetic type args are specified
authorGary Guo <gary@garyguo.net>
Mon, 14 Feb 2022 03:27:33 +0000 (03:27 +0000)
committerGary Guo <gary@garyguo.net>
Sat, 26 Feb 2022 03:21:39 +0000 (03:21 +0000)
compiler/rustc_typeck/src/astconv/generics.rs
compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr

index b16bf33f06abf9a209048967a01614fa37cd25ba..a06b37627e3cadc3961e4a6cf4c45e1f2c7301b2 100644 (file)
@@ -512,61 +512,69 @@ pub(crate) fn check_generic_arg_count(
             explicit_late_bound == ExplicitLateBound::Yes,
         );
 
-        let mut check_types_and_consts =
-            |expected_min, expected_max, provided, params_offset, args_offset| {
-                debug!(
-                    ?expected_min,
-                    ?expected_max,
-                    ?provided,
-                    ?params_offset,
-                    ?args_offset,
-                    "check_types_and_consts"
+        let mut check_types_and_consts = |expected_min,
+                                          expected_max,
+                                          expected_max_with_synth,
+                                          provided,
+                                          params_offset,
+                                          args_offset| {
+            debug!(
+                ?expected_min,
+                ?expected_max,
+                ?provided,
+                ?params_offset,
+                ?args_offset,
+                "check_types_and_consts"
+            );
+            if (expected_min..=expected_max).contains(&provided) {
+                return true;
+            }
+
+            let num_default_params = expected_max - expected_min;
+
+            let gen_args_info = if provided > expected_max {
+                invalid_args.extend(
+                    gen_args.args[args_offset + expected_max..args_offset + provided]
+                        .iter()
+                        .map(|arg| arg.span()),
                 );
-                if (expected_min..=expected_max).contains(&provided) {
-                    return true;
+                let num_redundant_args = provided - expected_max;
+
+                // Provide extra note if synthetic arguments like `impl Trait` are specified.
+                let synth_provided = provided <= expected_max_with_synth;
+
+                GenericArgsInfo::ExcessTypesOrConsts {
+                    num_redundant_args,
+                    num_default_params,
+                    args_offset,
+                    synth_provided,
                 }
+            } else {
+                let num_missing_args = expected_max - provided;
 
-                let num_default_params = expected_max - expected_min;
+                GenericArgsInfo::MissingTypesOrConsts {
+                    num_missing_args,
+                    num_default_params,
+                    args_offset,
+                }
+            };
 
-                let gen_args_info = if provided > expected_max {
-                    invalid_args.extend(
-                        gen_args.args[args_offset + expected_max..args_offset + provided]
-                            .iter()
-                            .map(|arg| arg.span()),
-                    );
-                    let num_redundant_args = provided - expected_max;
+            debug!(?gen_args_info);
 
-                    GenericArgsInfo::ExcessTypesOrConsts {
-                        num_redundant_args,
-                        num_default_params,
-                        args_offset,
-                    }
-                } else {
-                    let num_missing_args = expected_max - provided;
+            WrongNumberOfGenericArgs::new(
+                tcx,
+                gen_args_info,
+                seg,
+                gen_params,
+                params_offset,
+                gen_args,
+                def_id,
+            )
+            .diagnostic()
+            .emit_unless(gen_args.has_err());
 
-                    GenericArgsInfo::MissingTypesOrConsts {
-                        num_missing_args,
-                        num_default_params,
-                        args_offset,
-                    }
-                };
-
-                debug!(?gen_args_info);
-
-                WrongNumberOfGenericArgs::new(
-                    tcx,
-                    gen_args_info,
-                    seg,
-                    gen_params,
-                    params_offset,
-                    gen_args,
-                    def_id,
-                )
-                .diagnostic()
-                .emit_unless(gen_args.has_err());
-
-                false
-            };
+            false
+        };
 
         let args_correct = {
             let expected_min = if infer_args {
@@ -582,6 +590,7 @@ pub(crate) fn check_generic_arg_count(
             check_types_and_consts(
                 expected_min,
                 param_counts.consts + named_type_param_count,
+                param_counts.consts + named_type_param_count + synth_type_param_count,
                 gen_args.num_generic_params(),
                 param_counts.lifetimes + has_self as usize,
                 gen_args.num_lifetime_params(),
index b763b51dd01434050980dd1116cc8eafaaa4f094..62f89a2e6cf88b09e1b5555d6f859bf853d6f4a7 100644 (file)
@@ -84,6 +84,9 @@ pub enum GenericArgsInfo {
         // us infer the position of type and const generic arguments
         // in the angle brackets
         args_offset: usize,
+
+        // if synthetic type arguments (e.g. `impl Trait`) are specified
+        synth_provided: bool,
     },
 }
 
@@ -254,6 +257,13 @@ fn get_num_default_params(&self) -> usize {
         }
     }
 
+    fn is_synth_provided(&self) -> bool {
+        match self.gen_args_info {
+            ExcessTypesOrConsts { synth_provided, .. } => synth_provided,
+            _ => false,
+        }
+    }
+
     // Helper function to choose a quantifier word for the number of expected arguments
     // and to give a bound for the number of expected arguments
     fn get_quantifier_and_bound(&self) -> (&'static str, usize) {
@@ -780,6 +790,15 @@ fn show_definition(&self, err: &mut Diagnostic) {
 
         err.span_note(spans, &msg);
     }
+
+    /// Add note if `impl Trait` is explicitly specified.
+    fn note_synth_provided(&self, err: &mut Diagnostic) {
+        if !self.is_synth_provided() {
+            return;
+        }
+
+        err.note("`impl Trait` cannot be explicitly specified as a generic argument");
+    }
 }
 
 impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
@@ -797,6 +816,7 @@ fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorReported> {
         self.notify(&mut err);
         self.suggest(&mut err);
         self.show_definition(&mut err);
+        self.note_synth_provided(&mut err);
 
         err
     }
index 3add0429d2d5819d44370454d31ab7310a2a77f4..2ae7745c725c1bcfe01676b9d2e5b15bb803bcd3 100644 (file)
@@ -11,6 +11,7 @@ note: function defined here, with 1 generic parameter: `T`
    |
 LL | fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
    |    ^^^ -
+   = note: `impl Trait` cannot be explicitly specified as a generic argument
 
 error: aborting due to previous error