Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 778
sapphie Avatar asked Dec 24 '22 02:12

sapphie


1 Answers

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.

like image 71
Sven Marnach Avatar answered Dec 26 '22 01:12

Sven Marnach