Skip to content

trait alias dyn type equality doesn't work #55629

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

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-trait-system 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-trait-system 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
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-trait-system 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