The Confessional Thread: Parts of Rust that I still don't get after all this time

I confess: the baggage of knowledge from other languages can be counterproductive. I didn't know about "variable name shadowing". In every other language (that I learned) this would be a clear amateur typing error. After months of Rust coding I learned to love "variable name shadowing". But the feeling that it can produce nasty bugs cannot leave my soul. I still don't get it why we don't have a special syntax for shadowing. Something different from initializer "let". Maybe "lets" could be the short "let shadowing". It would calm my soul to have the possibility to explicitly express my intent of shadowing. No nasty bug possible in that way. Thanks for listening my confession.

7 Likes

That's actually sortof interesting. It seems that shadowing is the simplest feature of Rust that seems plausibly easy to misinterpret. Wondering if someone who has been around longer knows why a different keyword wasn't chosen for shadowing, or if there's a thread somewhere to read more about that.

2 Likes

This has of course been discussed at length over the years:


Personally I like shadowing in Rust. It has proved useful. It's unlikely to cause bugs that don't show up almost immediately, at compile time or first testing.

I loath the the idea of adding more keywords and language complexity for such non-issues.

5 Likes
1 Like

Hmm, I think I have stumbled upon something I thought I understood but it turns out I don't (cc @ExpHP: we discussed about this a long time ago): the meaning (and thus variance) of + 'lifetime in trait objects.

That is, the following program does not compile (it would be unsound if it did!):

  • EDIT: I am not so sure anymore that it would be unsound :sweat_smile:, quite the opposite actually
trait Trait {}
const _ : () = {
    fn check<'short, 'long : 'short> (
        it: &'short mut Box<dyn Trait + 'long>,
    )
    {
        let _: &'short mut Box<dyn Trait + 'short> = it;
    }
    let _ = check;
};

i.e., type T1<'x> = &'fixed mut Box<dyn Trait + 'x> is not covariant;

but

trait Trait {}
const _ : () = {
    fn check<'short, 'long : 'short> (
        it: &'short mut (dyn Trait + 'long),
    )
    {
        let _: &'short mut (dyn Trait + 'short) = it;
    }
    let _ = check;
};

does compile fine, meaning that

type T2<'x> = &'fixed mut (dyn Trait + 'x) "is covariant" ??

  • Despite trying to, I haven't been able to exploit that unexpected (co)variance into something unsound;

I'd never have expected Box / &_ (covariant) indirection to change the variance of a type, so there is clearly something I'm missing w.r.t indirection and trait objects' attached / inherent lifetime bound.


If somebody is also interested / intrigued by this, feel free to start a thread where we can discuss about it.

6 Likes

Huh, I'm not sure if I recall that conversation, but that's positively bizarre. I would definitely expect both to be invariant.

Yeah, if we can open a thread for that I'd like to take a stab at exploiting unsoundness with it...

2 Likes

I love this thread. :slight_smile: In some ways it seems kind of cool how Rust itself is like a living science experiment where tons of people can contribute to it from all ranges of completely clueless newbies, to experts in one thing and clueless in others, to a complete expert at everything ( if there's such a person, but I doubt it! ).

Rust is safe enough, but not too safe at the same time. I don't know I've ever seen a better balance in computing.

Anyway, lets see, what I don't get in Rust yet...well I'd have to say FFI is a big one. That's kind of a direct result of not knowing C or C++ at all and not having an great understanding of all the rules not to break to keep unsafe code sound.

I think I'm perfectly capable of grasping that stuff, I just think it would take some time to get used to the dark arts necessary to soundly compose unsafe code. One day it will probably be worth learning, but it hasn't been yet.

I essentially get all the most major points of Rust including traits and trait bounds, generics, lifetimes, async, etc., but not super deep in. Once it gets to a certain point for each subject, it goes into the black magic realm for me.

Any time I need to get a little deeper to make something work, I open up a forum topic and usually some guru that gets the topic helps out until I usually go a little outside my initial comfort zone and I leave knowing more than when I started.