Skip to content

Provide more context on trait bounds being unmet due to imperfect derive#151278

Merged
rust-bors[bot] merged 17 commits intorust-lang:mainfrom
estebank:issue-108894
Feb 6, 2026
Merged

Provide more context on trait bounds being unmet due to imperfect derive#151278
rust-bors[bot] merged 17 commits intorust-lang:mainfrom
estebank:issue-108894

Conversation

@estebank
Copy link
Contributor

@estebank estebank commented Jan 18, 2026

When encountering a value that has a borrow checker error where the type was previously moved, when suggesting cloning verify that it is not already being derived. If it is, explain why the derive(Clone) doesn't apply:

note: if `TypedAddress<T>` implemented `Clone`, you could clone the value
  --> $DIR/derive-clone-implicit-bound.rs:6:1
   |
LL | #[derive(Clone, Copy)]
   |          ----- derived `Clone` adds implicit bounds on type parameters
LL | pub struct TypedAddress<T>{
   | ^^^^^^^^^^^^^^^^^^^^^^^^-^
   | |                       |
   | |                       introduces an implicit `T: Clone` bound
   | consider manually implementing `Clone` for this type
...
LL |         let old = self.return_value(offset);
   |                                     ------ you could clone this value

When encountering a bound coming from a derive macro, suggest manual impl of the trait.

Use the span for the specific param when adding bounds in builtin derive macros, so the diagnostic will point at them as well as the derive macro itself.

note: required for `Id<SomeNode>` to implement `PartialEq`
  --> $DIR/derive-implicit-bound.rs:5:10
   |
LL | #[derive(PartialEq, Eq)]
   |          ^^^^^^^^^
LL | pub struct Id<T>(PhantomData<T>);
   |               - unsatisfied trait bound introduced in this `derive` macro
   = help: consider manually implementing `PartialEq` to avoid undesired bounds

Mention that the trait could be manually implemented in E0599.

Fix #108894. Address #143714. Address ##146515 (but ideally would also suggest constraining the fn bound correctly as well).

@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 Jan 18, 2026
@rustbot
Copy link
Collaborator

rustbot commented Jan 18, 2026

r? @davidtwco

rustbot has assigned @davidtwco.
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

@rust-log-analyzer

This comment has been minimized.

@fmease
Copy link
Member

fmease commented Jan 18, 2026

CC another related issue: #146515. This one won't be fixed by your PR IINM but we might be able to leverage & reuse some of your added logic to do so (disclaimer: I've only skimmed your PR, so I might be wrong).

There's a PR open to fix said issue, namely #150720, but your approach might be more general and could supersede it.

@estebank
Copy link
Contributor Author

estebank commented Jan 18, 2026

@fmease for that case, what do you think of output like

error[E0308]: mismatched types
 --> f30.rs:9:5
  |
8 | fn clone_me<T, K>(x: &ContainsRc<T, K>) -> ContainsRc<T, K> {
  |                                            ---------------- expected `ContainsRc<T, K>` because of return type
9 |     x.clone()
  |     -^^^^^^^^
  |     |
  |     expected `ContainsRc<T, K>`, found `&ContainsRc<T, K>`
  |     `ContainsRc<T, K>` does not implement `Clone`, so `&ContainsRc<T, K>` was cloned instead
  |
  = note: expected struct `ContainsRc<_, _>`
          found reference `&ContainsRc<_, _>`
help: `Clone` is not implemented because the following trait bounds could not be satisfied
 --> f30.rs:4:19
  |
3 | #[derive(Clone)]
  |          ----- in this derive macro expansion
4 | struct ContainsRc<T, K> {
  |                   ^  ^ derive introduces an implicit unsatisfied trait bound `K: Clone`
  |                   |
  |                   derive introduces an implicit unsatisfied trait bound `T: Clone`
  = help: consider manually implementing `Clone`

@rust-log-analyzer

This comment has been minimized.

@rustbot rustbot added the WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) label Jan 18, 2026
@estebank
Copy link
Contributor Author

David: I can split the PR into smaller ones as needed (it's just they touch the same stderr files so it was easier to keep it as a single patchset). Each commit is logically grouped.

@rust-log-analyzer

This comment has been minimized.

@rustbot
Copy link
Collaborator

rustbot commented Jan 18, 2026

HIR ty lowering was modified

cc @fmease

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

Copy link
Member

@davidtwco davidtwco left a comment

Choose a reason for hiding this comment

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

Implementation largely looks good to me, some thoughts on the new suggestions more generally

View changes since this review

When encountering a value that has a borrow checker error where the type was previously moved, when suggesting cloning verify that it is not already being derived. If it is, explain why the `derive(Clone)` doesn't apply:

```
note: if `TypedAddress<T>` implemented `Clone`, you could clone the value
  --> $DIR/derive-clone-implicit-bound.rs:6:1
   |
LL | #[derive(Clone, Copy)]
   |          ----- derived `Clone` adds implicit bounds on type parameters
LL | pub struct TypedAddress<T>{
   | ^^^^^^^^^^^^^^^^^^^^^^^^-^
   | |                       |
   | |                       introduces an implicit `T: Clone` bound
   | consider manually implementing `Clone` for this type
...
LL |         let old = self.return_value(offset);
   |                                     ------ you could clone this value
```
When encountering a bound coming from a derive macro, suggest manual impl of the trait.

Use the span for the specific param when adding bounds in builtin derive macros, so the diagnostic will point at them as well as the derive macro itself.

```
error[E0277]: can't compare `SomeNode` with `SomeNode`
  --> f29.rs:24:15
   |
24 |     accept_eq(&node);
   |     --------- ^^^^^ no implementation for `SomeNode == SomeNode`
   |     |
   |     required by a bound introduced by this call
   |
   = note: -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs:279:39
   = help: the trait `PartialEq` is not implemented for `SomeNode`
note: required for `Id<SomeNode>` to implement `PartialEq`
  --> f29.rs:3:10
   |
 3 | #[derive(PartialEq, Eq)]
   |          ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
 4 | pub struct Id<T>(PhantomData<T>);
   |               -
   = help: consider manually implementing `PartialEq` to avoid undesired bounds
note: required by a bound in `accept_eq`
  --> f29.rs:15:23
   |
15 | fn accept_eq(_: &impl PartialEq) { }
   |                       ^^^^^^^^^ required by this bound in `accept_eq`
help: consider annotating `SomeNode` with `#[derive(PartialEq)]`
   |
13 + #[derive(PartialEq)]
14 | struct SomeNode();
   |
```
```
note: required for `B<C>` to implement `Copy`
  --> $DIR/deriving-copyclone.rs:9:10
   |
LL | #[derive(Copy, Clone)]
   |          ^^^^ unsatisfied trait bound introduced in this `derive` macro
LL | struct B<T> {
   |          - would need to be `Copy`
```
… for derive

On type errors where the difference is expecting an owned type and getting a reference, if the expression is a `.clone()` call and the type is annotated with `#[derive(Clone)]`, we now explain implicit bounds and suggest manually implementing `Clone`.

```
error[E0308]: mismatched types
  --> $DIR/derive-implicit-bound-on-clone.rs:10:5
   |
LL | fn clone_me<T, K>(x: &ContainsRc<T, K>) -> ContainsRc<T, K> {
   |                                            ---------------- expected `ContainsRc<T, K>` because of return type
LL |     x.clone()
   |     ^^^^^^^^^ expected `ContainsRc<T, K>`, found `&ContainsRc<T, K>`
   |
   = note: expected struct `ContainsRc<_, _>`
           found reference `&ContainsRc<_, _>`
note: `ContainsRc<T, K>` does not implement `Clone`, so `&ContainsRc<T, K>` was cloned instead
  --> $DIR/derive-implicit-bound-on-clone.rs:10:5
   |
LL |     x.clone()
   |     ^
help: `Clone` is not implemented because the some trait bounds could not be satisfied
  --> $DIR/derive-implicit-bound-on-clone.rs:5:19
   |
LL | #[derive(Clone)]
   |          ----- in this derive macro expansion
LL | struct ContainsRc<T, K> {
   |                   ^  ^ derive introduces an implicit unsatisfied trait bound `K: Clone`
   |                   |
   |                   derive introduces an implicit unsatisfied trait bound `T: Clone`
   = help: consider manually implementing `Clone` to avoid the implict type parameter bounds
```
@rustbot
Copy link
Collaborator

rustbot commented Feb 1, 2026

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.

@davidtwco
Copy link
Member

@bors r+

@rust-bors
Copy link
Contributor

rust-bors bot commented Feb 5, 2026

📌 Commit 6756561 has been approved by davidtwco

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 Feb 5, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Feb 5, 2026
Provide more context on trait bounds being unmet due to imperfect derive

When encountering a value that has a borrow checker error where the type was previously moved, when suggesting cloning verify that it is not already being derived. If it is, explain why the `derive(Clone)` doesn't apply:

```
note: if `TypedAddress<T>` implemented `Clone`, you could clone the value
  --> $DIR/derive-clone-implicit-bound.rs:6:1
   |
LL | #[derive(Clone, Copy)]
   |          ----- derived `Clone` adds implicit bounds on type parameters
LL | pub struct TypedAddress<T>{
   | ^^^^^^^^^^^^^^^^^^^^^^^^-^
   | |                       |
   | |                       introduces an implicit `T: Clone` bound
   | consider manually implementing `Clone` for this type
...
LL |         let old = self.return_value(offset);
   |                                     ------ you could clone this value
```

When encountering a bound coming from a derive macro, suggest manual impl of the trait.

Use the span for the specific param when adding bounds in builtin derive macros, so the diagnostic will point at them as well as the derive macro itself.

```
note: required for `Id<SomeNode>` to implement `PartialEq`
  --> $DIR/derive-implicit-bound.rs:5:10
   |
LL | #[derive(PartialEq, Eq)]
   |          ^^^^^^^^^
LL | pub struct Id<T>(PhantomData<T>);
   |               - unsatisfied trait bound introduced in this `derive` macro
   = help: consider manually implementing `PartialEq` to avoid undesired bounds
```

Mention that the trait could be manually implemented in E0599.

Fix rust-lang#108894. Address rust-lang#143714. Address #rust-lang#146515 (but ideally would also suggest constraining the fn bound correctly as well).
rust-bors bot pushed a commit that referenced this pull request Feb 5, 2026
…uwer

Rollup of 9 pull requests

Successful merges:

 - #151278 (Provide more context on trait bounds being unmet due to imperfect derive)
 - #151955 (escape symbol names in global asm)
 - #149329 (Mark match arms in try and for as being from desugarings.)
 - #151474 (Minor structural improvements)
 - #151744 (fix refining_impl_trait suggestion with return_type_notation)
 - #152107 (Convert to inline diagnostics in `rustc_borrowck`)
 - #152117 (Convert to inline diagnostics in `rustc_trait_selection`)
 - #152136 (Consolidate type const checks on `tcx.is_type_const`)
 - #152170 (Port `rustc_effective_visibility` to the new attribute parser)
@rust-bors
Copy link
Contributor

rust-bors bot commented Feb 5, 2026

⌛ Testing commit 6756561 with merge 4ea8b57...

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

rust-bors bot pushed a commit that referenced this pull request Feb 5, 2026
Provide more context on trait bounds being unmet due to imperfect derive

When encountering a value that has a borrow checker error where the type was previously moved, when suggesting cloning verify that it is not already being derived. If it is, explain why the `derive(Clone)` doesn't apply:

```
note: if `TypedAddress<T>` implemented `Clone`, you could clone the value
  --> $DIR/derive-clone-implicit-bound.rs:6:1
   |
LL | #[derive(Clone, Copy)]
   |          ----- derived `Clone` adds implicit bounds on type parameters
LL | pub struct TypedAddress<T>{
   | ^^^^^^^^^^^^^^^^^^^^^^^^-^
   | |                       |
   | |                       introduces an implicit `T: Clone` bound
   | consider manually implementing `Clone` for this type
...
LL |         let old = self.return_value(offset);
   |                                     ------ you could clone this value
```

When encountering a bound coming from a derive macro, suggest manual impl of the trait.

Use the span for the specific param when adding bounds in builtin derive macros, so the diagnostic will point at them as well as the derive macro itself.

```
note: required for `Id<SomeNode>` to implement `PartialEq`
  --> $DIR/derive-implicit-bound.rs:5:10
   |
LL | #[derive(PartialEq, Eq)]
   |          ^^^^^^^^^
LL | pub struct Id<T>(PhantomData<T>);
   |               - unsatisfied trait bound introduced in this `derive` macro
   = help: consider manually implementing `PartialEq` to avoid undesired bounds
```
 
Mention that the trait could be manually implemented in E0599.

Fix #108894. Address #143714. Address ##146515 (but ideally would also suggest constraining the fn bound correctly as well).
@JonathanBrouwer
Copy link
Contributor

@bors yield
Yielding to enclosing rollup

@rust-bors
Copy link
Contributor

rust-bors bot commented Feb 5, 2026

Auto build cancelled. Cancelled workflows:

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

rust-bors bot pushed a commit that referenced this pull request Feb 5, 2026
…uwer

Rollup of 9 pull requests

Successful merges:

 - #151278 (Provide more context on trait bounds being unmet due to imperfect derive)
 - #151955 (escape symbol names in global asm)
 - #149329 (Mark match arms in try and for as being from desugarings.)
 - #151474 (Minor structural improvements)
 - #151744 (fix refining_impl_trait suggestion with return_type_notation)
 - #152107 (Convert to inline diagnostics in `rustc_borrowck`)
 - #152117 (Convert to inline diagnostics in `rustc_trait_selection`)
 - #152136 (Consolidate type const checks on `tcx.is_type_const`)
 - #152170 (Port `rustc_effective_visibility` to the new attribute parser)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Feb 5, 2026
Provide more context on trait bounds being unmet due to imperfect derive

When encountering a value that has a borrow checker error where the type was previously moved, when suggesting cloning verify that it is not already being derived. If it is, explain why the `derive(Clone)` doesn't apply:

```
note: if `TypedAddress<T>` implemented `Clone`, you could clone the value
  --> $DIR/derive-clone-implicit-bound.rs:6:1
   |
LL | #[derive(Clone, Copy)]
   |          ----- derived `Clone` adds implicit bounds on type parameters
LL | pub struct TypedAddress<T>{
   | ^^^^^^^^^^^^^^^^^^^^^^^^-^
   | |                       |
   | |                       introduces an implicit `T: Clone` bound
   | consider manually implementing `Clone` for this type
...
LL |         let old = self.return_value(offset);
   |                                     ------ you could clone this value
```

When encountering a bound coming from a derive macro, suggest manual impl of the trait.

Use the span for the specific param when adding bounds in builtin derive macros, so the diagnostic will point at them as well as the derive macro itself.

```
note: required for `Id<SomeNode>` to implement `PartialEq`
  --> $DIR/derive-implicit-bound.rs:5:10
   |
LL | #[derive(PartialEq, Eq)]
   |          ^^^^^^^^^
LL | pub struct Id<T>(PhantomData<T>);
   |               - unsatisfied trait bound introduced in this `derive` macro
   = help: consider manually implementing `PartialEq` to avoid undesired bounds
```

Mention that the trait could be manually implemented in E0599.

Fix rust-lang#108894. Address rust-lang#143714. Address #rust-lang#146515 (but ideally would also suggest constraining the fn bound correctly as well).
rust-bors bot pushed a commit that referenced this pull request Feb 5, 2026
…uwer

Rollup of 11 pull requests

Successful merges:

 - #152174 (stdarch subtree update)
 - #151278 (Provide more context on trait bounds being unmet due to imperfect derive)
 - #151955 (escape symbol names in global asm)
 - #149329 (Mark match arms in try and for as being from desugarings.)
 - #151474 (Minor structural improvements)
 - #151744 (fix refining_impl_trait suggestion with return_type_notation)
 - #152107 (Convert to inline diagnostics in `rustc_borrowck`)
 - #152117 (Convert to inline diagnostics in `rustc_trait_selection`)
 - #152136 (Consolidate type const checks on `tcx.is_type_const`)
 - #152170 (Port `rustc_effective_visibility` to the new attribute parser)
 - #152184 (Port rustc_abi to the attribute parser)
rust-bors bot pushed a commit that referenced this pull request Feb 5, 2026
…uwer

Rollup of 11 pull requests

Successful merges:

 - #152174 (stdarch subtree update)
 - #151278 (Provide more context on trait bounds being unmet due to imperfect derive)
 - #151955 (escape symbol names in global asm)
 - #149329 (Mark match arms in try and for as being from desugarings.)
 - #151474 (Minor structural improvements)
 - #151744 (fix refining_impl_trait suggestion with return_type_notation)
 - #152107 (Convert to inline diagnostics in `rustc_borrowck`)
 - #152117 (Convert to inline diagnostics in `rustc_trait_selection`)
 - #152136 (Consolidate type const checks on `tcx.is_type_const`)
 - #152170 (Port `rustc_effective_visibility` to the new attribute parser)
 - #152184 (Port rustc_abi to the attribute parser)
rust-bors bot pushed a commit that referenced this pull request Feb 5, 2026
…uwer

Rollup of 11 pull requests

Successful merges:

 - #152174 (stdarch subtree update)
 - #151278 (Provide more context on trait bounds being unmet due to imperfect derive)
 - #151955 (escape symbol names in global asm)
 - #149329 (Mark match arms in try and for as being from desugarings.)
 - #151474 (Minor structural improvements)
 - #151744 (fix refining_impl_trait suggestion with return_type_notation)
 - #152107 (Convert to inline diagnostics in `rustc_borrowck`)
 - #152117 (Convert to inline diagnostics in `rustc_trait_selection`)
 - #152136 (Consolidate type const checks on `tcx.is_type_const`)
 - #152170 (Port `rustc_effective_visibility` to the new attribute parser)
 - #152184 (Port rustc_abi to the attribute parser)
rust-bors bot pushed a commit that referenced this pull request Feb 6, 2026
Rollup of 4 pull requests

Successful merges:

 - #152174 (stdarch subtree update)
 - #151278 (Provide more context on trait bounds being unmet due to imperfect derive)
 - #151955 (escape symbol names in global asm)
 - #152194 (Remove the 4 failing tests from rustdoc-gui)

Failed merges:

 - #152191 (Convert to inline diagnostics in `rustc_hir_analysis`)
@rust-bors rust-bors bot merged commit 7b821d1 into rust-lang:main Feb 6, 2026
11 of 12 checks passed
@rustbot rustbot added this to the 1.95.0 milestone Feb 6, 2026
rust-timer added a commit that referenced this pull request Feb 6, 2026
Rollup merge of #151278 - estebank:issue-108894, r=davidtwco

Provide more context on trait bounds being unmet due to imperfect derive

When encountering a value that has a borrow checker error where the type was previously moved, when suggesting cloning verify that it is not already being derived. If it is, explain why the `derive(Clone)` doesn't apply:

```
note: if `TypedAddress<T>` implemented `Clone`, you could clone the value
  --> $DIR/derive-clone-implicit-bound.rs:6:1
   |
LL | #[derive(Clone, Copy)]
   |          ----- derived `Clone` adds implicit bounds on type parameters
LL | pub struct TypedAddress<T>{
   | ^^^^^^^^^^^^^^^^^^^^^^^^-^
   | |                       |
   | |                       introduces an implicit `T: Clone` bound
   | consider manually implementing `Clone` for this type
...
LL |         let old = self.return_value(offset);
   |                                     ------ you could clone this value
```

When encountering a bound coming from a derive macro, suggest manual impl of the trait.

Use the span for the specific param when adding bounds in builtin derive macros, so the diagnostic will point at them as well as the derive macro itself.

```
note: required for `Id<SomeNode>` to implement `PartialEq`
  --> $DIR/derive-implicit-bound.rs:5:10
   |
LL | #[derive(PartialEq, Eq)]
   |          ^^^^^^^^^
LL | pub struct Id<T>(PhantomData<T>);
   |               - unsatisfied trait bound introduced in this `derive` macro
   = help: consider manually implementing `PartialEq` to avoid undesired bounds
```

Mention that the trait could be manually implemented in E0599.

Fix #108894. Address #143714. Address ##146515 (but ideally would also suggest constraining the fn bound correctly as well).
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. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

#[derive(Clone, Copy)] doesn't work

6 participants