Rust function pointer Contravariant

254 views Asked by At

I having trouble getting my head around contravariance in Rust.

Specifically:

However, the same logic does not apply to arguments. Consider trying to satisfy:

fn handle_animal(Animal);

with

fn handle_animal(Cat);

The first function can accept Dogs, but the second function absolutely can't. Covariance doesn't work here. But if we flip it around, it actually does work! If we need a function that can handle Cats, a function that can handle any Animal will surely work fine. Or to relate it back to real Rust: if we need a function that can handle anything that lives for at least 'long, it's perfectly fine for it to be able to handle anything that lives for at least 'short.

(from: https://doc.rust-lang.org/nomicon/subtyping.html)

It's this part I can't get my head around:

Or to relate it back to real Rust: if we need a function that can handle anything that lives for at least 'long, it's perfectly fine for it to be able to handle anything that lives for at least 'short.

Wouldn't that not work as if you pass 'short somewhere where it needs 'long, it would mean that the 'short being passed in would not live long enough?

I am aware that when it comes to lifetimes if 'long: 'short, then 'long is a subtype of 'short (as 'long is 'short and more), even with this in mind, I'm still struggling with the above..

Can someone help me make sense of it?

Also, when it come to variance, why do we say 'over' as in: &mut T is invariant over T'?

2

There are 2 answers

0
Jeff Garrett On

Wouldn't that not work as if you pass 'short somewhere where it needs 'long, it would mean that the 'short being passed in would not live long enough?

It's the inverse. We are passing in a 'long where we need a 'short, and that works.

Break down the quote:

if we need a function that can handle anything that lives for at least 'long

We need a function that can accept 'long, which means we must have 'long (or even longer) we are going to pass to it.

it's perfectly fine for it to be able to handle anything that lives for at least 'short

So, we have a 'long to pass as an argument, and a provided function that accepts 'short. That's OK. The function needs it to live at least 'short and it does since it lives at least 'long.

0
harmic On

Answering the other question:

Also, when it come to variance, why do we say 'over' as in: &mut T is invariant over T'?

If there are multiple parameters, then there may be different variances for the different parameters.

For example &'a mut T has two parameters, 'a and T. It is covariant over 'a and invariant over T.