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

Support multiple blanket impls with differing bounds for traits #442

Closed
soltanmm opened this issue Nov 5, 2014 · 5 comments
Closed

Support multiple blanket impls with differing bounds for traits #442

soltanmm opened this issue Nov 5, 2014 · 5 comments

Comments

@soltanmm
Copy link

soltanmm commented Nov 5, 2014

This currently fails to compile:

trait Trait { fn asdf() {} }

trait A {}
trait B {}

impl<T> Trait for T where T: A {}
impl<T> Trait for T where T: B {}

with error:

<anon>:8:1: 8:34 error: conflicting implementations for trait `Trait` [E0119]
<anon>:8 impl<T> Trait for T where T: A {}
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<anon>:9:1: 9:34 note: note conflicting implementation here
<anon>:9 impl<T> Trait for T where T: B {}
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

Rust Playpen Link

Naturally, this error makes sense. A type can impl both traits A and B. I was hoping that such a check could be deferred, though, thus resolving these 'conflicts' later when something actually asking for Trait pops up. Ex. a type that impls only A would get the blanket impl for A, and if multiple impls apply (e.g. the type impls both A and B) then the compiler errors out.

Some ideas

It was suggested on IRC that one may allow both blanket impls to apply by using UFCS path syntax to disambiguate trait bounds and narrow down the possibly applicable impls to a single one. Ex. a type that impls both A and B could get both blanket impls but be disambiguated when calling via <Type as A>::asdf().

But really I'd be totally cool with only one blanket impl applying to any one type at any time.

@soltanmm soltanmm changed the title Support multiple blanket impls for traits? Support multiple blanket impls with differing bounds for traits Nov 5, 2014
@japaric
Copy link
Member

japaric commented Nov 6, 2014

You can probably achieve what you want with "negative bounds":

// All these implementations are valid (i.e. they don't conflict)
impl<T> Trait for T where T: A + B {}    // T implements A and B
impl<T> Trait for T where T: A + !B {}   // T implements A, but it doesn't implement B
impl<T> Trait for T where T: !A + B {}   // the reverse case
impl<T> Trait for T where T: !A + !B {}  // T implements neither A nor B

There are some parts of the stdlib that could benefit a lot from it. [1, 2] So, we'll likely get this feature at some point in the future.

[1] rust-lang/rust#17884 (comment)
[2] rust-lang/rust#12517 (comment)

@soltanmm
Copy link
Author

soltanmm commented Nov 7, 2014

Oh man I want those. The functional completeness that would bring (assuming one is willing to come up with a new trait + blanket impl for every parenthetical) sounds flippin' great.

Although, wouldn't this still require deferring checks (in the absence of brute-force checking for non-overlapping coverage of the trait bounds)?

@mitsuhiko
Copy link
Contributor

I'm running into more and more of these problems lately with my error handling experiments. Huge +1 on negative trait bounds.

@codyps
Copy link

codyps commented Dec 4, 2014

I've also wanted this (negative bounds)

@nikomatsakis
Copy link
Contributor

This issue is subsumed by the more general #1053, so I'm going to close it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants