Skip to content

Commit

Permalink
Provide extra note if synthetic type args are specified
Browse files Browse the repository at this point in the history
  • Loading branch information
nbdd0121 committed Feb 26, 2022
1 parent d973b35 commit 6747458
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 49 deletions.
107 changes: 58 additions & 49 deletions compiler/rustc_typeck/src/astconv/generics.rs
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
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
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

0 comments on commit 6747458

Please sign in to comment.