Rust: Can't write non-overlapping blanket impls that involve associated type bindings

Created on 1 Jan 2015  路  12Comments  路  Source: rust-lang/rust

STR

Example from libcore:

#![crate_type = "lib"]
#![feature(associated_types)]
#![no_implicit_prelude]

trait Iterator {
    type Item;
}

trait AdditiveIterator {
    type Sum;

    fn sum(self) -> Self::Sum;
}

impl<I> AdditiveIterator for I where I: Iterator<Item=u8> {  //~error conflicting implementation
    type Sum = u8;

    fn sum(self) -> u8 { loop {} }
}

impl<I> AdditiveIterator for I where I: Iterator<Item=u16> {  //~note conflicting implementation here
    type Sum = u16;

    fn sum(self) -> u16 { loop {} }
}

Version

7d4f487

No type can implement _both_ Iterator<Item=u8> and Iterator<Item=u16>, therefore these blanket impls are non overlapping and should be accepted.

cc @nikomatsakis

A-associated-items A-traits C-bug T-lang needs-rfc

Most helpful comment

To give an update on this: In 2016, RFC 1672 was proposed to fix this, but was postponed until the Chalk integration is done. Additionally, according to https://github.com/rust-lang/rfcs/pull/1672#issuecomment-262152934, allowing these kinds of impls would allow users to express mutually exclusive traits, which is a very powerful feature that needs more in-depth consideration by the language team (hence marking as blocked on an RFC as well).

(also adding the keyword "disjoint" to make this issue easier to find)

All 12 comments

I encountered this bug too, while trying to optimize ToString (#18404):

pub enum Void {}

pub trait Display {
    // ...
    type AsStr = Void;
    fn fmt_as_str(&self) -> &<Self as Display>::AsStr { unimplemented!() }
}

pub trait ToString {
    fn to_string(&self) -> String;
}

impl<T: Display<AsStr=Void> + ?Sized> ToString for T {
    fn to_string(&self) -> String {
        format!("{}", self)
    }
}

impl<T: Display<AsStr=str> + ?Sized> ToString for T {
    fn to_string(&self) -> String {
        String::from_str(self.fmt_as_str())
    }
}

This change could speed up "".to_string() significantly (currently, String::from_str is between 2 and 5 times faster than format!) so I'd love to see this issue fixed.

cc me

cc me

This is really causing problems for a crate I'm working on.

Is this bug likely to get any love? I keep hitting this (see #23341) too. I had a look around by I can't really follow how overlapping impls are determined, I would have liked to have a go at it.

Any chance of this getting triaged any time soon? Also feeling pains from this issue.

I ran into this problem just now. I wanted to provide and_then() and map() methods for my type that would work if Trait::Type is Option or Result.

What's needed to advance this issue towards a fix? Are we dependent on Chalk?

Looks like you can kind of "trick" the compiler by using type specialization. On stable, 2015 edition:

https://play.rust-lang.org/?gist=d803059c64390d7182445bb21756f98c&version=stable&mode=debug&edition=2015

I'd like to add myself to the list of people that this causes problems for :).

Looks like you can kind of "trick" the compiler by using type specialization. On stable, 2015 edition:

https://play.rust-lang.org/?gist=d803059c64390d7182445bb21756f98c&version=stable&mode=debug&edition=2015

@ZerothLaw could you explain your trick a bit? I think I'm running into this issue and am hoping for a workaround but I'm struggling to understand your example. If you could give some advice on how to apply that to the code in #58171 that would be great.

To give an update on this: In 2016, RFC 1672 was proposed to fix this, but was postponed until the Chalk integration is done. Additionally, according to https://github.com/rust-lang/rfcs/pull/1672#issuecomment-262152934, allowing these kinds of impls would allow users to express mutually exclusive traits, which is a very powerful feature that needs more in-depth consideration by the language team (hence marking as blocked on an RFC as well).

(also adding the keyword "disjoint" to make this issue easier to find)

Was this page helpful?
0 / 5 - 0 ratings