Тёмный

Safe Rust AIN'T SAFE!? (cve-rs) 

Residual Entropy
Подписаться 1,5 тыс.
Просмотров 49 тыс.
50% 1

Chapters:
0:00 Intro
1:03 General Channel Update
1:53 Rust Basics - Ownership & Borrowing
4:51 Rust Basics - Lifetimes
8:00 A Very Weird Function
11:08 Attempt #1
13:26 Storing `weird` in a Variable
14:26 A Clue!
15:23 Variance
18:48 The Final Trick
The bug: github.com/rust-lang/rust/iss...
fake-static: crates.io/crates/fake-static
cve-rs: github.com/Speykious/cve-rs

Наука

Опубликовано:

 

16 июн 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 284   
@residual-entropy
@residual-entropy 3 месяца назад
Alright, I've made a Part 2 video that hopefully can address some of the confusion / questions people have. Feel free to check it out: ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-fdu6OcQX5gE.html
@brandonlewis2599
@brandonlewis2599 3 месяца назад
Not able to play either video. Just get a generic error.
@residual-entropy
@residual-entropy 3 месяца назад
@@brandonlewis2599 Huh, it works fine for me.
@Oler-yx7xj
@Oler-yx7xj 3 месяца назад
Using necromancy to extend lifetimes, another thing I didn't think I would see. Great Video
@AlexKen-zv8mm
@AlexKen-zv8mm 3 месяца назад
walking _dead
@snowman4933
@snowman4933 3 месяца назад
If you said this out loud before a non-technical person, they would've literally started thinking that we programmers are doing dark magic
@frankbauerful
@frankbauerful 3 месяца назад
The RU-vid algorithm recommended me this video. Probably because I was watching the trial of the armorer who is on trial because of unsafe handling of guns on the set of the movie Rust. Well done RU-vid AI 👍
@mohitkumar-jv2bx
@mohitkumar-jv2bx 3 месяца назад
This was great. When i saw this on reddit, i didn't get it. Even the docs were not that useful. This explained the issue very nicelyvv
@residual-entropy
@residual-entropy 3 месяца назад
Thanks, glad to hear it!
@xshady2967
@xshady2967 3 месяца назад
finally someone (maybe not first one) is shedding some light on rustc soundness bugs here on youtube, thanks
@pqnet84
@pqnet84 3 месяца назад
I'm not sure what's more "sus" in this: the ability to create "weird" functions that can leverage type information of arguments to infer lifetime nesting or the covariance of reference to reference lifetimes. Probably the ability to cast an & 'static & 'static to a &'a &'b in a single step is the issue: If you are forced to go through an intermediate step (such as &'a &'static) you'd find yourself banging against the borrow checker fairly soon (i would think you would never be allowed to create a &'static &'b)
@residual-entropy
@residual-entropy 3 месяца назад
See my part 2 video - ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-fdu6OcQX5gE.html You very much can do it one step at a time, explicitly laying out all the types, and the borrowck is none the wiser. ;)
@jfb-
@jfb- 3 месяца назад
I feel like what's up here is that weird should be a function that has a bound 'a : 'b, which can be thought of as an extra argument that it needs to accept as a proof that a outlives b (just like when a function has a bound that T: Display, you can think of it as accepting the actual implementation of T being Display as an argument). Then the type &'b&'a() isn't actually carrying that proof, it must be carried separately.
@residual-entropy
@residual-entropy 3 месяца назад
@@jfb- This is a really good thought- traits are secretly just implicit parameters that the compiler can pass for you. In for example the Scala language it doesn’t have traits natively but you can get them this way, because it does let you mark parameters as implicit and the compiler will figure them out. So the function really needs to accept some sort of proof that `'a: 'b` as an argument. Rust sort of pretends like `&'b &'a ()` does this but it doesn’t. Because any `&'b &'static ()` is clearly an `&'b &'a ()`, but a proof that `'static: 'b` is clearly *not* a proof that `'a: 'b`. I really like that actually. :)
@Lecopivo
@Lecopivo 3 месяца назад
Imagine a function that takes a proof that `a
@quickdudley
@quickdudley 3 месяца назад
@@residual-entropy Traits could in theory just be implicit parameters that the compiler passes for but that's actually not how rustc implements them unless you use the `dyn` keyword.
@pqnet84
@pqnet84 3 месяца назад
Interestingly this video has brought enough attention to the original bug report that they had to close the conversation because of spam.
@residual-entropy
@residual-entropy 3 месяца назад
It didn't- as far as I can tell the `cve-rs` project got up high on Hacker News. Assuming I'm not misremembering it was locked for spam before my video.
@haraseesgill8491
@haraseesgill8491 3 месяца назад
I’ve been sharing this with others. You’ve done a great job covering this, and thanks for sharing such a fascinating problem in a very digestible way. Hope your channel keeps growing… I’d love to keep learning and your style is really well done and organized
@residual-entropy
@residual-entropy 3 месяца назад
Thank you so much! :)
@jongeduard
@jongeduard 3 месяца назад
I have seen both videos. Fantastic explanation. I have come across earlier people mentioning it, but I did not read the details yet. The thing is, everything has bugs. But the number and significance of bugs strongly differs. In Rust these are both low. You really have to do quite a lot of specific work make this problem show up. So it does not change at all how much I like Rust and it's actually amazing how people do their best to test and experiment with everything. It's part of actually making it all better.
@Matt23488
@Matt23488 3 месяца назад
Wow. That is really neat. I don't have a ton of experience with Rust, but I completely understood your explanation. Although it is definitely a bug, it thankfully doesn't seem like something someone would inadvertently create in real code, unless they are dealing with complicated lifetime semantics without fully understanding lifetimes...
@residual-entropy
@residual-entropy 3 месяца назад
Glad you liked it! You’re right that it seems very unlikely to create by accident, but I hate to say I don’t think you’re wrong about it being introduced by accident being totally impossible either.
@nordgaren2358
@nordgaren2358 3 месяца назад
It's such a pain in the ass to write a buffer overflow in this language, the cve-rs repo needed an issue for it's cve (It was not always generating a buffer overflow on every target)
@_fudgepop01
@_fudgepop01 3 месяца назад
2:15 the moment I saw that the first generic numbers typed were 69 and 420 was the moment I knew this was going to be a damn good watch
@residual-entropy
@residual-entropy 3 месяца назад
This is the way. ;)
@RootsterAnon
@RootsterAnon 3 месяца назад
Wow, the amount of info in this video is wild. Thank you for documenting and sharing this with us, it was a nice read to know about.
@residual-entropy
@residual-entropy 3 месяца назад
Thanks, glad you enjoyed it! :)
@sudonick-kn5zn
@sudonick-kn5zn 3 месяца назад
dude you explained the cve and lifetimes so well! learned a lot from this video.
@residual-entropy
@residual-entropy 3 месяца назад
Glad you liked it! :)
@karpfenboy
@karpfenboy 3 месяца назад
explained it so well that it felt like a really simple conclusion in the end
@residual-entropy
@residual-entropy 3 месяца назад
That’s the idea ;)
@aronhegedus
@aronhegedus 3 месяца назад
really good explanation, I've done a bit of rust and felt like I understood this! thanks for the video
@residual-entropy
@residual-entropy 3 месяца назад
Thanks for that, glad you liked it!
@samuelwaller4924
@samuelwaller4924 3 месяца назад
This is an amazing video. Love the NecromancerWhoLovesCats
@residual-entropy
@residual-entropy 3 месяца назад
Thanks! Glad you liked my questionable explanation lol. :)
@TCMx3
@TCMx3 3 месяца назад
really enjoyable discussion of the issue. I will say I didnt expect to see exactly that cat reference, but I dont hate it lol
@aoeuable
@aoeuable 3 месяца назад
I am now even more convinced that subtyping is the root of all evil.
@residual-entropy
@residual-entropy 3 месяца назад
It is interesting given some languages like Haskell don’t have subtyping at all.
@binary_gaming113
@binary_gaming113 3 месяца назад
Great explanation!
@residual-entropy
@residual-entropy 3 месяца назад
Thanks, glad you enjoyed it!
@doce3609
@doce3609 3 месяца назад
This is an amazing explanation
@residual-entropy
@residual-entropy 3 месяца назад
Thanks, glad it worked for you! :)
@kfftfuftur
@kfftfuftur 3 месяца назад
Ultimately I think the bug is, that you can only replace &'b &'a () with &'static &'static () if it is a valid type to begin with. If 'a doesn't outlive 'b then &'b &'a () will be equivalent to infallible since no valid reference can outlive the value being referenced and therefore it has no valid representations on runtime. To fix this the compiler would in addition to checking if &'static &'static () can be treated as &'b &'a () also need to check if any lifetime conditions that arise along the way are met.
@residual-entropy
@residual-entropy 3 месяца назад
Yes that’s right but the trick is how do you remember those conditions. Really the type of `weird` should be something like `for where 'a: 'b fn(…) -> …`. But that type currently doesn’t exist, so you’d have to add that to the language.
@rupen42
@rupen42 3 месяца назад
Great explanation! I fully expected not to understand anything but I could follow everything!
@Skyb0rg
@Skyb0rg 3 месяца назад
You touched on it at 18:20, but the Rust Vec type is neither co- or contravariant. This is because you can mutably add elements! If you only read elements it’s contravariant; if you only add elements it’s contravariant. It’s sometimes called invariant, and now I’m curious how Rust handles that.
@residual-entropy
@residual-entropy 3 месяца назад
Actually Rust’s `Vec` type is covariant! You can find this here: doc.rust-lang.org/nightly/nomicon/subtyping.html Because of Rust’s borrowing rules you can only have one mutable reference, so it’s actually fine for it to be covariant. If you want it to behave more normally you would have to use an interior mutability type like `Cell`- those actually are invariant.
@a46475
@a46475 Месяц назад
​@@residual-entropyThen it should not be. It is not fine. If I define a function that accepts a Vec and you pass it Vec and the function adds a dog to it, what do you have?
@residual-entropy
@residual-entropy Месяц назад
@@a46475 To add stuff to it you need to have a mutable reference to it (`&mut Vec`). Mutable references are invariant (and this is why).
@a46475
@a46475 Месяц назад
@@residual-entropy oh ok
@jpjude68
@jpjude68 3 месяца назад
sounds like a possible solution to the lifetime problem could be applying the idea of a hard link instead of what seems like a symbolic link : any number of instances can reference a bloc of data, but the data is dropped if there are no references remaining
@residual-entropy
@residual-entropy 3 месяца назад
It sounds like you’re describing reference counting to manage memory. This is a thing (it’s what swift does), every pointer also has a reference count, which is incremented when a reference is created, decremented when the object goes out of scope, and when it’s zero you free the object. You can create a reference counted pointer in Rust with the `Rc` type. Reference counting everything (like swift afaik) has pretty crappy performance, Rust is trying to get the same speed as C and C++. All this incrementing/decrementing takes time, and more importantly it also is very cache-unfriendly (you can google more I don’t think I can explain it in a yt comment if you don’t know). But regardless, the point is that reference counting is slow- it can actually be slower than full on garbage collection like most languages have. Hopefully that clears things up a bit. :)
@konkitoman
@konkitoman 3 месяца назад
Really good video! Thanks for putting a spot light on this! But how the function is cast from fn(&'b &'a (), &'a T) -> &'b T to fn(&'static &'static (), &'a T) -> &'static T You can write extend like this: fn extend &'static T { let fp: fn(&'static &'static (), &'a T) -> &'static T = weird; fp(FOREVER, borrow) } This is simpler to understand and to see that is a auto casting problem!
@residual-entropy
@residual-entropy 3 месяца назад
Thanks!
@nevokrien95
@nevokrien95 3 месяца назад
I love the video you really build up to it well. Who's bright idea was it that's every lifetime is a subtype of static? Like if you think about it for a bit that's not true as u have clearly showen. If they wanted a generic lifetime they could have used any.
@residual-entropy
@residual-entropy 3 месяца назад
Thanks! It’s not that every lifetime is a subtype (sublifetime really) of 'static - it’s that 'static is a subtype of every lifetime. But yeah, this is essentially a hole where that’s not the case - nested references hide additional constraints you’re dropping. Again tho ideally (and if you don’t want to break existing code) those extra constraints should be separate from the reference type itself. Then it would be totally correct to say &'static T is a subtype of &'a T for any T and 'a.
@DooMWhite
@DooMWhite 3 месяца назад
Amazing video!
@residual-entropy
@residual-entropy 3 месяца назад
Thanks, glad you liked it!!!
@DooMWhite
@DooMWhite 3 месяца назад
@@residual-entropyGonna check the Bad Apple one now.
@downthecrop
@downthecrop 3 месяца назад
Good vid brother 🙀
@Speykious
@Speykious 3 месяца назад
Good video, I like the analogies :D
@residual-entropy
@residual-entropy 3 месяца назад
Thanks!
@residual-entropy
@residual-entropy 3 месяца назад
Hold up I only just realized that you're the one who actually made cve-rs lmao. I swear I was just like "that name seems familiar" and then moved on. Thanks for the kind words *and* for making the crate! :)
@Speykious
@Speykious 3 месяца назад
​@@residual-entropyYou're welcome haha. To be completely honest I only did a third of the work (for example Creative0708 iterated on all the safe transmute implementations) and the license we chose mostly reflects the amount of understanding we actually had when making this. To me there was a problem mostly with lifetimes, but you explained how variance plays into it and I can say you made me understand the exploit better than I did before lol
@residual-entropy
@residual-entropy 3 месяца назад
@@Speykious Thanks for clarifying, but also it’s really quite cool to hear that I made it make more sense to even you lol. :)
@coder0xff
@coder0xff 3 месяца назад
So Is the fix that when changing &'b &'a to &'static &'static in one part of the function type that all occurrences of 'b and 'a have to become 'static as well? fn(&'static &'static, &'static T) -> &'static T
@residual-entropy
@residual-entropy 3 месяца назад
Not quite- we aren’t substituting 'a and 'b but we’re just using the subtyping relationship. It’s like converting an `fn(Animal, Animal)` to an `fn(Cat, Animal)`. We aren’t substituting `Cat` for `Animal` we’re just narrowing a type that’s in a contravariant position. I made a part 2 with more detail (which kind of is necessary to understand how to fix it): ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-fdu6OcQX5gE.html Hopefully that helps clear things up.
@whythosenames
@whythosenames 3 месяца назад
They just need to check which function instance is really used when doing such a cast in extend, i.e. the exact values for a and b. Here 'a has to be more general than the 'a provided to extend and to 'static, so for example exactly equal to the provided a. For b, 'b has to be more general than 'static, but from the output, more specific than the provided 'b. Then they could easily check if the function signature is valid, also for other conditions that have to be met (maybe there are others but I am not a rust developer). But that only works if b has a shorter lifetime than a, which is what we want
@residual-entropy
@residual-entropy 3 месяца назад
They can’t, see part 2: m.ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-fdu6OcQX5gE.html
@qbasic16
@qbasic16 3 месяца назад
Great video, you earned a sub 😊
@residual-entropy
@residual-entropy 3 месяца назад
Thanks! :)
@jacobesplin20
@jacobesplin20 3 месяца назад
Great Video!
@residual-entropy
@residual-entropy 3 месяца назад
Glad you enjoyed it! :)
@milasudril
@milasudril 3 месяца назад
I guess these lifetime annotations are more like attributes. In C++, a function pointer must otherwise be an exact match, both with respect to arguments and return type. However, covariant return types are allowed in certain cases when using virtual.
@henkpietjaaphein1122
@henkpietjaaphein1122 3 месяца назад
I'm fairly new to rust yet this was very clearly explained, great job!
@residual-entropy
@residual-entropy 3 месяца назад
Thanks, glad it made sense! :)
@kacper7516
@kacper7516 3 месяца назад
i like how u explain things.
@residual-entropy
@residual-entropy 3 месяца назад
Glad you liked it :)
@mr.togrul--9383
@mr.togrul--9383 3 месяца назад
This is so awesome, you simplified cve rs perfectly, instant sub and like from me
@residual-entropy
@residual-entropy 3 месяца назад
Thanks, I’m so glad you liked it! :)
@LeYuzer
@LeYuzer 3 месяца назад
which theme and font are using?
@residual-entropy
@residual-entropy 3 месяца назад
I’m using the Moegi Dark theme, as for the font it’s just the default which I think is Droid Sans Mono.
@eitanseri-levi2169
@eitanseri-levi2169 3 месяца назад
I cannot unsee this
@IsawU
@IsawU 3 месяца назад
Nicely explained, but not entirely obvious where the complexity in solving this lies. It just feels like since you basically said in the signature of weird_function that 'a and 'static is the same, it should be automatically implied that 'a: 'static and 'static: 'a. Then 'a of extend is 'static and the compiler should scream if you pass anything non 'static to extend. Is this a problem with Rust's current implementation, that it can't be easily modified to handle this case?
@residual-entropy
@residual-entropy 3 месяца назад
So 'a is not 'static, in fact the only bound checked is that ‘static: 'a (well and 'static: 'b). All that needs to happen is for any `&'static &'static ()` to be a valid `&'b &'a ()`, *regardless of what 'a and 'b are*. I really can see why this is confusing, the important thing is where 'a and 'b come from. They are given to the function, when you say `fn extend…` you are saying “for any 'a and 'b you give me, …”. So the compiler when doing variance checks looks to see if `&’static &'static ()` is a subtype of `&'b &'a ()`, which it is for any 'a and 'b. So the conversion is allowed. Someone else said kind of the same thing, we’re never choosing what 'a and 'b are or constraining them inside the definition of `extend`. Sorry for not being clearer about that in the video, hopefully this clears it up a little. :)
@IsawU
@IsawU 3 месяца назад
@@residual-entropy No need to be sorry. Your video still did a lot for me to help me understand how this works. I guess I'm just a little frustrated that I don't understand why the compiler can't catch this :).
@residual-entropy
@residual-entropy 3 месяца назад
​@@IsawU I'm glad the video was able to help at least some. :) The full chain goes something like this: 1. We start with the function `weird`, which is a function declared as `fn weird(...: &'b &'a T, ...: &'a T) -> &b T`. The compiler at this point can tell that if you call `weird(...)` it has to check `'a: 'b`. 2. We put it in a variable, so now `weird` is an actual value with a type. The function `weird` works for any 'a and any 'b, so we give it the type `for fn(&'b1 &'a1 (), &'a1 T) -> &'b1 T`. (This weird `for` is called an HRTB). This is where the bug is - we've silently dropped the constraint that `'a1: 'b1` whenever you call this. It's also why fixing this is very much nontrivial - where does this constraint even go? Creating a type like `for where 'a1: 'b1 fn(...) -> ...` isn't something you can do in Rust (right now, adding this would allow you to fix it). 4. The compiler chooses 'a1 to be 'a and 'b1 to 'b. But by this point the constraint that `'a1: 'b1` is gone, and so we never know to check `'a: 'b`. It now has the more refined type `fn(&'b &'a (), &'a T) -> &'b T`. 5. We play the contravariance card and turn it into a function that takes an `&'b &'a ()` into a function that takes an `&'static &'static ()`. We now have `weird_function`. Hopefully that helps. :)
@whtiequillBj
@whtiequillBj 3 месяца назад
is it known when this bug was introduced? or to rephrase the question is it known if this bug was in a revision of Rust prior to 2015? If it wasn't can the good code not be pushed into the current version?
@residual-entropy
@residual-entropy 3 месяца назад
If you want to learn about how you might fix it (it’s not quite so easy)- there might just be a part 2 video on the subject ;) ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-fdu6OcQX5gE.html
@scottramsay3671
@scottramsay3671 3 месяца назад
Thanks for the clear explaination. After reading about cve-rs on hackernews, it seemed like the importance of it all really rested on if it would be possible or not to organically stumble upon bugs like this. (Or if you'd only encounter them by fuzzing or trying to overwhelm the complexity of stuff). This reminds me of when I was learning Haskell and I wrote some code 'f [x] = ...' thinking it would mark x as an array and not realising that it was a pattern match for an array with a single element x in it. Once I figured out why it wasn't compiling, I felt a bit silly. Clearly I was speaking natural language, not Haskell. From that experiance I can 100% imagine myself organically stumbling across this bug while learning rust for the first time. Especially as a former functional programmer who won't bat an eyelid at functions being assigned to local variables, and making their types more generic.
@NStripleseven
@NStripleseven 3 месяца назад
That’s… uhhh… that’s wild.
@feuermurmel
@feuermurmel 3 месяца назад
Can you add the part to the URLs in the video description? Otherwise RU-vid won't recognize it as URLs (at least in the iOS app). Thanks! 😊
@residual-entropy
@residual-entropy 3 месяца назад
Done! :)
@SalvoBrick-eg3uo
@SalvoBrick-eg3uo 3 месяца назад
IDK why anyone treats software like there will ever be a point where there are zero exploits. Imagine that with physical security or mechanical devices. There are always limitations, and security is always about mitigation. Just like machines will always need mechanical maintainence, electrical and plumbing and roadways etc, computers will always require diligent review. Cheers for breaking down the code! Safety requires vigillance!
@khalloof
@khalloof 3 месяца назад
Nice conclusion, but in the beginning it sounded like you were talking about @residual-entropy . (Got no idea how to mention someone on RU-vid though)
@residual-entropy
@residual-entropy 3 месяца назад
I didn’t think it was referencing me- but maybe I’m just naive lol. Last year I did a microarchitectural security project. You can trust me when I say I am very much aware of the fact that nothing is perfectly secure and all we can do is mitigate to the best of our ability. That said I do think using Rust is a pretty good mitigation tbh. ;) (btw you didn’t mention me but I don’t know how to either lol- fortunately I spend too much of my time reading comments lol)
@khalloof
@khalloof 3 месяца назад
@@residual-entropyApparently it works on replies (although I didn't get the same mention when replying to the other guy). Though I wonder what you think of Zig? Seems memory-safe too, but not as safe in return for a lot more simplicity. Would love it if you make a video about this.
@residual-entropy
@residual-entropy 3 месяца назад
@@khalloof Do not worry. I absolutely love Zig and have a lot to say about it- a video is very much coming once I finish the couple I’m working on right now. ;)
@younesskafia4189
@younesskafia4189 3 месяца назад
That was a really fun video to watch, very informative!
@residual-entropy
@residual-entropy 3 месяца назад
Thanks! :)
@NerosCreations
@NerosCreations 3 месяца назад
Great video. Simple fix: when defining the weird_function variable, it seems that the compiler should be able to infer that 'a and 'b must both be 'static based on the lifetime of the witness variable. It should then only allow calls to extend when the argument has lifetime of 'static. -- Essentially the compiler should change the type of extend under the hood, so that it becomes fn(&'static T) -> 'static T. Why wouldn't this work?
@residual-entropy
@residual-entropy 3 месяца назад
Glad you liked it. :) The compiler first has to figure out the type of just `weird`, which it can happily infer as `fn(&'b &'a (), &'a T) -> &'b T`. Then when we define `weird_function` we aren’t saying “okay change 'a and 'b to 'static”. We’re saying “hey can I give you an `&'static &'static ()` instead of an `&'b &'a ()`” and this is totally fine. We aren’t ever defining 'a or 'b inside the function, when you say `fn extend…` you’re saying this function will work for any 'a and any 'b (chosen when you call it). But the compiler knows that a `&’static &’static ()` will always count as a `&'b &'a ()` no matter what 'a and 'b are. Hopefully that made sense, let me know if it didn’t or you have other questions. :)
@AlexKen-zv8mm
@AlexKen-zv8mm 3 месяца назад
@@residual-entropy If possible start Rust tutorial series like crust in rust by Jon Gjengset. You have lots in your head that other would like to hear about it.
@residual-entropy
@residual-entropy 3 месяца назад
@@AlexKen-zv8mm Thanks for the suggestion, I just might give that a try.
@AlexKen-zv8mm
@AlexKen-zv8mm 3 месяца назад
@@residual-entropyyou should , take your time, enjoy it.
@meqativ
@meqativ 3 месяца назад
18:16 the cops are already coming after you
@nexpro6985
@nexpro6985 3 месяца назад
It sounds like you speeded up the video.
@residual-entropy
@residual-entropy 3 месяца назад
Just a bit- I felt like I was talking too slow but I’m not going to keep doing that or anything.
@Tombsar
@Tombsar 3 месяца назад
@@residual-entropyPlease don’t speed it up like this in future videos. I found it very off-putting and hard to understand in places.
@residual-entropy
@residual-entropy 3 месяца назад
@@Tombsar I won’t.
@discreaminant
@discreaminant 3 месяца назад
Has it been found already? Is it going thru rfc?
@residual-entropy
@residual-entropy 3 месяца назад
See description for a link to the issue. There’s no clear way to fix it without either making massive changes to the Rust compiler or adding a new language feature.
@Otakutaru
@Otakutaru 3 месяца назад
I am not ready for rust. Now every ' in plain text scares me
@residual-entropy
@residual-entropy 3 месяца назад
Well this is advanced stuff you probably shouldn’t do lol, I wouldn’t be discouraged to learn the language because some crazy type system issue doesn’t make sense. Btw someone else commented on the part 2 video where I said “'twas” that they thought 'twas was a lifetime lol. ;)
@noxagonal
@noxagonal 3 месяца назад
Same... Although I love template metaprogramming in C++ to a point where my code sometimes looks like alien language... So... I guess I'm a little hypocritical.
@residual-entropy
@residual-entropy 3 месяца назад
@@noxagonal Hey, I’ve written some heinous stuff with C++ templates, type traits, concepts, and decltype/declval. It’s fun and seems like your making progress but usually I get to the end and realize that I didn’t actually need all that chaos lol.
@Otakutaru
@Otakutaru 3 месяца назад
@@residual-entropy I understand. The truth is, that I've never had to deal with lifetimes in my rust journey, is that kind of thing that you know it's there if the situation requires it
@residual-entropy
@residual-entropy 3 месяца назад
@@Otakutaru You will one day- and you’ll have the wonderful privilege of not needing to know all the crazy details like you do for this bug. ;) Best of luck on your Rust journey tho! :)
@theohallenius8882
@theohallenius8882 3 месяца назад
Perfect, now I no longer have to fight the compiler, just call extend() everywhere 🤣🤣🤣🤣
@diadetediotedio6918
@diadetediotedio6918 3 месяца назад
This is a very specific way to do things But also, it feels like an intuitive error, why would 'a be transmuted to 'static just because you called weird_function passing FOREVER as the argument? The compiler should have rejected passing 'borrow' as the second argument because 'a of borrow is externally defined by the caller and FOREVER is externally defined by a static variable, so any 'a infered by FOREVER locally on weird_function while calling it with FOREVER as the first argument should be objectively different from the 'a from 'borrow' being passed in the same function. This by itself should not be already a reason to reject the call entirely?
@residual-entropy
@residual-entropy 3 месяца назад
There's only one 'a which is the one passed to the `extend` function. For simplicity let's call the lifetimes 'a and 'b in the definition of `weird` 'a1 and 'b1. So pretend we said `fn weird(...) ...`. When creating `weird_function` the compiler needs to see if we're allowed to convert a `for fn(&'b1 &'a1 (), &'a1 T) -> &'b1 T` to a `fn(&'static &'static (), &'a T) -> &'b T`. The weird `for` bit is called a Higher Rank Trait Bound or HRTB, and basically just says "for any 'a1 or 'b1 you give me ...". The compiler chooses 'a1 to be 'a and 'b1 to be 'b, and so now we just have to convert `fn(&'b &'a (), &'a T) -> &'b T` to `fn(&'static &'static (), &'a T) -> &'b T` which it can. So now we call the function, the compiler checks that `FOREVER` is a `&'static &'static ()` which it is and so that part is fine. And then it checks that `borrow` is a `&'a T` which it so we're all good. So the choice of 'a1 and 'b1 (which in the original code are 'a and 'b inside the definition of `weird`) is done explicitly by us when we say `let weird_function: ... = ...;`. The 'a and 'b in `fn(&'static &'static (), &'a T) -> &'b T` refer specifically to the 'a and 'b for the `extend` function. Let me know if that doesn't make sense (this stuff definitely is weird). :)
@tee1532
@tee1532 3 месяца назад
​@@residual-entropy It doesn't make sense to me. The line: let weird_function: fn(&'static &'static (), &'a T) -> &'b T = weird; seems to obviously require that &'a is at least as long-lived as &'static, because otherwise it would not be compatible with weird's signature. According to weird's signature: fn weird(_witness: &'b &'a (), borrow: &'a T) -> &'b T { It is obvious that the lifetime of weird's second argument must be the same as or longer than the lifetime of weird's first argument. So in weird_function's type let weird_function: fn(&'static &'static (), &'a T) -> &'b T = weird; the second argument &'a T must have a lifetime longer-or-the-same as the first argument which is &'static. So why does the compiler allow calling weird_function with a second argument that has a lifetime shorter than &'static ?
@orgs804
@orgs804 3 месяца назад
Which vscode color scheme is that?
@residual-entropy
@residual-entropy 3 месяца назад
Moegi Dark :)
@anonymousalexander6005
@anonymousalexander6005 3 месяца назад
I also love that `dyn` can implement impossible trait bounds :). Until some headway is made on constrained HRTBs, I think this will just live within "language flaws" for the rest of Rust's life probably. I will say, now that I think about it, it might actually be easier to explain mathematical notation and then explain from there. That might just be me, I do love me some proposition logic.
@residual-entropy
@residual-entropy 3 месяца назад
I'm a fan of propositional logic and notation too, but that would probably just be confusing to most people, and also I don't really know of a standard syntax for things like lifetimes that are Rust-specific. Those might exist but I mean even if they do almost nobody would recognize them.
@razvanfilea8076
@razvanfilea8076 3 месяца назад
Is this going to be fixed by the polonius project?
@residual-entropy
@residual-entropy 3 месяца назад
Polonius (NLLs) is about making the lifetime system *more* accepting. If you’re curious to learn more and also understand how to fix it boy do I have the part 2 video for you: m.ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-fdu6OcQX5gE.html ;)
@ukyoize
@ukyoize 3 месяца назад
Rust sure is weird
@richardmorgan7734
@richardmorgan7734 3 месяца назад
I am wondering, what are potential ways this can be fixed? Everything seems legit, and I do not think adding to the compiler "check for these series of functions" would be a sound solution.
@richardmorgan7734
@richardmorgan7734 3 месяца назад
nevermind, i see your second video lol
@residual-entropy
@residual-entropy 3 месяца назад
I made a part 2 video which explains the ideal fix ( ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-fdu6OcQX5gE.html ), BUT basically you want to be able to encode the constraint that 'a: 'b in the function type itself.
@KhalilEstell
@KhalilEstell 3 месяца назад
Oh wow n that's crazy!
@torsten_dev
@torsten_dev 3 месяца назад
So why is the fix not just that if you use contravariance to extend a lifetime argument that appears somewhere covariant like the return that that lifetime also has to be changed?
@residual-entropy
@residual-entropy 3 месяца назад
A couple things: - Returns are covariant not invariant but I’ll assume that was a typo - The actual issue here isn’t that you can do contravariance with lifetimes (although disallowing this was proposed as a short-term fix) - I’m not sure what you mean by “the lifetime has to be changed”? Changed how? The lifetime is “changed” in the sense that it’s converted from `&'b &'a ()` to `&'static &'static ()` which is totally fine, but the hidden constraint that `'a: 'b` was dropped. How would you change the lifetime to keep that constraint alive? Sorry if things were confusing.
@torsten_dev
@torsten_dev 3 месяца назад
@@residual-entropy I'm beginning to see why this hasn't been resolved in a decade. Is there a proposed alternative fix?
@residual-entropy
@residual-entropy 3 месяца назад
@@torsten_dev If you read through the issue you can see that the sort of ideal solution is to allow constraints to be added to function traits and then to have these constraints be automatically generated as necessary. The type of `weird` is currently `for fn(&'b &'a …) -> …` but the idea is to change it to `for where 'a: 'b fn(&'b &'a …) -> …`. The `for` bit exists and is called a Higher-Rank Trait Bound or HRTB. Basically it just says “hey when you actually use this type you gotta give me a 'a and a 'b.” The proposal is to add `where` clauses to this expression. Then when you actually sub in 'a and 'b from the `extend` function you would know to check `'a: 'b`. Of course this already involves creating a new language feature that extends an already-complicated language feature (HRTBs). You would even (hypothetically if it were implemented) be able to have lifetime where clauses inside of type where clauses like: `… where T: for
@Turalcar
@Turalcar 3 месяца назад
@@residual-entropy I remember wanting to use HRTBs for an associated type trait A where 'b: 'a }. (type B is only defined for lifetimes that outlive 'a) and it didn't work but I didn't expect the current implementation to be unsound. I would probably prefer if they wouldn't allow dropping implied constraints and went with the largest supported type instead.
@taishi-sama-tfc
@taishi-sama-tfc 3 месяца назад
​@@torsten_dev developers said that solution of this problem relies on features of new rustc type checker which is still in development.
@fabiopetrillo
@fabiopetrillo 3 месяца назад
This video is the proof that Rust is very safe in practice.
@residual-entropy
@residual-entropy 3 месяца назад
Hey, I did put "under very specific circumstances usually its fine" in the thumbnail. Obviously everyone noticed that. /s
@lovelaceada5127
@lovelaceada5127 3 месяца назад
Really clear and cool explanation bro
@residual-entropy
@residual-entropy 3 месяца назад
Thanks, glad you liked it. :)
@korigamik
@korigamik 3 месяца назад
man this is a cool video and the style. Can you tell me what you use to create the video, the editor stuff, voiceover and tools that you've used?
@residual-entropy
@residual-entropy 3 месяца назад
Thanks! There really wasn’t much too it- I just screen-recorded vscode in zen mode for the actual coding parts, and then I used kdenlive to edit everything. The VO was recorded on my phone resting on top of a bunch of small boxes so that it was just above like where my laptop webcam is.
@zookaroo2132
@zookaroo2132 2 месяца назад
this turned out to be the simplest way to learn Rust lol
@residual-entropy
@residual-entropy Месяц назад
:)
@Azyo64
@Azyo64 3 месяца назад
Very interesting issue. One that should really deserve a fix. But the problem clearly come from the line: let weird_function: fn(&'static &'static (), &'a T) -> &'b T = weird; // => 'a and 'b should be deduced to be 'static Maybe the bug exist because of lifetime, but it should be possible to do the same thing with types, so lets take your necromancers instead: fn chimeraNecromancer(a1: Soul, a2: Soul) -> Chimera; let weirdNecro : fn(Soul, Soul) -> Chimera = chimeraNecromancer; // => Animal should only be Cat! let catFish = weirdNecro(nemoSoul, myCatSoul); // error nemoSoul is not a Soul! The exact same problem exist with types! I tested and rust give me an invalid cast on chimeraNecromancer. So the same logic should be used for lifetime as for types, and that problem would be solved. There might be other variants that are more complex, but that one shouldn't have waited so long before being addressed (when it is). (Instead, people have been putting a lot more effort into using this this bug to break rust)
@residual-entropy
@residual-entropy 3 месяца назад
Lifetimes don't behave like types in a very specific way. I made a Part 2 video that explains this in more detail (including the specific way in which types and lifetimes behave differently). ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-fdu6OcQX5gE.html
@parlor3115
@parlor3115 3 месяца назад
I'm not worried about these issues, because in order to invoke these exploits, you'd actually have to understand Rust which only like 2 people do (out of the entire user base that is 5 people). The only other option is installing libraries authored by those 2 people, but you can't do that as a malicious actor since Rust is a server-side language.
@residual-entropy
@residual-entropy 3 месяца назад
*sigh* Sure Rust isn’t that popular but it’s been growing fast and it’s definitely more than just a few people. And yeah it’s not a serious security exploit- but it’s still a problem. And I’m not sure what server-side has to do with it not being a problem, if this ends up in some library that your server users now you’re back to the same world as broken c code where you can read loads of uninitialized memory and probably rce if you’re clever about it.
@comma_thingy
@comma_thingy 3 месяца назад
13:00, your logic on why &'static &'static should be able to coerce to &'b &'a seems shakey. Given the earlier statement that &'b (type with lifetime 'x) means that 'x outlives 'b, and &'a has a lifetime (at most) of 'a, then 'b must be shorter than 'a. So the supposed intermediate step of "&'static &'a ()" should be valid is wrong. Unfortunately, it seems the compiler also seems to miss this, hence allowing 'b to be independent of 'a, even though the function definition should implicitly force 'a:'b
@residual-entropy
@residual-entropy 3 месяца назад
If we keep things as they are then, well, yes the conversion is invalid. The thing is that this is simply the result of borrows being covariant in their lifetimes- `S: T` implies `&’q S: &’q T`. So (*if* you don’t implement the proposed fix and you’re forced to have a constraint `'x: 'y`, then we have no problems. The thing is if we run with your version and say that borrows *aren’t* covariant that’s a pretty basic assumption and that would require reworking loads of stuff in the compiler and breaking heaps of existing code. So yes that conversion is incorrect but only if we assume the prior step isn’t. Hopefully that makes sense. :)
@gordonfreimann
@gordonfreimann 3 месяца назад
i feel sorry for rust devs
@guelakais1438
@guelakais1438 3 месяца назад
It's hard to reproach the maintainers of Rust here, which you don't do either. Rust has some unorthodox features and of course they don't always work. Either Rust or one of the following programming languages will show a proper implementation of these features. At the end of the day, programming languages and the features implemented in them are part of a continuous development process. What today's programming languages cannot do, the following ones will.
@residual-entropy
@residual-entropy 3 месяца назад
I do hope that this gets fixed and I fully believe that eventually they’ll get around to it. It’s just that a ton of people see this as something with an “easy fix” and I wanted to clarify that that just isn’t the case here.
@vladomaimun
@vladomaimun 3 месяца назад
Ok but why doesn't rustc complain about the argument borrow not living as along as 'static when weird_function() is called? Does it check the types against the definition of weird() or against the definition of weird_function()?
@residual-entropy
@residual-entropy 3 месяца назад
We aren’t substituting 'a for 'static, we’re just using subtyping. It’s fine to convert an `fn(Animal, Animal)` to an `fn(Cat, Animal)`. If you want to see it step by step also there’s a part 2 video: m.ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-fdu6OcQX5gE.html
@bujitself
@bujitself 3 месяца назад
You missed the transmute part, but cool vid nevertheless
@residual-entropy
@residual-entropy 3 месяца назад
I was actually going to add that but the video was getting kind of long and I wanted to get back to working on the next one, that’s all. Maybe I’ll make a little bonus video with it if I have some time- thanks for the feedback tho.
@hunter-tm2kl
@hunter-tm2kl 3 месяца назад
@@residual-entropy this was a really great vid, would love to see another on transmute when you have time!
@residual-entropy
@residual-entropy 3 месяца назад
Ask and you shall receive (sometimes): ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-qqgDuEi7OU0.html
@residual-entropy
@residual-entropy 3 месяца назад
Ask and you shall receive (sometimes): ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-qqgDuEi7OU0.html
@DeathSugar
@DeathSugar 3 месяца назад
I wonder if it works on pre-nll Rust
@residual-entropy
@residual-entropy 3 месяца назад
The issue was opened in 2015 and NLLs were stable in 2022 so I’m pretty sure it did. :)
@DeathSugar
@DeathSugar 3 месяца назад
@@residual-entropy cranelift, gcc?
@residual-entropy
@residual-entropy 3 месяца назад
I’m not familiar with cranelift and am not sure what you mean by gcc? I don’t think it depends on the compiler backend since it’s a weakness in the type/lifetime system as it currently exists.
@DeathSugar
@DeathSugar 3 месяца назад
@@residual-entropy cranelift uses sophisticated data types to represent everything in rust typesystem, so some states theoretically cannot be represented and compiled by cranelift. gats let them represent read only/write only pointer types which cannot be casted in each other, for example. idea was featured in some twir issue, if I'm not mistaken it to some other project. gcc also has their own rust compiler but I'm unsure how featureful are they, so I wonder if it would even compile with it.
@residual-entropy
@residual-entropy 3 месяца назад
@@DeathSugar Ah, I guess in that case it could be possible for them (cranelift) to add these kinds of constraints then. Thanks for explaining it! :) As for gcc your guess is as good as mine.
@therealyojames
@therealyojames 3 месяца назад
Why does the mic warble in and out of clarity
@residual-entropy
@residual-entropy 3 месяца назад
Because the mic was my phone balanced on some random boxes. ;) I’ll get a real mic eventually…..
@therealyojames
@therealyojames 3 месяца назад
@@residual-entropy ahhhh rip, good video otherwise, I couldn’t for the life of me wrap my head around the lifetime tick marker stuff, but thats my fault lol
@residual-entropy
@residual-entropy 3 месяца назад
@@therealyojames Well I’m the one whose supposed to be explaining it lol. I tried to go through the basics but did so really quite quickly- the book might be helpful here: doc.rust-lang.org/book/ch10-03-lifetime-syntax.html Glad you still liked it tho. :)
@therealyojames
@therealyojames 3 месяца назад
@@residual-entropy nah you did a good job explaining it, my brain just couldnt absorb it very well because I’m sleep deprived rn 😂
@residual-entropy
@residual-entropy 3 месяца назад
@@therealyojames Dw I’m a college student doing a double major- I’m always sleep-deprived. ;)
@user-mj5ww8zg3h
@user-mj5ww8zg3h 3 месяца назад
To listen to it normally set speed to 75%
@residual-entropy
@residual-entropy 3 месяца назад
Yeah I made the mistake of speeding it up a bit since I got nervous I was speaking too slowly. Sorry.
@emjizone
@emjizone 3 месяца назад
Some day we will finally implement mem security at hardware level, instead of fooling around.
@residual-entropy
@residual-entropy 3 месяца назад
Implementing this stuff at the hardware level doesn’t guarantee anything will be totally safe either- some ARM chips have pointer authentication but then some people used side channels to crack it: pacmanattack.com I’ve actually played around with microarchitectural security and implemented an attack known as website fingerprinting, where JavaScript on one website uses the latency to do certain operations to guess what’s happening in another tab (usually you use an ML model). It’s not super reliable but the fact that my sketchy version with a simple decision tree and not that much data worked at all is definitely a bit scary. Solving things in hardware is definitely something that could help, especially given all the code in not-Rust, but it’s not a way out at all.
@kai4166
@kai4166 3 месяца назад
I wanted to give a new programming language a try. I was confused between Go and Rust. I went with Rust because well it makes you think really hard while writing your programs. And that IMO makes you a better programmer. But after seeing this, should I just switch to Go?
@residual-entropy
@residual-entropy 3 месяца назад
Heck no. ;) This isn’t a serious problem because the likelihood of someone doing this by accident is basically zero. But it *is* interesting (at least I think so). Go is a great language too, but you’ll definitely learn more from learning Rust in my opinion. Programming languages are a sort of perspective through which you view the world, and any day of the week I could shout from the rooftops just how valuable having the different perspectives you get from different languages can be. At least until security came and made me get down from the roof. Go and Rust are both pretty nice languages, but Go just isn’t that different from more normal languages. I 100% agree with you that having to really think about what you’re doing is a great thing. If I had a nickel for every time I spent half an hour fighting with the Rust compiler before realizing that my idea was actually just stupid…… I mean then I would be able to afford an actual microphone. Regardless hopefully that makes sense, this is absolutely 0% a reason to not use Rust. I wish you the best of luck on your Rust journey! :) I’m also happy to answer Rust (or even Go if you join the dark side :p) questions too ;) - at this point yt comments are fine and I check them regularly enough (just do it on a Rust video)
@oglothenerd
@oglothenerd 3 месяца назад
The video sounds like it was sped up by 1.25x.
@residual-entropy
@residual-entropy 3 месяца назад
Other ppl said the same thing, back when I made this I sped it up a little because I felt like I was talking too slowly. Haven’t done it after this vid tho.
@oglothenerd
@oglothenerd 3 месяца назад
@@residual-entropy I sped up one of my videos, yeah, never again!
@sansmojo
@sansmojo 3 месяца назад
Alright, I guess I'm slow. I followed up until you started talking about covariance and contravariance. It seems that you're saying that any function that can take an animal soul is a function that can take a cat soul, and so any function that can take a cat soul is a function that can take an animal soul. That makes a bit of sense to me, in that a cat is an animal, so a function that can take a cat soul is a function that can take an animal soul, but that's not really true because it can't take any animal soul; only a cat soul. What am I missing? Maybe another way to talk about it is a vending machine that can accept any US currency (coins or bills) and a vending machine that can accept coins. The vending machine that can take any US currency is a vending machine that can take coins, but the vending machine that can take coins is not a vending machine that can take any US currency (it can't accept bills).
@residual-entropy
@residual-entropy 3 месяца назад
It’s only one way; fn(AnimalSoul) is an fn(CatSoul) but not the other way round.
@kayakMike1000
@kayakMike1000 3 месяца назад
Basically... Its not endorsed by JD Power and Associates.
@drew-et1mm
@drew-et1mm 3 месяца назад
why is the video sped up?
@residual-entropy
@residual-entropy 3 месяца назад
It’s just sped up a little because I thought I was talking too slow. Probably wasn’t the best idea in retrospect, future stuff won’t be.
@LuisCabreraT
@LuisCabreraT 3 месяца назад
If you really want a safe and fast program you should write assembly
@residual-entropy
@residual-entropy 3 месяца назад
Ah yes the safest language of them all
@markcolburn
@markcolburn 3 месяца назад
Well presented.
@residual-entropy
@residual-entropy 3 месяца назад
Thanks! :)
@mzg147
@mzg147 3 месяца назад
wow your keyboard thocks so perfectly 🥵🤤 you need make an asmr channel! 😎 In all seriousness though, thanks for this amazing video, it's soo interesting to mess around with Rust type system
@jonnyso1
@jonnyso1 3 месяца назад
At least I think people are generally aware of that considering the 2023 Rust Survey results.
@icemojo
@icemojo 3 месяца назад
We need more videos on the Internet like this. At the end of the day, Rust is ultimately a tool. A tool which brings many great ideas and benefits, even though it IS NOT a "one size fits all" tool. People should realize this more often. The problem with the Rust community these days (especially on RU-vid) is, wherever corner you turn towards, Rust is being treated like it's some sort of second coming. It's just a tool, people, it's just a tool. Use it where appropriate.
@residual-entropy
@residual-entropy 3 месяца назад
Very much agree. :)
@russianbotfarm3036
@russianbotfarm3036 3 месяца назад
Yeah, it always seemed strange to me that the rust people couldn’t _prove_ it was safe, given that it was designed from scratch, amid sota theory and tools.
@residual-entropy
@residual-entropy 3 месяца назад
Yeah, the fact that the language doesn’t even have a formal specification (and they only recently started on one) has always been concerning to me in much the same vein. At least there is an effort on that front ( github.com/rust-lang/rust/issues/113527 ), but it isn’t great that we don’t even have a draft at this point. I know “probably safe” is very much not easy but the way Rust is supposed to be this rock-solid safe thing it definitely seems off to have so little in the way of formality. Just my thoughts tho.
@steveoc64
@steveoc64 3 месяца назад
Thats barely half a page of code, with a really detailed explanation of the bug, and its still really hard to see that it can be doing the wrong thing. Imagine some dystopian future where Rust is in mainstream use in corporate applications, and this stuff comes up for code review ? You can bet that anyone reviewing this code will just say "It passes the borrow checker - LGTM" and clicks the green button
@sunofabeach9424
@sunofabeach9424 3 месяца назад
sounds just like any other program written in C++
@ultrapoci
@ultrapoci 3 месяца назад
Have you ever read a big C code base? It's so full of macros and weird syntax that it is basically impossible to parse. You already live in the world you describe, mate.
@residual-entropy
@residual-entropy 3 месяца назад
I mean yes that's right. I like to for example use the token-pasting operator (##) in C/C++ to make macros for timing, where I can say `STARTTIMER(Something)` and `ENDTIMER(Something)` and the macro will create the `timerStart_Something` and `timerEnd_Something` variables. It's truly horrendous but especially when I'm just curious and want to try something I do it anyway. We very much do live in that world but (at least imo) part of the point of Rust is to get us out of there. Also I feel like Rust definitely gives you a sense of security where you don't even think about memory issues as a possibility (assuming you don't use unsafe), and if that becomes a *false* sense of security I would say that's definitely a problem. That's all.
@ultrapoci
@ultrapoci 3 месяца назад
@@residual-entropy Well, the presence of this bug is a problem, and hopefully gets resolved sooner rather than later. I don't think false security is a problem, tho. This can be said of any language, since any compiler can have bugs. Programming in C doesn't make a compiler bug less problematic just because C makes less guarantees. Of course, C and C++ have had years and years of people working with them and resolving bug. Also, this is the only known bug in the Rust compiler regarding safety, as far as I know. You still get a ton of benefit using Rust, and it's proven by the people actually building software with it.
@sunofabeach9424
@sunofabeach9424 3 месяца назад
@@ultrapoci the problem is that this bug exists from 2015
@maninalift
@maninalift 3 месяца назад
The "witness" is not a sound witness to a outliving b. Since it is satisfied by lifetimes x >= a y >= b x >= y This doesn't proove (ie act as a witness to) a >= b
@residual-entropy
@residual-entropy 3 месяца назад
Yes. An `&'static &'static ()` counts as an `&'b &'a ()` even though obviously proves nothing. Really the function definition should implicitly be `fn weird(...) -> ... where 'a: 'b`, but doing that would break things because of the way storing functions in variables (or passing them around) actually works. I explain that side of things in part 2: ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-fdu6OcQX5gE.html
@lepidoptera9337
@lepidoptera9337 2 месяца назад
No language can save you from your worst self. ;-)
@ggsap
@ggsap 2 месяца назад
If you are speeding up your voiceover could you uncheck the pitch option? Quite annoying
@agungokill
@agungokill 3 месяца назад
how to get memory faulty in rust : cannot be concidence. other language : shit i didnt know it it would be faulty
@residual-entropy
@residual-entropy 3 месяца назад
python: is it memory safe or not? I don’t know it’s been running for three days and it’s still not done yet
@anwiseru9064
@anwiseru9064 3 месяца назад
you could mono the voiceover (keeping only the left channel signal) after the time stretching so it doesn't make things stereo unless theres an option to make time stretching mono already
@eptic-c
@eptic-c 3 месяца назад
Very nice video, i watched it and i don't even like rust.
@codelinx
@codelinx 3 месяца назад
Same... I've never used rust
@henrycgs
@henrycgs 3 месяца назад
when I saw the code compile I was just.... fuck. oh, fuck. how on earth do you even fix this? is it even possible?
@michawhite7613
@michawhite7613 3 месяца назад
The compiler will need to encode outlived constraints into the types of variables
@henrycgs
@henrycgs 3 месяца назад
@@michawhite7613 yeah, after a bit of thought I imagined something like that. I wonder if it's possible without additional syntax.
@residual-entropy
@residual-entropy 3 месяца назад
Oh boy do I have the part 2 video for you: m.ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-fdu6OcQX5gE.html
@somenerd8139
@somenerd8139 3 месяца назад
why do you speed up your vids? I’d rather just listen to it at normal speed than not understand anything with a higher speed.
@residual-entropy
@residual-entropy 3 месяца назад
I just thought that I was talking a bit too slowly. Not something I’m going to do moving forward.
@hrmny_
@hrmny_ 3 месяца назад
You should invest in a better microphone if you're planning on making more videos Audio quality is often more important than video quality
@residual-entropy
@residual-entropy 3 месяца назад
I’m aware- I was just using my phone as it’s the best I have. I will get a real mic at some point, but I mean that’s a good chunk of change.
@JorgetePanete
@JorgetePanete 3 месяца назад
I don't remember if I wrote this in another video of yours The video/voice is sped up
@residual-entropy
@residual-entropy 3 месяца назад
Yes. Not something I’m going to keep doing.
@tee1532
@tee1532 3 месяца назад
At 0:49 you say "this is an incredibly hard problem to solve". I wish your video explained why! It looks like it's easy to fix the example shown in the video and GH issue. The line: let weird_function: fn(&'static &'static (), &'a T) -> &'b T = weird; seems to obviously require that &'a is at least as long-lived as &'static, because otherwise it would not be compatible with weird's signature. According to weird's signature: fn weird(_witness: &'b &'a (), borrow: &'a T) -> &'b T { It is obvious that the lifetime of weird's second argument must be the same as or longer than the lifetime of weird's first argument. So in weird_function's type let weird_function: fn(&'static &'static (), &'a T) -> &'b T = weird; the second argument &'a T must have a lifetime longer-or-the-same as the first argument which is &'static. So why does the compiler allow calling weird_function with a second argument that has a lifetime shorter than &'static ?
@residual-entropy
@residual-entropy 3 месяца назад
I’m not sure I understand how the `let weird_function: … = weird;` line requires that 'a is at least as long as 'static. All that needs to happen is any `&'static &'static ()` needs to be an `&'b &'a ()` which of course is the case. This is function arguments being contravariant enables: We’re allowed to convert a `fn() -> …` to a `fn() -> …`. In this case `&'b &'a ()` is the general type and `&'static &’static ()` is the specific type. We aren’t trying to set 'a and 'b to 'static or anything, we’re creating a new function that does the same thing with a different type signature. If it helps imagine that I instead do this: ``` fn weird_function(witness: static &'static (), borrow: &'a T) -> &'b T { weird(make_specific(witness), borrow) } fn make_general(witness: &’static &'static ()) -> &'b &'a () { witness } ``` Hopefully that example should clearly be all above board. Contravariance is sort of a shortcut to do the same thing without actually creating a new function. That’s why contravariance is a key part of the trick- the whole `&'b &'a …` thing is normally checked at the call site (in the code above when we call `make_general`. But here we never actually have to call it. In the code above you can see that `weird` and `weird_function` *do* the same thing. So the language is perfectly happy allowing us to convert `weird` to `weird_function`. You don’t need to have a `fn make_general(cs: CatSoul) -> AnimalSoul …` and then call it explicitly. You can just convert a `fn(AnimalSoul) -> …` to a `fn(CatSoul) -> …`. Hopefully that clears it up a bit. As for explaining why fixing it is difficult that’s sort of a difficult thing to do since everyone has their own slightly different idea on how it could be fixed easily. The reason it’s hard is because there isn’t a way to fix it easily, and I video going through all the possible easy fixes that wouldn’t actually work wouldn’t be very interesting. I *might* make a follow-up video explaining one or two not-quite-correct easy fixes and then the sort of ideal way to fix it. But I’m pretty busy both with the next vid and lots of other stuff. There have been a couple of people in the comments seeming to specifically think that you’re somehow substituting 'a and 'b when you don’t. Let me know if I’m misunderstanding you though.
@tee1532
@tee1532 3 месяца назад
​@@residual-entropy I thought the original function signature fn weird(_witness: &'b &'a (), borrow: &'a T) -> &'b T { specifies &'a is at least as long as &'b. I thought you wouldn't be allowed to use contravariance to specify incompatible bounds. E.g. if the signature were fn weird(_witness: B, borrow: A) -> B { I'm pretty sure fn extend(borrow: A) -> B { let weird_function: fn(SuperA, A) -> B = weird; would not be allowed by the compiler. I just don't see the difference between this and writing the same thing with lifetimes instead of types.
@residual-entropy
@residual-entropy 3 месяца назад
@@tee1532 The original signature should specify that exact constraint but currently doesn’t. This is the real problem- the language doesn’t actually have away to associate these kinds of constraints with a function type. Ideally you’d be able to say the type is `for where 'a: 'b fn(&'b &'a (), &’a T) -> &'b T`. But currently putting a where clause there isn’t a language feature that actually exists. That’s the bug and the ideal way to fix it. Hopefully that makes sense. :)
@tee1532
@tee1532 3 месяца назад
@@residual-entropy why is it an ideal fix to require the programmer to type extra words? The compiler should currently be able to infer that constraint anyway
@residual-entropy
@residual-entropy 3 месяца назад
@tee1532 (See comment after this one first, I think this one isn’t actually answering your question) How can it infer the constraint? Are you saying that at the time we use `weird` to a `fn(…) -> …` trait object the compiler should look through the type of `weird` for any of these constraints? That seems like it would work but the problem is we don’t know what 'a and 'b are at that point. The compiler deduces the type of `weird` to be `for fn(&'b1 &'a1 (), &'a1 T) -> &'b1 T`. This is basically just abstracted over any possible lifetimes 'a1 and 'b1 ( doc.rust-lang.org/nomicon/hrtb.html ). So we can’t check it then since we don’t know what 'a1 and 'b1 are and after that the constraint 'a: 'b is nowhere to be found. Unless we somehow store it in the type. Sorry for the confusion. Honestly I’m sort of regretting not explaining the `for` bit in the video but I just realize how important it kind of just seemed like unnecessary having to explain another weird rust feature. But I think it’s clear that’s not the case.
@iliya-malecki
@iliya-malecki 3 месяца назад
i feel like fn(&'b&'a(), &'a T) -> &'b T shouldnt be coercible to fn(&'static&'static (), &'a T) -> &'b T since, while &'static&'static is a valid &'b&'a, it is not a valid &'b&'a in a function that couples the lifetime with some other parameter "borrow: &'a". It implies that "borrow" is also &'static and doesnt check for that, even allowing the second parameter to be &'a T
@iliya-malecki
@iliya-malecki 3 месяца назад
So the real question is why are functions are coercible if every parameter by itself is coercible, if, clearly, a dependency between parameters should be respected?
@residual-entropy
@residual-entropy 3 месяца назад
I made a part 2 video which (I think) explains what you’re struggling with: m.ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-fdu6OcQX5gE.html Hope that helps. :)
Далее
You Should Really Know These Traits in Rust
18:36
Просмотров 10 тыс.
Rust Functions Are Weird (But Be Glad)
19:52
Просмотров 126 тыс.
FUN&SUN | Update 0.29.0 Trailer | Standoff 2
02:32
Просмотров 1,2 млн
Tipuan Jenius dalam Mengasuh Anak & Gadget Cerdas
00:21
Object Oriented Programming is Good | Prime Reacts
31:30
Safe Rust AIN'T EASY!? (*fixing* cve-rs)
11:56
Просмотров 13 тыс.
Constructors Are Broken
18:16
Просмотров 100 тыс.
Async Rust Is A Bad Language | Prime Reacts
28:46
Просмотров 86 тыс.
I'm Coming Around To Go...
21:33
Просмотров 100 тыс.
So You Think You Know Git - FOSDEM 2024
47:00
Просмотров 987 тыс.
Learn Rust with Rustlings 5.2.1 (No C required)
3:07:42
Для фанатов SEGA MEGADRIVE - Anbernic RG ARC
14:23
Неразрушаемый смартфон
1:00
Просмотров 829 тыс.