Skip to content

Improve E0277 for imperfect derives - #158764

Merged
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
raushan728:issues/157117
Jul 15, 2026
Merged

Improve E0277 for imperfect derives#158764
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
raushan728:issues/157117

Conversation

@raushan728

@raushan728 raushan728 commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 4, 2026
@rustbot

rustbot commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

r? @khyperia

rustbot has assigned @khyperia.
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 75 candidates
  • Random selection from 22 candidates

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@mejrs mejrs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think we should be dropping this "perfect derive" prose on every trait bound error. Certainly not for the linked example.

Some examples where it would be appropriate are:

#[derive(Debug)]
struct S<T>{
    spooky: PhantomData<T>,
}

or

#[derive(Clone)]
struct S<T>{
   stufff: Arc<T>,
}

View changes since this review

err.help(format!(
"consider manually implementing `{trait_name}` to avoid undesired \
bounds",
"consider manually implementing `{trait_name}` to avoid undesired bounds caused by \"imperfect derives\", or using a crate like `derive-where`, `derivative` or `perfect_derive`",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not sure about recommending all these crates. If I'm honest it makes me a bit uncomfortable.

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 agree that avoiding specific crate endorsements aligns better with general rustc diagnostic practices. I'll remove them once we confirm the final wording with @estebank.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not mentioning specific crates might be best... But there's precedent in mentioning some (async-trait comes to mind).

Comment on lines +4257 to +4258
"to learn more, visit <https://github.com/rust-lang/rust/issues/26925> and <https://smallcultfollowing.com/babysteps//blog/2022/04/12/implied-bounds-and-perfect-derive/>",
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same for these links. I'd lean towards just briefly explaining why there's a T: Trait bound introduced by the derive, name drop "perfect derive" and let the user google it for themselves.

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.

Briefly explaining the bound and name dropping "perfect derive" for users to search sounds like a much cleaner approach. I'll update the diagnostic to do this once we have consensus on the scope.

@estebank estebank Jul 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

At the very least, lets link to the issue (the ideal situation would be for the dev guide or some other "official" page to have literally the same info as niko's blog).

Edit: I do feel comfortable with linking to niko's blog, at least for now, though. He himself might not :)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

"perfect derive" is like "turbofish" in that it's very google-able, so there is limited value in providing a link to one particular resource. And while Niko's blog is very well written and fun to read it doesn't actually help with making your code compile.

@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 4, 2026
@rustbot

rustbot commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

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

@rustbot rustbot added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jul 4, 2026
@raushan728

Copy link
Copy Markdown
Contributor Author

I don't think we should be dropping this "perfect derive" prose on every trait bound error. Certainly not for the linked example.

Some examples where it would be appropriate are:

#[derive(Debug)]
struct S<T>{
    spooky: PhantomData<T>,
}

or

#[derive(Clone)]
struct S<T>{
   stufff: Arc<T>,
}

View changes since this review

I understand ur concerns about restricting this proce to actual imperfect cases, and avoiding specific crate endorsement or external URLs in the compiler output.

I implemented it this way beacouse I strictly followed the S<T>(T) example and the exact desired output in that issue. Since there is a design difference here regarding filtering logic and diagnostic, I'd love to both of ur thoughts to reach a consensus before I update. @estebank

@raushan728

Copy link
Copy Markdown
Contributor Author

@rustbot ready

@rustbot rustbot 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 Jul 5, 2026
@khyperia

khyperia commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

thanks for looking into this! ✨

(just chiming in as the randomly-assigned reviewer, mostly to acknowledge that I've seen this - someone like estebank might be a more appropriate reviewer) - I agree with @mejrs that it would be unfortunate to talk about the difference between perfect and imperfect derives in error messages in situations where there is no difference between the two (e.g. struct S<T>(T)). Happy to wait for estebank to chime in though!

@mejrs

mejrs commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

I understand ur concerns about restricting this proce to actual imperfect cases

@estebank I'd like to build some consensus on this. I would only like to see this diagnostic if "perfect derive" would actually solve their problem. In impl terms, we would only mention it if for each field existed an impl regardless of T, like impl <T> Clone for Arc<T> or impl <T> Debug for Phantomdata<T>

@khyperia

khyperia commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

In impl terms, we would only mention it if for each field existed an impl regardless of T

I'm guessing folks are already aware, but just saying it out loud as an fyi: it's not just blanket impls regardless of T, associated types also are relevant here:

trait Trait {
    type Assoc: Clone;
}

#[derive(Clone)]
struct S<T: Trait> {
    field: T::Assoc,
}

struct NonClone;

impl Trait for NonClone {
    type Assoc = u32;
}

fn main() {
    let x: S<NonClone> = S { field: 2 };
    let _y = x.clone();
    //~^ ERROR the method `clone` exists for struct `S<NonClone>`, but its trait bounds were not satisfied
}

// however, manually writing it works fine:
// impl<T: Trait> Clone for S<T> {
//     fn clone(&self) -> Self {
//         Self {
//             field: self.field.clone(),
//         }
//     }
// }

edit: I suppose you could view this as "an impl existing regardless of T", the field of type T::Assoc does indeed have an impl of Clone regardless of T (via the bounds of T::Assoc: Clone)

@raushan728

Copy link
Copy Markdown
Contributor Author

I thing requirement is clear: we should only emit this prose if all fields of the struct actually implement the trait independent of T itself. Implementing this filtering logic inside diagnostic reporting would require Inspecting the struct definition, iterating over its fields, and evaluating trait obligation for each field's type without strictly binding T.

@estebank, given that this expands the scope to more involved traint evaluation check, do u agree with this ? if yes, should i move ahead?

@raushan728 raushan728 changed the title fix(diagnostics): improve E0277 for imperfect derives Improve E0277 for imperfect derives Jul 9, 2026
@khyperia

Copy link
Copy Markdown
Contributor

apologies, I've fallen ill and probably won't get around to reviewing this for a while, so I'm just assigning this to estebank

r? estebank

@rustbot rustbot assigned estebank and unassigned khyperia Jul 13, 2026

@estebank estebank left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Apologies for the delay.

Let's change the wording slightly and not mention explicit crates, nor niko's blogpost (but keep the perfect derive info and tracking issue).

given that this expands the scope to more involved traint evaluation check, do u agree with this ? if yes, should i move ahead?

Only if you feel up to it, experience and time wise. Bruno's concerns around showing the wording only when strictly relevant are well founded, we don't want to lead people astray. On the other hand, I think we could land the wording changes only (we already tell people to manually implement the trait from the bound without really checking if that would solve the problem)...

View changes since this review

Comment thread compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs Outdated
Comment thread compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs Outdated
@rustbot

rustbot commented Jul 15, 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.

@raushan728
raushan728 requested review from estebank and mejrs July 15, 2026 12:12
@estebank

Copy link
Copy Markdown
Contributor

@bors r+

Let's keep the ticket open to address the more accurate targeting, but in the meantime lets merge the wording changes.

@rust-bors

rust-bors Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

📌 Commit c02f727 has been approved by estebank

It is now in the queue for this repository.

@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 Jul 15, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 15, 2026
@raushan728

raushan728 commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Let's keep the ticket open to address the more accurate targeting, but in the meantime lets merge the wording changes.

I updated it to Relates to since Addresses makes it seem like all the work is done, which isn't the case yet.🙂

@rust-bors

rust-bors Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

⌛ Testing commit c02f727 with merge 84d065e...

Workflow: https://github.com/rust-lang/rust/actions/runs/29442115239

rust-bors Bot pushed a commit that referenced this pull request Jul 15, 2026
Improve E0277 for imperfect derives



Relates to #157117
@JonathanBrouwer

Copy link
Copy Markdown
Contributor

@bors yield
Yielding to enclosing rollup

@rust-bors

rust-bors Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Auto build was cancelled. Cancelled workflows:

The next pull request likely to be tested is #159350.

rust-bors Bot pushed a commit that referenced this pull request Jul 15, 2026
…uwer

Rollup of 2 pull requests

Successful merges:

 - #158764 (Improve E0277 for imperfect derives)
 - #159345 (std: upgrade `addr2line`, `object`, `miniz_oxide`)
@rust-bors

rust-bors Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

⌛ Testing commit c02f727 with merge c827f63...

Workflow: https://github.com/rust-lang/rust/actions/runs/29442932447

rust-bors Bot pushed a commit that referenced this pull request Jul 15, 2026
Improve E0277 for imperfect derives



Relates to #157117
@JonathanBrouwer

Copy link
Copy Markdown
Contributor

@bors yield
Yielding to enclosing rollup

@rust-bors

rust-bors Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Auto build was cancelled. Cancelled workflows:

The next pull request likely to be tested is #159350.

rust-bors Bot pushed a commit that referenced this pull request Jul 15, 2026
…uwer

Rollup of 2 pull requests

Successful merges:

 - #158764 (Improve E0277 for imperfect derives)
 - #159345 (std: upgrade `addr2line`, `object`, `miniz_oxide`)
@rust-bors
rust-bors Bot merged commit ed2989e into rust-lang:main Jul 15, 2026
13 of 14 checks passed
@rustbot rustbot added this to the 1.99.0 milestone Jul 15, 2026
@raushan728
raushan728 deleted the issues/157117 branch July 16, 2026 03:50
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.

7 participants