about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-02-26 07:52:41 +0100
committerGitHub <noreply@github.com>2022-02-26 07:52:41 +0100
commit5dcee689d179477175eda68502764afce6ba9caa (patch)
treef789af0fd9bcd377176ce94702ba3a2e763e1133 /compiler
parentbe9b99b0d000d176c6b00180ce98d27fd6de9d48 (diff)
parent674745836cb67756daf2d349bb4028d89014f877 (diff)
downloadrust-5dcee689d179477175eda68502764afce6ba9caa.tar.gz
rust-5dcee689d179477175eda68502764afce6ba9caa.zip
Rollup merge of #93982 - nbdd0121:explicit-generic-args, r=jackh726
Provide extra note if synthetic type args are specified

Implement the unresolved question in #83701 as suggested in https://github.com/rust-lang/rust/pull/86176#discussion_r680613890.

r? ``@jackh726``
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_typeck/src/astconv/generics.rs107
-rw-r--r--compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs20
2 files changed, 78 insertions, 49 deletions
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index b16bf33f06a..a06b37627e3 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -512,61 +512,69 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             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 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             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(),
diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
index b763b51dd01..62f89a2e6cf 100644
--- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
@@ -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 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
         }
     }
 
+    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 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
 
         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 @@ impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
         self.notify(&mut err);
         self.suggest(&mut err);
         self.show_definition(&mut err);
+        self.note_synth_provided(&mut err);
 
         err
     }