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``
This commit is contained in:
Matthias Krüger 2022-02-26 07:52:41 +01:00 committed by GitHub
commit 5dcee689d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 51 deletions

View file

@ -512,62 +512,70 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
explicit_late_bound == ExplicitLateBound::Yes, explicit_late_bound == ExplicitLateBound::Yes,
); );
let mut check_types_and_consts = let mut check_types_and_consts = |expected_min,
|expected_min, expected_max, provided, params_offset, args_offset| { expected_max,
debug!( expected_max_with_synth,
?expected_min, provided,
?expected_max, params_offset,
?provided, args_offset| {
?params_offset, debug!(
?args_offset, ?expected_min,
"check_types_and_consts" ?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) { let num_redundant_args = provided - expected_max;
return true;
// 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,
let gen_args_info = if provided > expected_max { num_default_params,
invalid_args.extend( args_offset,
gen_args.args[args_offset + expected_max..args_offset + provided] }
.iter()
.map(|arg| arg.span()),
);
let num_redundant_args = provided - expected_max;
GenericArgsInfo::ExcessTypesOrConsts {
num_redundant_args,
num_default_params,
args_offset,
}
} else {
let num_missing_args = expected_max - provided;
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
}; };
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
};
let args_correct = { let args_correct = {
let expected_min = if infer_args { let expected_min = if infer_args {
0 0
@ -582,6 +590,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
check_types_and_consts( check_types_and_consts(
expected_min, expected_min,
param_counts.consts + named_type_param_count, param_counts.consts + named_type_param_count,
param_counts.consts + named_type_param_count + synth_type_param_count,
gen_args.num_generic_params(), gen_args.num_generic_params(),
param_counts.lifetimes + has_self as usize, param_counts.lifetimes + has_self as usize,
gen_args.num_lifetime_params(), gen_args.num_lifetime_params(),

View file

@ -84,6 +84,9 @@ pub enum GenericArgsInfo {
// us infer the position of type and const generic arguments // us infer the position of type and const generic arguments
// in the angle brackets // in the angle brackets
args_offset: usize, 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 // Helper function to choose a quantifier word for the number of expected arguments
// and to give a bound 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) { fn get_quantifier_and_bound(&self) -> (&'static str, usize) {
@ -780,6 +790,15 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
err.span_note(spans, &msg); 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> { impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
@ -797,6 +816,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
self.notify(&mut err); self.notify(&mut err);
self.suggest(&mut err); self.suggest(&mut err);
self.show_definition(&mut err); self.show_definition(&mut err);
self.note_synth_provided(&mut err);
err err
} }

View file

@ -11,6 +11,7 @@ note: function defined here, with 1 generic parameter: `T`
| |
LL | fn foo<T: ?Sized>(_f: impl AsRef<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 error: aborting due to previous error