Wrong types in PartialOrder compare?

I was trying a problem from The Book - find the largest element in an array. I have the following solution:

fn largest<T: PartialOrd>(lis: &[T]) -> &T {
    let mut larg = &lis[0];
    for item in lis {
        if item > larg {
            larg = item;
        }
    }
    larg
}

But to my surprise, the following works as well:

fn largest<T: PartialOrd>(lis: &[T]) -> &T {
    let mut larg = &lis[0];
    for item in lis {
        if *item > *larg {    // this line is changed
            larg = item;
        }
    }
    larg
}

I wonder why the *item and *larg work? I thought that should lead to ownership transfer. But then this is the signature of gt : fn gt(&self, other: &Rhs) -> bool

How can I pass a non-reference (*item or *larg) to gt which expects a reference?

Take another example which fails.

fn main() {
    let k = 23;
    let p = &k;
    somefun(*p);
}

fn somefun(k: &u32) {}

What's the difference between this and PartialOrder gt with pointer deferencing?

When you type a > b, this is syntax sugar for PartialOrd::gt(&a, &b). Calling PartialOrd::gt(&*item, &*lang) does not perform an ownership transfer. The same does not apply to your somefun example.

2 Likes
  • So is a > b transformed to PartialOrd::gt(&a, &b) at compile time?
  • Additionally, if a and b are references, it is simply transformed to PartialOrd::(a, b)?

Yes and no. If a and b are references, it is transformed to PartialOrd::gt(&a, &b) just like it is for any other types. It just so happens that the compiler has an implementation of PartialOrd for references that forward the call to the underlying type, so it still works.

3 Likes

For reference, here it is: cmp.rs - source (rust-lang.org).

1 Like

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.