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

Conflicting between impl <T: Base> T: Ext and impl B: Ext #3429

Closed
gifnksm opened this issue Sep 8, 2012 · 15 comments
Closed

Conflicting between impl <T: Base> T: Ext and impl B: Ext #3429

gifnksm opened this issue Sep 8, 2012 · 15 comments
Labels
A-trait-system Area: Trait system C-enhancement Category: An issue proposing an enhancement or a PR with one. E-hard Call for participation: Hard difficulty. Experience needed to fix: A lot.

Comments

@gifnksm
Copy link
Contributor

gifnksm commented Sep 8, 2012

Minimized test case

(taken from bstrie's comment below)

fn main() {
    let x = X;
    x.foobar();
}

trait Foo {
    fn foobar(&self);
}

trait Bar {
    fn foobar(&self);
}

trait FooBase {}

trait BarBase {}

impl<T: FooBase> Foo for T {
    fn foobar(&self) {}
}

impl<T: BarBase> Bar for T {
    fn foobar(&self) {}
}

struct X;

impl FooBase for X {}

Original bug report follows

I tried implementing of a trait Eq for a generic type T: OrdEx, but rustc says conflicting between impl <T: OrdEx> T: Eq and impl Cmp: Eq.

extcmp.rs:

use cmp::{Eq, Ord};

enum Cmp { Lt, Eq, Gt }

trait OrdEx {
    pure fn cmp(&&other: self) -> Cmp;
}

impl Cmp : Eq {
    pure fn eq(&&other: Cmp) -> bool {
        match (self, other) {
          (Lt, Lt) | (Gt, Gt) | (Eq, Eq) => true,
          _ => false
        }
    }
    pure fn ne(&&other: Cmp) -> bool { !self.eq(other) }
}

impl<T: OrdEx> T : Eq {
    pure fn eq(&&other: T) -> bool { match self.cmp(other) { Eq => true, _ => false } }
    pure fn ne(&&other: T) -> bool { !self.eq(other) }
}

impl<T: OrdEx> T : Ord {
    pure fn lt(&&other: T) -> bool { match self.cmp(other) { Lt      => true, _ => false} }
    pure fn le(&&other: T) -> bool { match self.cmp(other) { Lt | Eq => true, _ => false} }
    pure fn ge(&&other: T) -> bool { match self.cmp(other) { Eq | Gt => true, _ => false} }
    pure fn gt(&&other: T) -> bool { match self.cmp(other) { Gt      => true, _ => false} }
}

fn main() {
}
$ rustc extcmp.rs
extcmp.rs:19:0: 22:1 error: conflicting implementations for a trait
extcmp.rs:19 impl<T: OrdEx> T : Eq {
extcmp.rs:20     pure fn eq(&&other: T) -> bool { match self.cmp(other) { Eq => true, _ => false } }
extcmp.rs:21     pure fn ne(&&other: T) -> bool { !self.eq(other) }
extcmp.rs:22 }
extcmp.rs:9:0: 17:1 note: note conflicting implementation here
extcmp.rs:9 impl Cmp : Eq {
extcmp.rs:10     pure fn eq(&&other: Cmp) -> bool {
extcmp.rs:11         match (self, other) {
extcmp.rs:12           (Lt, Lt) | (Gt, Gt) | (Eq, Eq) => true,
extcmp.rs:13           _ => false
extcmp.rs:14         }
             ...
extcmp.rs:16:40: 16:47 error: multiple applicable methods in scope
extcmp.rs:16     pure fn ne(&&other: Cmp) -> bool { !self.eq(other) }
                                                     ^~~~~~~
extcmp.rs:10:4: 15:5 note: candidate #1 is `__extensions__::eq`
extcmp.rs:10     pure fn eq(&&other: Cmp) -> bool {
extcmp.rs:11         match (self, other) {
extcmp.rs:12           (Lt, Lt) | (Gt, Gt) | (Eq, Eq) => true,
extcmp.rs:13           _ => false
extcmp.rs:14         }
extcmp.rs:15     }
extcmp.rs:20:4: 20:87 note: candidate #2 is `__extensions__::eq`
extcmp.rs:20     pure fn eq(&&other: T) -> bool { match self.cmp(other) { Eq => true, _ => false } }
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
@Dretch
Copy link
Contributor

Dretch commented Sep 9, 2012

I have run into this issue too. I think the problem is that rust allows you to use generics to declare multiple impls of a trait for the same type - but typeclass coherence says this shouldn't be allowed.

@nikomatsakis
Copy link
Contributor

In general, support for impls for type parameters is sketchy. It's unclear if such constructs should be allowed at all (though they are unquestionably useful). But if we do decide to allow them, it's clear that we have to beef up our algorithms to deal with the complexities that they introduce. In this case, the bug is because coherence doesn't "go further" to check that all the bounds on the type parameters are met when deciding whether two implementations overlap. This is somewhat tricky---it would basically have to conclude that an implementation on all implements of Foo does not conflict with an implementation on the type A because the type A does not implement Foo. This check is only reasonable, of course, due to coherence itself.

@catamorphism
Copy link
Contributor

Nominated for maturity milestone 1 (well-defined), since there's a question as to whether the code should be allowed.

@graydon
Copy link
Contributor

graydon commented May 16, 2013

accepted for well-defined milestone

@graydon
Copy link
Contributor

graydon commented May 16, 2013

sub-bug of #5527

@bstrie
Copy link
Contributor

bstrie commented Jun 5, 2013

Here's an updated, minimized, self-contained test case:

fn main() {
    let x = X;
    x.foobar();
}

trait Foo {
    fn foobar(&self);
}

trait Bar {
    fn foobar(&self);
}

trait FooBase {}

trait BarBase {}

impl<T: FooBase> Foo for T {
    fn foobar(&self) {}
}

impl<T: BarBase> Bar for T {
    fn foobar(&self) {}
}

struct X;

impl FooBase for X {}

Output:

con.rs:3:4: 3:15 error: multiple applicable methods in scope
con.rs:3     x.foobar();
             ^~~~~~~~~~~
con.rs:23:4: 23:23 note: candidate #1 is `__extensions__::foobar`
con.rs:23     fn foobar(&self) {}
              ^~~~~~~~~~~~~~~~~~~
con.rs:19:4: 19:23 note: candidate #2 is `__extensions__::foobar`
con.rs:19     fn foobar(&self) {}
              ^~~~~~~~~~~~~~~~~~~
con.rs:3:4: 3:15 error: failed to find an implementation of trait BarBase for X
con.rs:3     x.foobar();
             ^~~~~~~~~~~

To clarify, the strangeness here is that even though the type X doesn't implement BarBase (this is even noted in the error message), the impl of Bar for all types T: BarBase conflicts with the impl of FooBase on X.

@pnkfelix
Copy link
Member

visited for triage email 2013-07-22.

still a problem.

@pnkfelix
Copy link
Member

While investigating the test case posted by bstrie, I noticed this variant of the test has a different error message (but its cause may stem from the same origin). This test's goal was to break the main method into separate functions with type signatures to see if I could force rustc to notice the X -> FooBase -> Foo path.

fn g<F:Foo>(f:&F) {
    f.foobar();
}

fn f<FB:FooBase>(fb:&FB) {
    g(fb);
}

fn main() {
    let x = X;
    f(&x);
}
struct X;
impl FooBase for X {}

trait Foo { fn foobar(&self); }

trait Bar { fn foobar(&self); }

trait FooBase {}
trait BarBase {}

impl<T: FooBase> Foo for T {
    fn foobar(&self) {}
}

impl<T: BarBase> Bar for T {
    fn foobar(&self) {}
}

error message:

% rustc /tmp/rusttmp/baz.rs
/tmp/rusttmp/baz.rs:6:4: 6:5 error: failed to find an implementation of trait Foo for T
/tmp/rusttmp/baz.rs:6     g(fb);
                          ^

@huonw
Copy link
Member

huonw commented Jul 25, 2013

@pnkfelix it looks like 906264b fixed that testcase there. (The testcase from the bug occurs still after that merge.)

@pnkfelix
Copy link
Member

@huonw oh sorry, I indeed was using rustc from 8a7b636 2013-07-10

@DaGenix
Copy link

DaGenix commented Jan 12, 2014

I hit upon a similar behavior, I think, with the following code:

trait T1 { }

trait T2 { }

struct S1;

impl T1 for S1 { }

impl <S: T2> T1 for S { }

fn main() {}

@japaric
Copy link
Member

japaric commented Oct 13, 2014

Triage: After the multidispatch PR (#17669) landed, two of the three test cases presented in this thread now work:

bstrie example still errors with the same message.

@luqmana
Copy link
Member

luqmana commented Nov 3, 2014

All these now pass thanks to the changes to the trait matching system. \o/

@luqmana luqmana closed this as completed Nov 3, 2014
@ufs-abrin
Copy link

I think, there similar issue with rustc 1.12.1 (d4f3940 2016-10-19)

code:

trait X {}
trait Y {}
trait Z {}
impl <T : Y> X for T {}
impl <T : Z> X for T {}

fails with:

error[E0119]: conflicting implementations of trait `X`:
 --> src/lib.rs:5:1
  |
4 | impl <T : Y> X for T {}
  | ----------------------- first implementation here
5 | impl <T : Z> X for T {}
  | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation

@nikomatsakis
Copy link
Contributor

@ufs-abrin

I think, there similar issue with rustc 1.12.1 (d4f3940 2016-10-19)

That is expected behavior. The problem is that one type could implement both Y and Z, in which case there would be two applicable impls (which we aim to avoid). We've been working on specialization (see rust-lang/rfcs#1210) which aims to allow overlapping impls in some situations, but it's still a work-in-progress.

RalfJung pushed a commit to RalfJung/rust that referenced this issue Apr 13, 2024
De-duplicate SSE2 sll/srl/sra code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-trait-system Area: Trait system C-enhancement Category: An issue proposing an enhancement or a PR with one. E-hard Call for participation: Hard difficulty. Experience needed to fix: A lot.
Projects
None yet
Development

No branches or pull requests