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

trait alias dyn type equality doesn't work #55629

Open
nikomatsakis opened this issue Nov 2, 2018 · 3 comments
Open

trait alias dyn type equality doesn't work #55629

nikomatsakis opened this issue Nov 2, 2018 · 3 comments
Labels
A-traits Area: Trait system C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@nikomatsakis
Copy link
Contributor

If you have trait Foo { } and trait Bar = Foo, we do not currently consider dyn Foo and dyn Bar to be the same type.

Subissue of #55628

@nikomatsakis nikomatsakis added A-traits Area: Trait system T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Nov 2, 2018
@alexreg
Copy link
Contributor

alexreg commented Nov 2, 2018

Here's an example from my comment in #55101:

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

trait A<T: Send> {}
trait B<T: Send> = A<T>;

struct Foo<T>(T);
struct Bar();

impl<T: Send> A<T> for Foo<T> {}

impl !Send for Bar {}

fn main() {
    let b: Box<B<Bar>> = Box::new(Foo(Bar()));
    let a: Box<A<Bar>> = b; // should work
}

yields

error[E0308]: mismatched types
  --> foo.rs:16:26
   |
16 |     let a: Box<A<Bar>> = b;
   |                          ^ expected trait `A`, found trait `B`
   |
   = note: expected type `std::boxed::Box<dyn A<Bar>>`
              found type `std::boxed::Box<dyn B<Bar>>`

Whereas references to A and B should clearly be interchangeable.

@alexreg
Copy link
Contributor

alexreg commented Nov 2, 2018

As @nikomatsakis said on Zulip, this is sort of a special case of upcasting. In general, if trait A is a subtype of trait B (i.e. A's bounds include all of B's bounds and possibly more), then dyn A should be convertible to dyn B.

@alexreg
Copy link
Contributor

alexreg commented Dec 5, 2018

Note a seemingly surprising consequence on coherence that this has:

Playground

#![feature(trait_alias)]

trait Foo {
    fn foo(&self) -> u32;
}

trait SendAlias = Send;

impl Foo for dyn Send {
    fn foo(&self) -> u32 {
        1
    }
}

impl Foo for dyn SendAlias {
    fn foo(&self) -> u32 {
        2
    }
}

fn main() {
    let x1 = Box::new(()) as Box<Send>;
    let x2 = Box::new(()) as Box<SendAlias>;
    println!("{}", x1.foo());
    println!("{}", x2.foo());
}

This is correct behaviour for now, and it doesn't cause any ICEs, but obviously is not what one would expect intuitively.

@Enselic Enselic added the C-bug Category: This is a bug. label Nov 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-traits Area: Trait system C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants