DammyD
DammyD

Reputation: 125

Why is 'impl Trait' syntax not working with two parameters?

I created a function in a sample Rust project that compares two values of types that implement the PartialOrd trait, but it isn't compiling:

fn main(){
    let x: i32 = 5;
    let y: i32 = 6;
    dbg!(greater_than(&x, &y));
}

fn greater_than(x: &impl PartialOrd, y: &impl PartialOrd) -> bool{
    x > y
}
error[E0308]: mismatched types
 --> src/main.rs:8:9
  |
7 | fn greater_than(x: &impl PartialOrd, y: &impl PartialOrd) -> bool{
  |                     ---------------      --------------- found type parameter
  |                     |
  |                     expected type parameter
8 |     x > y
  |         ^ expected type parameter `impl PartialOrd`, found a different type parameter `impl PartialOrd`
  |
  = note: expected reference `&impl PartialOrd` (type parameter `impl PartialOrd`)
             found reference `&impl PartialOrd` (type parameter `impl PartialOrd`)
  = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
  = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

My understanding is that once in your parameters in your function signature were typed using the impl trait syntax, any type that implement that trait (i32 is meant to implement PartialOrd trait) could be used in the function as an argument. (I have used a different function signature -using trait bounds as shown below- and it worked fine): fn greater_than<T: PartialOrd>(x: &T, y: &T) -> bool

Upvotes: 2

Views: 107

Answers (2)

Masklinn
Masklinn

Reputation: 42592

My understanding is that once in your parameters in your function signature were typed using the impl trait syntax, any type that implement that trait (i32 is meant to implement PartialOrd trait) could be used in the function as an argument.

Well yes, but impl trait defines no relation between your arguments, so what you've written is essentially

fn greater_than<T: PartialOrd, U: PartialOrd>(x: &T, y: &U) -> bool

So each argument is partially comparable to itself, but there's no implication that they're partially comparable to one another. For all Rust is concerned, you could pass an i32 as first parameter and a String as second, they both impl PartialOrd.

Upvotes: 5

Chayim Friedman
Chayim Friedman

Reputation: 71545

Each occurrence of impl Trait gives a new distinct type parameter. For example, x can be u32 and y String. Both implement PartialOrd, but they still cannot be compared with one another.

What you want cannot be expressed with impl Trait, since you need to mention the type twice:

fn greater_than<T: PartialOrd>(x: &T, y: &T) -> bool{
    x > y
}

Or, to accept even two different types as long as they can be compared:

fn greater_than<T: PartialOrd<U>, U>(x: &T, y: &U) -> bool {
    x > y
}

Upvotes: 7

Related Questions