sapphie
sapphie

Reputation: 57

Rust type inferencing oddity

I ran into a weird situation earlier. I wrote:

if rand::random() < self.food_chance {...}

(self.food_chance is of type f32)

and I got a type inferencing error:

   |
71 |             if rand::random() < self.food_chance {
   |                ^^^^^^^^^^^^ cannot infer type for `T`

However this code compiles

if self.food_chance > rand::random() {...}

And I'm left wondering. Is there a reason for this behaviour? Is it even intended behaviour?

I know a little bit about type inferencing theory, and I know that most of the algorithms are agnostic to lhs/rhs, so I'm tempted to think this is expected behaviour rather than straight up a bug.

I tried searching around, but I never got anything close to this.

Upvotes: 4

Views: 120

Answers (2)

Sven Marnach
Sven Marnach

Reputation: 601489

That's basically because Rust can never infer the type of the receiver. The type of the receiver must be known to perform method lookup, and since

rand::random() < self.food_chance

is equivalent to

std::cmp::PartialOrd::lt(&rand::random(), &self.food_chance);

the receiver is the left-hand operand.

In the expression

self.food_chance > rand::random()

on the other hand, the receiver is known, so Rust can perform method lookup. It will only find a single implementation for f32 as the receiver, namely PartialOrd<f32>, which then in turn determines the type of the right-hand side. If there were implementations for different right-hand side types, Rust would not be able to infer the type in that case either.

To understand why Rust can't infer the receiver, take a look at how Rust's method lookup process works. The first step is to build a list of candidate types based on the type of the receiver. This obvious only works when you already know the type of the receiver.

Upvotes: 7

vandenheuvel
vandenheuvel

Reputation: 359

The > operator is sugar for a method; the partial_cmp method of the PartialOrd trait. The method is called with the left-hand side as the self argument; this determines which implementation of PartialOrd is used. Because you could implement the PartialOrd trait for different types with f32 as the right-hand side type, the implementation of PartialOrd is only uniquely determined if the type of the left-hand side is known. This implementation of PartialOrd, in turn, determines the type required from rand::random.

Upvotes: 3

Related Questions