Fix ICE, generalize 'move generics to trait' suggestion for >0 non-rcvr arguments

This commit is contained in:
Michael Goulet 2022-09-05 00:23:02 +00:00
parent b44197abb0
commit bee48e3fdc
5 changed files with 104 additions and 11 deletions

View File

@ -749,23 +749,45 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
fn suggest_moving_args_from_assoc_fn_to_trait_for_method_call(
&self,
err: &mut Diagnostic,
trait_: DefId,
trait_def_id: DefId,
expr: &'tcx hir::Expr<'tcx>,
msg: String,
num_assoc_fn_excess_args: usize,
num_trait_generics_except_self: usize,
) {
if let hir::ExprKind::MethodCall(_, receiver, args, ..) = expr.kind {
assert_eq!(args.len(), 0);
if num_assoc_fn_excess_args == num_trait_generics_except_self {
if let Some(gen_args) = self.gen_args.span_ext()
&& let Ok(gen_args) = self.tcx.sess.source_map().span_to_snippet(gen_args)
&& let Ok(receiver) = self.tcx.sess.source_map().span_to_snippet(receiver.span) {
let sugg = format!("{}::{}::{}({})", self.tcx.item_name(trait_), gen_args, self.tcx.item_name(self.def_id), receiver);
err.span_suggestion(expr.span, msg, sugg, Applicability::MaybeIncorrect);
}
}
let sm = self.tcx.sess.source_map();
let hir::ExprKind::MethodCall(_, rcvr, args, _) = expr.kind else { return; };
if num_assoc_fn_excess_args != num_trait_generics_except_self {
return;
}
let Some(gen_args) = self.gen_args.span_ext() else { return; };
let Ok(generics) = sm.span_to_snippet(gen_args) else { return; };
let Ok(rcvr) = sm.span_to_snippet(
rcvr.span.find_ancestor_inside(expr.span).unwrap_or(rcvr.span)
) else { return; };
let Ok(rest) =
(match args {
[] => Ok(String::new()),
[arg] => sm.span_to_snippet(
arg.span.find_ancestor_inside(expr.span).unwrap_or(arg.span),
),
[first, .., last] => {
let first_span =
first.span.find_ancestor_inside(expr.span).unwrap_or(first.span);
let last_span =
last.span.find_ancestor_inside(expr.span).unwrap_or(last.span);
sm.span_to_snippet(first_span.to(last_span))
}
}) else { return; };
let comma = if args.len() > 0 { ", " } else { "" };
let trait_path = self.tcx.def_path_str(trait_def_id);
let method_name = self.tcx.item_name(self.def_id);
err.span_suggestion(
expr.span,
msg,
format!("{trait_path}::{generics}::{method_name}({rcvr}{comma}{rest})"),
Applicability::MaybeIncorrect,
);
}
/// Suggests to remove redundant argument(s):

View File

@ -0,0 +1,12 @@
pub trait Ice {
fn f(&self, _: ());
}
impl Ice for () {
fn f(&self, _: ()) {}
}
fn main() {
().f::<()>(());
//~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied
}

View File

@ -0,0 +1,17 @@
error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-101421.rs:10:8
|
LL | ().f::<()>(());
| ^------ help: remove these generics
| |
| expected 0 generic arguments
|
note: associated function defined here, with 0 generic parameters
--> $DIR/issue-101421.rs:2:8
|
LL | fn f(&self, _: ());
| ^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0107`.

View File

@ -0,0 +1,18 @@
// Generalizes the suggestion introduced in #100838
trait Foo<T> {
fn bar(&self, _: T);
}
impl Foo<i32> for i32 {
fn bar(&self, x: i32) {
println!("{}", self + x);
}
}
fn main() {
1.bar::<i32>(0);
//~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied
//~| HELP consider moving this generic argument to the `Foo` trait, which takes up to 1 argument
//~| HELP remove these generics
}

View File

@ -0,0 +1,24 @@
error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/move-generic-to-trait-in-method-with-params.rs:14:7
|
LL | 1.bar::<i32>(0);
| ^^^ expected 0 generic arguments
|
note: associated function defined here, with 0 generic parameters
--> $DIR/move-generic-to-trait-in-method-with-params.rs:4:8
|
LL | fn bar(&self, _: T);
| ^^^
help: consider moving this generic argument to the `Foo` trait, which takes up to 1 argument
|
LL | Foo::<i32>::bar(1, 0);
| ~~~~~~~~~~~~~~~~~~~~~
help: remove these generics
|
LL - 1.bar::<i32>(0);
LL + 1.bar(0);
|
error: aborting due to previous error
For more information about this error, try `rustc --explain E0107`.