Type inference with two traits

Type inference fails for this:

trait TraitA {}
trait TraitB {}

impl TraitA for u64 {}
impl TraitA for i64 {}
impl TraitB for u64 {}
impl TraitB for u8 {}

fn foo<T: TraitA + TraitB>(x: T) {}

fn main() {
error[E0277]: the trait bound `i32: TraitA` is not satisfied

The compiler defaults 5 to i32 and fails even though only u64 satisfies both traits. I guess it doesn't use traits to deduce types if a trait is implemented by at least two types. Is this documented behavior?

The same error occurs with single trait: fn foo<T: TraitA>(x: T) {}.

I found this in Trait solving - Guide to Rustc Development.

Naturally, since we don't know what T is, we can't find the specific impl; but based on the bound, we can say that there exists an impl which the caller must provide.

We use the term obligation to refer to a trait reference in need of an impl. Basically, the trait resolution system resolves an obligation by proving that an appropriate impl does exist.

During type checking, we do not store the results of trait selection. We simply wish to verify that trait selection will succeed.


The error msg could be more user-friendly if it's pointed out. Now Rust emits the candidates separately

   = help: the following other types implement trait `TraitA`:
   = help: the following other types implement trait `TraitB`:

It's well-known that integer type inference is flaky and behaves like that. I don't know whether there is a specific place where it's described.

The error messages could be better, though. I guess the compiler should state that it's defaulting to i32 since there isn't a constraint which uniquely specifies the type. TraitA + TraitB isn't it, because trait bounds are checked separately. What you want looks a bit like specialization for {integer}.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.