Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler does not error when implementing the same trait twice on generic types that are bounded by Copy #7555

Closed
bstrie opened this issue Jul 2, 2013 · 5 comments
Labels
A-typesystem Area: The type system

Comments

@bstrie
Copy link
Contributor

bstrie commented Jul 2, 2013

In this code snippet, we impl a trait on all types that implement Bar. However, we impl the trait twice, and this correctly does not compile:

fn main() {
    //let qux = Qux;
    //qux.foo();
}

struct Qux;

trait Bar {
    fn bar(&self);
}

impl Bar for Qux {
    fn bar(&self) { println("qux"); }
}

trait Foo {
    fn foo(&self);
}

impl<T: Bar> Foo for T {
    fn foo(&self) { println("foo1"); }
}

impl<T: Bar> Foo for T {
    fn foo(&self) { println("foo2"); }
}
4894.rs:24:0: 26:1 error: conflicting implementations for a trait
4894.rs:24 impl<T: Bar> Foo for T {
4894.rs:25     fn foo(&self) { println("foo2"); }
4894.rs:26 }
4894.rs:20:0: 22:1 note: note conflicting implementation here
4894.rs:20 impl<T: Bar> Foo for T {
4894.rs:21     fn foo(&self) { println("foo1"); }
4894.rs:22 }
4894.rs:20:0: 22:1 error: conflicting implementations for a trait
4894.rs:20 impl<T: Bar> Foo for T {
4894.rs:21     fn foo(&self) { println("foo1"); }
4894.rs:22 }
4894.rs:24:0: 26:1 note: note conflicting implementation here
4894.rs:24 impl<T: Bar> Foo for T {
4894.rs:25     fn foo(&self) { println("foo2"); }
4894.rs:26 }
error: aborting due to 2 previous errors

But, if instead of bounding our generics with Bar we bound them with the built-in Copy trait, this compiles successfully!

fn main() {
    //let qux = Qux;
    //qux.foo();
}

struct Qux;

trait Foo {
    fn foo(&self);
}

impl<T: Copy> Foo for T {
    fn foo(&self) { println("foo1"); }
}

impl<T: Copy> Foo for T {
    fn foo(&self) { println("foo2"); }
}

However, if you uncomment the lines that actually attempt to invoke .foo(), this code will fail to compile with "multiple applicable methods in scope".

Given that the non-built-in trait correctly prevents compilation at definition-time rather than waiting for invocation, I think it would be correct for Copy to do the same.

@bstrie
Copy link
Contributor Author

bstrie commented Jul 2, 2013

Even if we happen to remove Copy in the future, we should go through and make sure this doesn't happen with other built-in traits.

@pcwalton
Copy link
Contributor

Nominated for production ready, this is a nasty coherence bug.

@catamorphism
Copy link
Contributor

Accepted for milestone 5, production-ready

@catamorphism
Copy link
Contributor

#5527 is related

@nikomatsakis
Copy link
Contributor

I believe this was due to the hack in coherence that was
specific to the (now removed) Copy trait (iirc the code was
not generalizing to other built-in traits). Closing as I can't
find any evidence of this code still existing. Reopen if you
disagree.

flip1995 pushed a commit to flip1995/rust that referenced this issue Jul 18, 2022
…ffate

Fixes for `branches_sharing_code`

fixes rust-lang#7198
fixes rust-lang#7452
fixes rust-lang#7555
fixes rust-lang#7589

changelog: Don't suggest moving modifications to locals used in any of the condition expressions in `branches_sharing_code`
changelog: Don't suggest moving anything after a local with a significant drop in `branches_sharing_code`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-typesystem Area: The type system
Projects
None yet
Development

No branches or pull requests

4 participants