Closed
Description
Code
#[derive(Clone)]
struct ThingThatDoesAThing {}
trait DoesAThing {}
impl DoesAThing for ThingThatDoesAThing {}
fn clones_impl_ref_inline(thing: &impl DoesAThing) {
drops_impl_owned(thing.clone());
}
fn drops_impl_owned(_thing: impl DoesAThing) { }
Current output
error[E0277]: the trait bound `&impl DoesAThing: DoesAThing` is not satisfied
--> src/lib.rs:9:22
|
9 | drops_impl_owned(thing.clone());
| ---------------- ^^^^^^^^^^^^^ the trait `DoesAThing` is not implemented for `&impl DoesAThing`
| |
| required by a bound introduced by this call
|
= help: the trait `DoesAThing` is implemented for `ThingThatDoesAThing`
note: required by a bound in `drops_impl_owned`
--> src/lib.rs:12:34
|
12 | fn drops_impl_owned(_thing: impl DoesAThing) { }
| ^^^^^^^^^^ required by this bound in `drops_impl_owned`
Desired output
error[E0277]: the trait bound `&impl DoesAThing: DoesAThing` is not satisfied
--> src/lib.rs:12:22
|
9 | drops_impl_owned(thing.clone());
| ---------------- ^^^^^^^^^^^^^ the trait `DoesAThing` is not implemented for `&impl DoesAThing`
| |
| required by a bound introduced by this call
|
= help: the trait `DoesAThing` is implemented for `ThingThatDoesAThing`
help: the type `&impl DoesAThing` does not implement `Clone`, so calling `clone` on `&impl DoesAThing` copies the reference, which does not do anything. Consider further restricting this bound
|
8 | fn clones_impl_ref_inline(thing: &impl DoesAThing + Clone) {
| +++++++
note: required by a bound in `drops_impl_owned`
--> src/lib.rs:33:34
|
12 | fn drops_impl_owned(_thing: impl DoesAThing) { }
| ^^^^^^^^^^ required by this bound in `drops_impl_owned`
Rationale and extra context
The current error message does not guide the programmer to the correct solution, which is to add a Clone
bound to the type constraints of the generic parameter.
Other cases
Moving the inline call to thing.clone()
onto its own line improves the error, but it's still misleading:
fn clones_impl_ref_statement(thing: &impl DoesAThing) {
let thing_clone = thing.clone();
drops_impl_owned(thing_clone);
}
error[E0277]: the trait bound `&impl DoesAThing: DoesAThing` is not satisfied
--> src/lib.rs:18:22
|
18 | drops_impl_owned(thing_clone);
| ^^^^^^^^^^^ the trait `DoesAThing` is not implemented for `&impl DoesAThing`
|
help: consider further restricting this bound
|
16 | fn clones_impl_ref_statement(thing: &impl DoesAThing + Clone) {
| +++++++
help: consider using clone here
|
18 | drops_impl_owned(thing_clone.clone());
| ++++++++
Removing the call to drops_impl_owned()
allows compilation to proceed to the warning stage, which generates a warning that actually explains the problem (incorporated into Desired output, above):
fn clones_and_drops_impl_ref(thing: &impl DoesAThing) {
let _ = thing.clone();
}
warning: call to `.clone()` on a reference in this situation does nothing
--> src/lib.rs:23:18
|
23 | let _ = thing.clone();
| ^^^^^^^^ help: remove this redundant call
|
= note: the type `impl DoesAThing` does not implement `Clone`, so calling `clone` on `&impl DoesAThing` copies the reference, which does not do anything and can be removed
= note: `#[warn(noop_method_call)]` on by default
Rust Version
rustc 1.78.0-nightly (397937d81 2024-02-22)
binary: rustc
commit-hash: 397937d812852f9bbeb671005cb399dbcb357cde
commit-date: 2024-02-22
host: aarch64-apple-darwin
release: 1.78.0-nightly
LLVM version: 18.1.0
Anything else?
I've set up a minimal reproducer repo for each of the above cases at https://github.com/overhacked/impl-ref-reproducer