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

Erroneous "conflicting implementations" message #24165

Closed
bfops opened this issue Apr 7, 2015 · 8 comments
Closed

Erroneous "conflicting implementations" message #24165

bfops opened this issue Apr 7, 2015 · 8 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-typesystem Area: The type system

Comments

@bfops
Copy link
Contributor

bfops commented Apr 7, 2015

This used to compile, but now it fails with error: conflicting implementations for trait.

trait Foo {}

impl<T> Foo for T where T: Copy {}
impl<T> Foo for Vec<T> where T: Copy {}

fn main() {
}
@apasel422
Copy link
Contributor

This is not a bug, as these impls do conflict: T could be instantiated with Vec<T>. In other words, the impl that would be selected here is ambiguous:

fn foo<F: Foo>() {}

fn main() {
    foo::<Vec<i32>>();
}

One solution involves parameterizing Foo itself with T, as multidispatch will disambiguate the two impls:

trait Foo<T> {}

impl<T> Foo<T> for T where T: Copy {}
impl<T> Foo<T> for Vec<T> where T: Copy {}

fn main() {
}

@bfops
Copy link
Contributor Author

bfops commented Apr 7, 2015

Vec<T> doesn't implement Copy; I can tell you exactly which impl should be picked in your example. And until I ran rustup today, the compiler was doing that properly. And it should be able to, since the impl Copy must be in scope if it exists for Vec.

@apasel422
Copy link
Contributor

Oh, I see. This may be a result of #23867.

@apasel422
Copy link
Contributor

@steveklabnik steveklabnik added A-typesystem Area: The type system A-diagnostics Area: Messages for errors, warnings, and lints labels Apr 7, 2015
@steveklabnik
Copy link
Member

/cc @nikomatsakis

@nikomatsakis
Copy link
Contributor

Yes, this is now the intended behavior, due to rust-lang/rfcs#1023, as @apasel422 points out. And this is also one of the known cases where it'd be nice to be able to extend the system, though the best way to do that is not yet agreed upon.

@bfops
Copy link
Contributor Author

bfops commented Apr 7, 2015

Ah. So given that the type system is now less powerful indefinitely, what's the appropriate course of action if I'm writing a Flatten trait? This used to work:

pub trait Flatten<T> {
  /// Emit a value into a Vec of bytes.
  fn emit(v: &Self, dest: &mut Vec<u8>) -> Result<(), ()>;
  /// Parse a value out of a stream of bytes.
  fn read<'a>(s: &mut MemStream<'a>) -> Result<Self, EOF>;
}

#[macro_export]
macro_rules! flatten_unit_struct_impl(
  ...
);

#[macro_export]
macro_rules! flatten_struct_impl(
  ...
);

#[macro_export]
macro_rules! flatten_enum_impl(
  ...
);

impl<T> Flatten for T where T: Copy {
  ...
}

impl<T> Flatten for Vec<T> where T: Copy {
  ...
}

impl Flatten for String {
  ...
}

@apasel422 I'm having some trouble using your fix for this, since not everything is neatly parameterized on some T.

The reason I'm not using rustc-serialize is because I couldn't find a way to optimize the Vec<T> where T: Copy case to a single memcpy.

@apasel422
Copy link
Contributor

@bfops: I'd suggest bringing this up in http://users.rust-lang.org/ and closing this issue, but the solution depends on how you want to be able to use this trait. My type parameter suggestion was just based on your reduced test case, but, in general, you won't be able to provide multiple Flatten impls if you have a blanket one for T. You may also want to take a look at rustc-serialize and serde for ideas.

@bfops bfops closed this as completed Apr 7, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-typesystem Area: The type system
Projects
None yet
Development

No branches or pull requests

4 participants