Skip to content
Closed
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
9 changes: 9 additions & 0 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1404,6 +1404,15 @@ fn compare_number_of_method_arguments<'tcx>(
potentially_plural_count(trait_number_args, "parameter")
),
);
if let Ok(snip) = tcx.sess.source_map().span_to_snippet(trait_span) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just copies the contents of the parentheses, right? If so, this doesn't take params into account, I think:

trait Foo {
  fn bar<T>(_: T);
}

impl Foo for () {
  fn bar<E>(_: E, _: i32) {}
}

which would suggest changing fn bar<E>(_: T) {}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it would suggest:

error[E0050]: method `bar` has 2 parameters but the declaration in trait `Foo::bar` has 1
 --> params.rs:6:16
  |
2 |   fn bar<T>(_: T);
  |                - trait requires 1 parameter
...
6 |   fn bar<E>(_: E, _: i32) {}
  |                ^^^^^^^^^ expected 1 parameter, found 2
  |
help: modify the signature to match the trait definition
  |
6 |   fn bar<E>(_: T) {}

I think we should suggest it to be fn bar<E>(_: E) {} or fn bar<T>(_: T) {}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, we need to consider cases where the arguments reference generics from the trait:

trait Foo<T> {
  fn foo(_: T);
}

impl Foo<()> for i32 {
  fn foo();
}

Should suggest _: (), not _: T.

let args_suggestion = if trait_number_args != 0 { snip } else { "".to_string() };
err.span_suggestion_verbose(
impl_span,
"modify the signature to match the trait definition",
format!("{}", args_suggestion),
Applicability::HasPlaceholders,
);
}
} else {
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
}
Expand Down
3 changes: 3 additions & 0 deletions tests/ui/error-codes/E0050.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ struct Bar;

impl Foo for Bar {
fn foo(&self) -> bool { true } //~ ERROR E0050
//~| HELP: modify the signature to match the trait definition
fn bar(&self) { } //~ ERROR E0050
//~| HELP: modify the signature to match the trait definition
fn less(&self, x: u8, y: u8, z: u8) { } //~ ERROR E0050
//~| HELP: modify the signature to match the trait definition
}

fn main() {
Expand Down
19 changes: 17 additions & 2 deletions tests/ui/error-codes/E0050.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,39 @@ LL | fn foo(&self, x: u8) -> bool;
...
LL | fn foo(&self) -> bool { true }
| ^^^^^ expected 2 parameters, found 1
|
help: modify the signature to match the trait definition
|
LL | fn foo(&self, x: u8) -> bool { true }
| ~~~~~~~~~~~~

error[E0050]: method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 4
--> $DIR/E0050.rs:11:12
--> $DIR/E0050.rs:12:12
|
LL | fn bar(&self, x: u8, y: u8, z: u8);
| -------------------------- trait requires 4 parameters
...
LL | fn bar(&self) { }
| ^^^^^ expected 4 parameters, found 1
|
help: modify the signature to match the trait definition
|
LL | fn bar(&self, x: u8, y: u8, z: u8) { }
| ~~~~~~~~~~~~~~~~~~~~~~~~~~

error[E0050]: method `less` has 4 parameters but the declaration in trait `Foo::less` has 1
--> $DIR/E0050.rs:12:13
--> $DIR/E0050.rs:14:13
|
LL | fn less(&self);
| ----- trait requires 1 parameter
...
LL | fn less(&self, x: u8, y: u8, z: u8) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 parameter, found 4
|
help: modify the signature to match the trait definition
|
LL | fn less(&self) { }
| ~~~~~

error: aborting due to 3 previous errors

Expand Down
11 changes: 11 additions & 0 deletions tests/ui/impl-trait/in-trait/method-signature-matches.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ LL | fn calm_down_please() -> impl Sized;
...
LL | fn calm_down_please(_: (), _: (), _: ()) {}
| ^^^^^^^^^^^^^^^^ expected 0 parameters, found 3
|
help: modify the signature to match the trait definition
|
LL - fn calm_down_please(_: (), _: (), _: ()) {}
LL + fn calm_down_please(_: ) {}
|

error[E0050]: method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3
--> $DIR/method-signature-matches.rs:38:5
Expand All @@ -59,6 +65,11 @@ LL | fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized;
...
LL | fn come_on_a_little_more_effort() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 3 parameters, found 0
|
help: modify the signature to match the trait definition
|
LL | (), _: (), _: () {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh. That's a bug of my implementation which doesn't consider the impl function being 0 parameters. I'll fix it

| ~~~~~~~~~~~~~~~~

error[E0053]: method `early` has an incompatible type for trait
--> $DIR/method-signature-matches.rs:47:27
Expand Down
1 change: 1 addition & 0 deletions tests/ui/trait-method-number-parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ trait Foo {
impl Foo for i32 {
fn foo(
&mut self, //~ ERROR
//~| HELP: modify the signature to match the trait definition
x: i32,
) {
}
Expand Down
6 changes: 6 additions & 0 deletions tests/ui/trait-method-number-parameters.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ LL | fn foo(&mut self, x: i32, y: i32) -> i32;
| ------------------------- trait requires 3 parameters
...
LL | / &mut self,
LL | |
LL | | x: i32,
| |______________^ expected 3 parameters, found 2
|
help: modify the signature to match the trait definition
|
LL | &mut self, x: i32, y: i32,
| ~~~~~~~~~~~~~~~~~~~~~~~~~

error: aborting due to previous error

Expand Down
1 change: 1 addition & 0 deletions tests/ui/traits/impl-different-num-params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ trait Foo {
impl Foo for isize {
fn bar(&self) -> isize {
//~^ ERROR method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 2
//~| HELP: modify the signature to match the trait definition
*self
}
}
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/traits/impl-different-num-params.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ LL | fn bar(&self, x: usize) -> Self;
...
LL | fn bar(&self) -> isize {
| ^^^^^ expected 2 parameters, found 1
|
help: modify the signature to match the trait definition
|
LL | fn bar(&self, x: usize) -> isize {
| ~~~~~~~~~~~~~~~

error: aborting due to previous error

Expand Down