Skip to content

Provide more context when an expected type was a type parameter - #160180

Merged
rust-bors[bot] merged 9 commits into
rust-lang:mainfrom
estebank:issue-67991
Nov 1, 2026
Merged

rust-bors[bot] merged 9 commits into
rust-lang:mainfrom
estebank:issue-67991

Conversation

@estebank

@estebank estebank commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

View all comments

This becomes particularly confusing when a type parameter has a default.

error[E0053]: method `foo` has an incompatible type for trait
  --> $DIR/default-type-parameter.rs:8:17
   |
LL | impl Trait for S {
LL |     fn foo() -> u32 { 0 }
   |                 ^^^ expected `()`, found `u32`
   |
note: type in trait
  --> $DIR/default-type-parameter.rs:2:17
   |
LL | trait Trait<T = ()> {
   |             ------ expected to match the default of type parameter `T`
LL |     fn foo() -> T;
   |                 ^
   = note: expected signature `fn() -> ()`
              found signature `fn() -> u32`
help: change the output type to match the trait
   |
LL -     fn foo() -> u32 { 0 }
LL +     fn foo() -> () { 0 }
   |

Fix #67991.

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 29, 2026
@rust-bors

This comment has been minimized.

@estebank
estebank marked this pull request as ready for review October 5, 2026 20:01
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 5, 2026
@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Oct 5, 2026
@rustbot

rustbot commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

r? @tiif

rustbot has assigned @tiif.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 77 candidates
  • Random selection from 19 candidates

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@tiif tiif left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for working on this! I have some non-blocking style nits that I think might be good to have. I am currently reading the code closely, it might take a few days, so I am releasing these comments for earlier feedback.

View changes since this review

--> $DIR/defaults-specialization.rs:8:18
|
LL | trait Tr {
...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

non-blocking style nit: will it be possible to have...?

    LL | trait Tr {
       |  ...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That change is something to bring up to rust-lang/annotate-snippets-rs. I don't think that rendering is necessarily ideal, because it would be hard to differentiate between the actual code being

trait Tr {
 ...

and

trait Tr {
// this like will be skipped by the diagnostic renderer and replaced with ` ...`

By having it on the other side of the gutter, it makes that a bit clearer.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see, makes sense.

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 19, 2026
@rustbot

rustbot commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@rustbot

This comment has been minimized.

@estebank estebank added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 20, 2026

@tiif tiif left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for waiting. I just have a few more questions.

View changes since this review

&& let param = generics.type_param(*param, tcx)
&& let GenericParamDefKind::Type { has_default: true, .. } = param.kind
{
context.push(tcx.def_span(trait_m.container_id(tcx)).shrink_to_lo());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What does this context do? Removing this line doesn't seem to change any test.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It will ensure that line that starts the containing trait will be displayed. It would only happen with weirdly formatted code or really long signatures.

&& p.name == kw::SelfUpper
&& infcx.can_eq(param_env, *ty, impl_trait_ref.self_ty())
{
format!("expected to match the `Self` default of type parameter `{param_name}`")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We seem to not have test for this, could you help to add one?

trait_err_span.map(|sp| {
let mut span: MultiSpan = sp.into();
span.push_span_context(tcx.def_span(trait_m.container_id(tcx)).shrink_to_lo());
span.push_span_context(tcx.def_span(trait_m.def_id).shrink_to_lo());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This also doesn't seem to change anything when removed. What is the intention of adding this line?

--> $DIR/defaults-specialization.rs:8:18
|
LL | trait Tr {
...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see, makes sense.

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 25, 2026
This becomes particularly confusing when a type parameter has a default.

```
  --> $DIR/default-type-parameter.rs:8:17
   |
LL |     fn foo() -> u32 { 0 }
   |                 ^^^ expected `()`, found `u32`
   |
note: type in trait
  --> $DIR/default-type-parameter.rs:2:17
   |
LL |     fn foo() -> T;
   |                 ^
   = note: expected signature `fn() -> ()`
              found signature `fn() -> u32`
note: expected to match this type parameter
  --> $DIR/default-type-parameter.rs:1:13
   |
LL | trait Trait<T = ()> {
   |             ^^^^^^
help: change the output type to match the trait
   |
LL -     fn foo() -> u32 { 0 }
LL +     fn foo() -> () { 0 }
```
…the trait

```
error[E0053]: method `foo` has an incompatible type for trait
  --> $DIR/async-example-desugared-boxed-in-trait.rs:11:28
   |
LL | impl MyTrait for i32 {
LL |     async fn foo(&self) -> i32 {
   |                            ^^^ expected `Pin<Box<dyn Future<Output = i32>>>`, found future
   |
note: type in trait
  --> $DIR/async-example-desugared-boxed-in-trait.rs:7:22
   |
LL | trait MyTrait {
LL |     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: expected signature `fn(&_) -> Pin<Box<dyn Future<Output = i32>>>`
              found signature `fn(&_) -> impl Future<Output = i32>`
```
…type in trait" note

```
error[E0053]: method `foo` has an incompatible type for trait
  --> $DIR/default-type-parameter.rs:8:17
   |
LL | impl Trait for S {
LL |     fn foo() -> u32 { 0 }
   |                 ^^^ expected `()`, found `u32`
   |
note: type in trait
  --> $DIR/default-type-parameter.rs:2:17
   |
LL | trait Trait<T = ()> {
   |             ------ expected to match the default of type parameter `T`
LL |     fn foo() -> T;
   |                 ^
   = note: expected signature `fn() -> ()`
              found signature `fn() -> u32`
help: change the output type to match the trait
   |
LL -     fn foo() -> u32 { 0 }
LL +     fn foo() -> () { 0 }
   |
```
@rustbot

rustbot commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@estebank

Copy link
Copy Markdown
Contributor Author

@tiff modified a few tests to exercise the new logic. The context spans are not always needed under normally formatted code, but for more convoluted/long code the thing being pointed at is not on the same line as the item itself, which makes it harder to understand what part of the code the compiler is talking about at a glance. Ensuring the item is in view, helps to disambiguate, specially when there are many types or traits that have associated items with the same name.

Comment on lines +11 to +17
LL | trait Trait<
LL | T = (),
| ------ expected to match the default of type parameter `T`
...
LL | fn foo()
LL | -> T;
| ^

@estebank estebank Oct 25, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is an example of the context spans actually doing something.

View changes since the review

Comment on lines +39 to +40
LL | K = Self,
| -------- expected to match the `Self` default of type parameter `K`

@estebank estebank Oct 25, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm surprised I even wrote logic for this case without a test. Good catch. IIRC, it is a common case for the math traits like Add<Rhs = Self>.

View changes since the review

@estebank estebank added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 26, 2026

@tiif tiif left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The context span stuff is interesting to know, thank you! I pushed a commit to fix a typo to avoid another round of review cycle. It's time to land this.

@bors r+ rollup

View changes since this review

@rust-bors

rust-bors Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 9ec7923 has been tentatively approved by tiif

It will be put into the queue for this repository once PR CI succeeds.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 1, 2026
rust-bors Bot pushed a commit that referenced this pull request Nov 1, 2026
…uwer

Rollup of 6 pull requests

Successful merges:

 - #138143 (rustdoc: add unstable option `--crate-list-heading` to customize the sidebar crate list.)
 - #165251 (Restore aarch64-apple-1 jobs with free disk space)
 - #160180 (Provide more context when an expected type was a type parameter)
 - #165262 (Replace `AbiAlign` with `Align` in function returns)
 - #165265 (Bless mir-opt tests again, again)
 - #165266 (Revert recent changes to async_drop)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Nov 1, 2026
Provide more context when an expected type was a type parameter

This becomes particularly confusing when a type parameter has a default.

```
error[E0053]: method `foo` has an incompatible type for trait
  --> $DIR/default-type-parameter.rs:8:17
   |
LL | impl Trait for S {
LL |     fn foo() -> u32 { 0 }
   |                 ^^^ expected `()`, found `u32`
   |
note: type in trait
  --> $DIR/default-type-parameter.rs:2:17
   |
LL | trait Trait<T = ()> {
   |             ------ expected to match the default of type parameter `T`
LL |     fn foo() -> T;
   |                 ^
   = note: expected signature `fn() -> ()`
              found signature `fn() -> u32`
help: change the output type to match the trait
   |
LL -     fn foo() -> u32 { 0 }
LL +     fn foo() -> () { 0 }
   |
```
Fix rust-lang#67991.
@rust-bors
rust-bors Bot merged commit c1afed8 into rust-lang:main Nov 1, 2026
14 checks passed
@rustbot rustbot added this to the 1.101.0 milestone Nov 1, 2026
rust-bors Bot pushed a commit that referenced this pull request Nov 1, 2026
Rollup merge of #160180 - estebank:issue-67991, r=tiif

Provide more context when an expected type was a type parameter

This becomes particularly confusing when a type parameter has a default.

```
error[E0053]: method `foo` has an incompatible type for trait
  --> $DIR/default-type-parameter.rs:8:17
   |
LL | impl Trait for S {
LL |     fn foo() -> u32 { 0 }
   |                 ^^^ expected `()`, found `u32`
   |
note: type in trait
  --> $DIR/default-type-parameter.rs:2:17
   |
LL | trait Trait<T = ()> {
   |             ------ expected to match the default of type parameter `T`
LL |     fn foo() -> T;
   |                 ^
   = note: expected signature `fn() -> ()`
              found signature `fn() -> u32`
help: change the output type to match the trait
   |
LL -     fn foo() -> u32 { 0 }
LL +     fn foo() -> () { 0 }
   |
```
Fix #67991.
DaniPopes pushed a commit to DaniPopes/rustc_codegen_cranelift that referenced this pull request Nov 4, 2026
…uwer

Rollup of 6 pull requests

Successful merges:

 - rust-lang/rust#138143 (rustdoc: add unstable option `--crate-list-heading` to customize the sidebar crate list.)
 - rust-lang/rust#165251 (Restore aarch64-apple-1 jobs with free disk space)
 - rust-lang/rust#160180 (Provide more context when an expected type was a type parameter)
 - rust-lang/rust#165262 (Replace `AbiAlign` with `Align` in function returns)
 - rust-lang/rust#165265 (Bless mir-opt tests again, again)
 - rust-lang/rust#165266 (Revert recent changes to async_drop)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incompatible type error should explain when types come from default type parameters

4 participants