diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index b16bf33f06abf..a06b37627e3ca 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 b763b51dd0143..62f89a2e6cf88 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 } diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr index 3add0429d2d58..2ae7745c725c1 100644 --- a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr +++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr @@ -11,6 +11,7 @@ note: function defined here, with 1 generic parameter: `T` | LL | fn foo(_f: impl AsRef) {} | ^^^ - + = note: `impl Trait` cannot be explicitly specified as a generic argument error: aborting due to previous error