Skip to content

Error in specialization type checking when using trait aliases #74809

Open
@jsmith628

Description

@jsmith628

So I seem to have found an error in the type checking for specialization impls when using trait alias bounds

Specifically, this code:

#![feature(specialization)]
#![feature(trait_alias)]

pub trait Marker1<T> {}
pub trait Marker2 {}

pub trait CombinedMarker<T> = Marker1<T> + Marker2;

pub struct Container<T,U> { p: std::marker::PhantomData<(T,U)> }

pub struct Struct;
impl<T> Marker1<T> for Struct {}

pub trait Trait { fn do_thing(&self); }

impl<T, U:Marker1<T>> Trait for Container<T,U> {
    default fn do_thing(&self) { println!("default behavior"); }
}

impl<T, U:CombinedMarker<T>> Trait for Container<T,U> {
    default fn do_thing(&self) { println!("partially specialized behavior"); }
}

impl<T> Trait for Container<T,Struct> {
    fn do_thing(&self) { println!("fully specialized behavior") }
}

gives a type error with output of:

warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
 --> src/main.rs:1:12
  |
1 | #![feature(specialization)]
  |            ^^^^^^^^^^^^^^
  |
  = note: `#[warn(incomplete_features)]` on by default
  = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information

error[E0119]: conflicting implementations of trait `Trait` for type `Container<_, Struct>`:
  --> src/main.rs:51:1
   |
47 | impl<T, U:CombinedMarker<T>> Trait for Container<T,U> {
   | ----------------------------------------------------- first implementation here
...
51 | impl<T> Trait for Container<T,Struct> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Container<_, Struct>`

error: aborting due to previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0119`.

However, if you change the bound on the impls from CombinedMarker<T> to Marker1<T>+Marker2 or CombinedMarker<T>+Marker2 it actually compiles, seemingly suggesting that the compiler isn't accurately translating the trait alias over to the bound since all three of those should be equivalent.

Also, before you ask, yes, for some reason, the <T> generic on Marker1 does seem to have an effect, as if it is removed, both the aliased and non-aliased versions compile. Furthermore, the Container<T> struct also seems to be important since removing it also fixed the type error.

Finally, for reference, my rustc is on this version:

rustc 1.47.0-nightly (6c8927b0c 2020-07-26)
binary: rustc
commit-hash: 6c8927b0cf80ceee19386026cf9d7fd4fd9d486f
commit-date: 2020-07-26
host: x86_64-unknown-linux-gnu
release: 1.47.0-nightly
LLVM version: 10.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-specializationArea: Trait impl specializationC-bugCategory: This is a bug.F-specialization`#![feature(specialization)]`F-trait_alias`#![feature(trait_alias)]`requires-nightlyThis issue requires a nightly compiler in some way.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions