Skip to content

simple type inference fails depending on order of trait bounds #54121

Closed
@mikebenfield

Description

@mikebenfield
Contributor

I can't be sure that this behavior is unintended, but it definitely seems very strange and undesirable to me.

This code works fine:

$ cat trash2.rs
trait Tr<A, B> {
    fn exec(a: A, b: B);
}

trait Q {
    type T: Tr<u16, u16> + Tr<u8, u8>;
}

#[allow(dead_code)]
fn f<S: Q>()
{
    <S as Q>::T::exec(0u8, 0u8)
}

fn main() {
}
$ rustc trash2.rs -o trash

But change the order of the trait bounds in the associated type T, and it fails:

$ cat trash2.rs
trait Tr<A, B> {
    fn exec(a: A, b: B);
}

trait Q {
    type T: Tr<u8, u8> + Tr<u16, u16>;
}

#[allow(dead_code)]
fn f<S: Q>()
{
    <S as Q>::T::exec(0u8, 0u8)
}

fn main() {
}
$ rustc trash2.rs -o trash
error[E0308]: mismatched types
  --> trash2.rs:12:23
   |
12 |     <S as Q>::T::exec(0u8, 0u8)
   |                       ^^^ expected u16, found u8
help: you can cast an `u8` to `u16`, which will zero-extend the source value
   |
12 |     <S as Q>::T::exec(0u8.into(), 0u8)
   |                       ^^^^^^^^^^

error[E0308]: mismatched types
  --> trash2.rs:12:28
   |
12 |     <S as Q>::T::exec(0u8, 0u8)
   |                            ^^^ expected u16, found u8
help: you can cast an `u8` to `u16`, which will zero-extend the source value
   |
12 |     <S as Q>::T::exec(0u8, 0u8.into())
   |                            ^^^^^^^^^^

error: aborting due to 2 previous errors

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

Activity

added
A-associated-itemsArea: Associated items (types, constants & functions)
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Aug 5, 2019
WaffleLapkin

WaffleLapkin commented on Sep 26, 2020

@WaffleLapkin
Member

Probably a duplicate of #72582

vmarkushin

vmarkushin commented on Sep 26, 2020

@vmarkushin

Here is another case of such behavior (playground).

trait Trait {
    type Type: Into<Self::Type1> + Into<Self::Type2> + Copy;
    type Type1;
    type Type2;
}

fn foo<T: Trait>(x: T::Type) {
    let _1: T::Type1 = x.into();
    let _2: T::Type2 = x.into();
}
error[E0308]: mismatched types
  --> src/lib.rs:10:24
   |
10 |     let _1: T::Type1 = x.into();
   |             --------   ^^^^^^^^ expected Trait::Type1, found Trait::Type2
   |             |
   |             expected due to this
   |
   = note: expected associated type `<T as Trait>::Type1`
              found associated type `<T as Trait>::Type2`

However, this will compile:

trait Trait {
    type Type: Into<Self::Type1> + Into<Self::Type2> + Copy;
    type Type1;
    type Type2;
}

fn foo<T: Trait>(x: T::Type) {
    let _1: T::Type1 = <T::Type as Into<T::Type1>>::into(x);
    let _2: T::Type2 = <T::Type as Into<T::Type2>>::into(x);
}

Also, an example with concrete types will compile too:

trait Trait {
    type Type: Into<Self::Type1> + Into<Self::Type2> + Copy;
    type Type1;
    type Type2;
}

impl Trait for () {
    type Type = ();
    type Type1 = ();
    type Type2 = ();  
}

fn foo(x: ()) {
    let _1: <() as Trait>::Type1 = x.into();
    let _2: <() as Trait>::Type2 = x.into();
}

Similar issues: #77010 #70944 #77159 #77159 #72582

WaffleLapkin

WaffleLapkin commented on Oct 9, 2020

@WaffleLapkin
Member

This is fixed on nightly. Presumably by #73905

camelid

camelid commented on Nov 10, 2020

@camelid
Member

I just bisected, and indeed this was fixed by #73905. I think this needs a test, and then it can be closed.

added
E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.
on Nov 10, 2020
added a commit that references this issue on Nov 24, 2020
added a commit that references this issue on Nov 29, 2020

Rollup merge of rust-lang#79514 - Julian-Wollersberger:order-dependen…

f0e41ce

6 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-associated-itemsArea: Associated items (types, constants & functions)A-inferenceArea: Type inferenceA-trait-systemArea: Trait systemE-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @mikebenfield@vmarkushin@estebank@fmease@camelid

      Issue actions

        simple type inference fails depending on order of trait bounds · Issue #54121 · rust-lang/rust