Improve E0277 for imperfect derives - #158764
Conversation
|
r? @khyperia rustbot has assigned @khyperia. Use Why was this reviewer chosen?The reviewer was selected based on:
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
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>,
}| 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`", |
There was a problem hiding this comment.
I'm not sure about recommending all these crates. If I'm honest it makes me a bit uncomfortable.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Not mentioning specific crates might be best... But there's precedent in mentioning some (async-trait comes to mind).
| "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/>", | ||
| ); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
"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.
|
Reminder, once the PR becomes ready for a review, use |
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 |
|
@rustbot ready |
|
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. |
@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 |
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 |
|
I thing requirement is clear: we should only emit this prose if all fields of the struct actually implement the trait independent of @estebank, given that this expands the scope to more involved traint evaluation check, do u agree with this ? if yes, should i move ahead? |
|
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 |
There was a problem hiding this comment.
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)...
5e8fee9 to
c02f727
Compare
|
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. |
|
@bors r+ Let's keep the ticket open to address the more accurate targeting, but in the meantime lets merge the wording changes. |
Improve E0277 for imperfect derives Relates to rust-lang#157117
I updated it to |
|
⌛ Testing commit c02f727 with merge 84d065e... Workflow: https://github.com/rust-lang/rust/actions/runs/29442115239 |
Improve E0277 for imperfect derives Relates to #157117
|
@bors yield |
|
Auto build was cancelled. Cancelled workflows: The next pull request likely to be tested is #159350. |
|
⌛ Testing commit c02f727 with merge c827f63... Workflow: https://github.com/rust-lang/rust/actions/runs/29442932447 |
Improve E0277 for imperfect derives Relates to #157117
|
@bors yield |
|
Auto build was cancelled. Cancelled workflows: The next pull request likely to be tested is #159350. |
View all comments
Relates to #157117