Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 58 additions & 49 deletions compiler/rustc_typeck/src/astconv/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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> {
Expand All @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down