How to fight Rust's borrow checker... and win.

Поделиться
HTML-код
  • Опубликовано: 26 янв 2025

Комментарии • 110

  • @letsgetrusty
    @letsgetrusty  Год назад +4

    📝Get your *FREE Rust cheat sheet* :
    letsgetrusty.com/cheatsheet

  • @discreaminant
    @discreaminant Год назад +73

    “ref mut” binding is unreasonably effective to fight the borrow checker

    • @Originalimoc
      @Originalimoc Год назад +5

      Because it does not take ownership when you pattern match it, but fun enough pattern matching itself consider borrowed T, &T as a separate type than T. So it's like borrow checker not being there if the code is not multithreaded.

  • @Dev-Siri
    @Dev-Siri Год назад +33

    as someone who has been fighting the borrow checker for a week straight, I really needed this

  • @InfiniteCoder01
    @InfiniteCoder01 Год назад +35

    When you rust, each time you borrow or partial move, you run a wire, from the place where you borrow/move, to the place where you last use it. The longer the wire, the weaker it is, it hangs lower and lower. The weaker the wire, the more borrow checker will try to break it. Especially, where there is more than one such wire. To protect yourself from this behaviour, you either run short strong cables, isolate cables with Rc and Arc, or use wireless connection, by storing (for example) an index into a vector, or using just a field of a struct every time instead of borrowing it. I don't speak English natively, sorry for any mistakes. You can correct me in the replies section :)

    • @djangofakkeldij
      @djangofakkeldij Год назад +3

      Although technically not very correct; this is a very, very good analogy on how to deal with the borrowchecker :) [IMO]

    • @lufenmartofilia5804
      @lufenmartofilia5804 Год назад

      ​@@djangofakkeldijagreed

    • @kratosgodofwar777
      @kratosgodofwar777 9 месяцев назад +1

      This is sound advice for all kinds of programming

  • @nice_sprite5285
    @nice_sprite5285 Год назад +18

    Cool copilot ad. How much did they pay u for that

  • @mk72v2oq
    @mk72v2oq Год назад +24

    Yeah, that's what I say every time. If you struggle with the borrow checker in one particular place, just slap Rc/Arc there. You can always deal with it later, when you'll become more proficient. And overhead will be negligible most of the time.
    Of course it is better to properly understand the borrow checker, but it is not a critical necessity.

  • @cken27
    @cken27 Год назад +36

    The biggest takeaway is avoiding battle. Even though I don't know enough rust, the code in 6:47 looks ugly, but it is right to start simple. I usually have a strong urge to write 'clean' code. It would take so much time just to validate the core logic, and all the cleanliness is wasted. I need to resist the temptation of premature optimisation. Focus on MVP, then refactoring and optimisation.

    • @lufenmartofilia5804
      @lufenmartofilia5804 Год назад +1

      Yeah I have this same issue, where if I don't make it clean or optimize fast enough, the spagetti mess will come to quick. I guess it's about finding balance

    • @futotta-neko
      @futotta-neko 9 месяцев назад +1

      Ahhh, another soul who shares my pain

    • @golangismyjam
      @golangismyjam 3 месяца назад

      This is why I learnt go, I could write very clean simple code easily, unfortunately garbage collection is getting in my way at this point so here I am attempting to tackle rust again. Honestly the syntax looks ugly and unintuitive to me but hopefully I can overcome it.

  • @SebastianHasch
    @SebastianHasch Год назад +2

    I have tried rust once and failed miserably. After bbout a week of pain with the compiler I've decided to just let it go but I'm thinking about giving it a try again. Your videos (and the whole rust community, obviously) make it seem not that difficult and I just wanted to say thank you for what you have gifted us with your videos! Hope you're doing well ;)

  • @panjak323
    @panjak323 11 месяцев назад +5

    Switch to C. You cannot fight something that just isn't there.

    • @Heater-v1.0.0
      @Heater-v1.0.0 10 месяцев назад

      True that. Problem is that having no borrow checker C is free to fight you in all kind of devious ways. At least C does not delude you about that so much. C++ is much more devious

    • @panjak323
      @panjak323 10 месяцев назад +1

      @@Heater-v1.0.0 C does exactly what you tell it to do, and not the other way around.

    • @Heater-v1.0.0
      @Heater-v1.0.0 10 месяцев назад +1

      @@panjak323 Indeed it does. And that is exactly the problem. More often than we care to admit what we tell C to do is not what we intended to to tell it to do. Due to some silly mistake or other.
      For example this week I sent too much time trying to find out why my C code which worked on my PC and worked on my ARM based McBook did not work on an embedded ARM system running Linux. Turned out I had made an error which caused some malloced memory to not be properly initialised.
      Rust would never have allowed that silly mistake in the first place. A lot of time would have been saved.
      Don't get me wrong, I'm still happy to use C and appreciate it very much for what it is. But I do also appreciate the advantages that Rust gives. I even more appreciate that the Rust version of the code I was talking about is faster!
      It is wrong to imply that Rust tells anyone what to do. It clearly does not.

  • @taylankammer
    @taylankammer Год назад +3

    At around 3:10 it would have been great to have an example of how the code can break if `set_id()` does something with `posts`. As a Rust noob, it's not self-evident to me, and I'm struggling to come up with an example, due to my limited understanding of Rust...

    • @SophieJMore
      @SophieJMore Год назад +4

      That essentially leads to 2 mutable references to the same memory, that's undefined behavior in Rust.
      So, for an example of how 2 mutable references can break code, imagine you took a mutable reference to posts inside of main and then set the first element to String::from("Hello").
      You then call set_id(), which maliciously sets the first element of posts to String::from("Goodbye").
      Then you attempt to print the first element of posts.
      What you might expect is it printing "Goodbye".
      But, not only, this might be confusing, the compiler also assumes that there is at most only one mutable reference to any value at any given time, and it uses it to elide reads.
      So, at the end, in a release build, the compiler might reason that, since we've just set the first element to "Hello" and no other mutable reference to posts exists (incorrect in this case), then we don't really need to read the first element, we know what it is already, so it would print "Hello".

    • @taylankammer
      @taylankammer Год назад +1

      @@SophieJMore Thanks for the example. Is there a situation in which it could lead to a segfault, too? (If the compiler didn't forbid the whole situation.) For example, could `set_id()` do something that amounts to (in C terms) calling `free()` on `posts` or an element of `posts`? I guess it could set `posts` to a completely new Vector, thus having the old Vector deallocated, while the code in main still holds a reference to the old Vector; is that plausible?

    • @InfiniteCoder01
      @InfiniteCoder01 Год назад +3

      @@SophieJMore The actual problem with this code is that posts are not borrowed, but moved. I don't know, how moving really works, but if it actually MOVES, then posts in the struct should be an invalid memory (For Vec it's especially dangerous, because the Vec itself just stores a pointer to data and length, so if you try to mutate the data that invalidated pointer points to, you'll get a segfault)

  • @ZacharyHubbellCodes
    @ZacharyHubbellCodes Год назад +2

    Always happy to see more Rust content from Bogden!

  • @itsmenewbie03
    @itsmenewbie03 Год назад +1

    Hello, seeing the screenshot in 7:20, it says "33K panonood", are you from PH bro?

  • @yuriihonchar9336
    @yuriihonchar9336 Год назад +5

    Great video. You are really trying hard to help people to suffer less!

  • @JavierHarford
    @JavierHarford Год назад +1

    A man of culture, I too love Berkeley mono

  • @AbelShields
    @AbelShields Год назад +1

    5:51 isn't the solution provided incorrect? I mean sure, it technically ensures the data outlives the spawned task, but iirc that's not accepted by the borrow checker.

  • @DJenriqez
    @DJenriqez Год назад +3

    Yeah, my code is fine, but when working with external libraries real fight begins,... but anyway you are kind of optimistic, usually I don't get a lot of help from AI in things of rust (but tried only ChatGPT and bard, never tried copilot)

    • @kevinmcfarlane2752
      @kevinmcfarlane2752 Год назад

      I’ve actually used AI quite a bit now and it has definitely helped me learn and improve my code. I recommend Phind, as it specialises in dev and tech stuff and provides good links and you get some free access to GPT-4. Also Perplexity. Both provide links as well.
      A free alternative to Copilot is Codeium, which is cross-IDE. I used it on my Rust a couple of days ago and learnt something.

  • @Ansatz66
    @Ansatz66 Год назад +6

    The biggest trick to win against the borrow checker is to avoid borrowing things. There is no borrow checker if there are no borrows. If you want a long-lived pointer, make it an Rc RefCell. It is so easy. In Rust as in life, only borrow things when you plan to give them back promptly.

    • @somebodyelse9130
      @somebodyelse9130 Год назад +1

      Oftentimes, it will make more sense and be more efficient to store a reference rather than a copy, even if a copy is still possible.
      For example, if you're writing a parser, it would make more sense for a "struct parser" to store a reference to the input string rather than to make a copy of it.

    • @Ansatz66
      @Ansatz66 Год назад +3

      @@somebodyelse9130 : You make it sound like our only choices are to either borrow or copy. The whole point of Rc is that it allows us to have pointers that are not borrows, and no one suggests that we should make copies.

  • @getakanda
    @getakanda 2 месяца назад

    As a C++ developer, seeing this made me feel like my wings are cut off

  • @maxwebstudio
    @maxwebstudio Год назад +2

    Rust is like a sweet pain.

  • @BenjaminWheeler0510
    @BenjaminWheeler0510 Год назад +1

    it bugs me that "advanced data structures" like a linked list are so difficult when many problems map to link-based data structures intuitively :( what's the general solution here? Let's say I want to use a tree, or a graph, or a linked list.

    • @adrianbool4568
      @adrianbool4568 Год назад +1

      Using the Rc reference counter to manage the connections between structs. (Or Arc if your appliacation is multithreaded.)

  • @fg786
    @fg786 Месяц назад

    Is it fair to say that if you fight the borrow checker you will create bugs in C and C++ that you don't even think about or is programming in Rust just "different"?
    My experience writing small python scripts at work is that I always make assumptions about how anything works in my code that aren't justified and therefore create edge cases that bite me in the ass at some point while the script did fine for weeks.

  • @sharperguy
    @sharperguy Год назад +1

    Is it bad that I use Arc just to avoid having to sprinkle lifetime generics all over my struct? I'd rather have struct Object { config: Arc } than struct Object { config: &'a ObjectConfig }

    • @nullbeyondo
      @nullbeyondo 4 месяца назад

      Arc is extremely inefficient, especially when used in multiple loop on multiple threads in a performance-critical application. I'd rather have a direct desynchronized immutable access across threads than the overhead atomic operations introduce; at least desynchronization is not a concern for what I was implementing, but I just do hate how Rust forces any shared data between threads to be atomic that I have to resort to unsafe Rust or creating my own wrapper on top of it.

  • @whoami83884
    @whoami83884 5 месяцев назад

    Linked lists are an advanced data structure?

  • @MichaFita
    @MichaFita Год назад +4

    Fighting your friend is showing bad attitude.
    The whole rethoric of "fighting" is plain wrong. This is sending wrong signal to all unexperienced apprentices of Rust.

  • @MrHirenP
    @MrHirenP Год назад +6

    I don’t get the Starbucks drink = basic reference. someone explain thanks.

    • @PranshuTheGamer
      @PranshuTheGamer Год назад +2

      people at starbucks miswrite names

    • @SkegAudio
      @SkegAudio Год назад +5

      Because basic girls order Starbucks 😂

    • @ernesto906
      @ernesto906 Год назад +1

      Me neither but a soy latte maga hat drinker is a funny Paradox 😂

    • @rurunosep
      @rurunosep Год назад +1

      "Basic" is slang to describe someone (usually a girl) that just likes and does mainstream things. Think of a blonde, white girl that drinks Starbucks and listens to Taylor Swift, just like all her friends and tens of thousands of other girls, for example.

    • @bobbobertson9325
      @bobbobertson9325 Год назад

      ​@ernesto906 yes we exist, yes we drink soy lattes. TMYK 🇺🇲☕️

  • @hakanaki
    @hakanaki 5 месяцев назад

    what extension are you using to show error inline on VS Code?

  • @codeman99-dev
    @codeman99-dev Год назад +2

    Again, Borrowing rule #1 is poorly stated.
    When using a mutable reference, all operations with that reference must be completed before the next reference is created.

  • @bryandata6658
    @bryandata6658 11 месяцев назад

    Thanks - good advice for fighting the BC.

  • @jaymartinez311
    @jaymartinez311 Год назад

    is using to_owned or to_string everywhere good or bad? Yes i’m lost 😂 i’m thinking i’m making clones everywhere. So idk in terms for backend development it’s bad. I’ve never used clone but i guess im cloning stuff anyway with the functions i mentioned right?

  • @bend.n
    @bend.n 9 месяцев назад

    borrowck checking functions wont increase comptime-- what it will add is a semver hazard, as all the information of a function isnt in its signature.

  • @Christobanistan
    @Christobanistan 9 месяцев назад +1

    Now I know why Rust is so loved. It's Stockholm Syndrome.

  • @Sylfa
    @Sylfa Год назад

    Anyone else distracted by the "fight scene" in the background at 3:28?
    He throws his only spear, then doesn't raise his shield, and the other one jumps making them unable to change their trajectory. It's just bad choreography on both sides…

  • @linkernick5379
    @linkernick5379 Год назад +3

    This is SPARUSTA!
    (Mighty kick the compiler error out of here...)
    😅

    • @voidwalker7774
      @voidwalker7774 Год назад +1

      Long live the Kingdom. Long live the king Ferris !!!

  • @knnmran
    @knnmran Год назад +2

    i think people have exaggerated the borrow checker. in the real life you hardly encounter it.

    • @knnmran
      @knnmran Год назад +1

      at least in my real life 😅

    • @gralha_
      @gralha_ Год назад +1

      That depends a lot on the kind of program you're making. I hit the borrow checker almost every day, but it's usually not a problem to just go around it by cloning or breaking a large struct into smaller parts

  • @TheRealMangoDev
    @TheRealMangoDev Год назад

    is there an owned type for Chars?

    • @sproccoli
      @sproccoli 11 месяцев назад

      individual chars are owned unless you borrow them.

    • @TheRealMangoDev
      @TheRealMangoDev 11 месяцев назад

      @@sproccoli … are they?

    • @sproccoli
      @sproccoli 11 месяцев назад

      @@TheRealMangoDev yes. they just implement copy , so they are cloned rather than moved when you assign them without a borrow. each copy still has a lifetime and can be borrowed\moved. the defaults are just different. you really cannot have an 'unowned' type.

  • @sunhsiang6644
    @sunhsiang6644 9 месяцев назад

    ChatGPT: Let me battle with rust compiler

  • @TheSkyGamez
    @TheSkyGamez Год назад +2

    6:44 ???

    • @xshady2967
      @xshady2967 Год назад

      3. Avoid Battle

    • @shellord
      @shellord Год назад

      Avoid Rust

    • @TheSkyGamez
      @TheSkyGamez Год назад

      @@xshady2967 for me error handling falls under making it work

    • @sadramohh
      @sadramohh Год назад +2

      Yeah the third point really sounds odd.
      I know where he comes from, but the way he put it, you get the impression "to avoid having ha hard time using rust, just ignore the difficult parts" which is basically just ignoring the issue.
      I also have a small gut feeling he might have deliberately made the third point sound a little controversial so people correct him in the comments ;)

  • @erlangparasu6339
    @erlangparasu6339 Год назад

    Great explanation, Thanks!

  • @coolcodingcat
    @coolcodingcat 5 месяцев назад

    Im already a pro at managing memory in C++. Why would I want to struggle with fighting with this borrow checker in this stupid rusty rust?

    • @carmen_13
      @carmen_13 4 месяца назад

      translation: i've only written 200 liner toy code.

    • @coolcodingcat
      @coolcodingcat 4 месяца назад

      @@carmen_13 dude. I've wtitten C++ code thats 1000s of lines long. Like up to 12,000 lines long, by myself.
      You bozo.

    • @coolcodingcat
      @coolcodingcat 4 месяца назад

      @@carmen_13 what the hell is wrong with you? Why the hell would you come on here and say that to me? Just to be d bag? Obviously that is why. Dude, the longest C++ coded was 12,000 lines of C++, that I coded entirely myself. I got another one that is C++ with cuda in C++ that communicates with javascript code via zaphoyd websocket library from github. Its about 5000 lines so far. Probably half of which is C++. All of which I wrote myself.

    • @coolcodingcat
      @coolcodingcat 4 месяца назад

      @@carmen_13 everytime I reply to you, it dissapears after a minute. The longest C++ code Ive written was about 12,000 lines long. And I wrote it, entirely myself.

    • @coolcodingcat
      @coolcodingcat 4 месяца назад

      @@carmen_13 Hopefully, this comment doesn't disappear after 30 seconds.
      The longest C++ project I have ever written was about 12,000 lines for the blackberry, that I was the sole developer for.
      See my other comment on here as well.

  • @kimdicentalevankim7023
    @kimdicentalevankim7023 Год назад

    Fantastic video!

  • @poketopa1234
    @poketopa1234 10 месяцев назад

    ngl this video really doesn't explain any rust concepts, just workarounds

  • @sunumi
    @sunumi Год назад

    fun video i liked it thank you

  • @nevokrien95
    @nevokrien95 Год назад

    Is a linked list hard to make or hard to use?
    Like ik from playing around in c whenever u think "hey a linked list can be nice and fast here" u r usually wrong.
    U also usually screw urself over with how annoying it is to work with a data structure that doesn't let u just go to index

    • @Turalcar
      @Turalcar 11 месяцев назад

      Hard to make. And yes, almost always pointless

  • @senya1296
    @senya1296 Год назад

    Fight me until I death 💀

  • @kuyajj68
    @kuyajj68 Год назад +2

    I don't get it why people is freaking out about th3 borrow checker when the docs clearly explains about it😂

  • @AEStolfo
    @AEStolfo Год назад

    ty!

  • @Christobanistan
    @Christobanistan 9 месяцев назад

    5: reread the Rust Book.
    6: ask someone else
    Also, I hear this suggestion to change data structures all the time, and I think it's bad advice. Honestly, if you're changing your algorithm to avoid language issues, you're using the wrong language.

    • @ysxbel
      @ysxbel 9 месяцев назад

      90% of the time that's your language telling you that your data structure was bad to begin with.

  • @surajraika7821
    @surajraika7821 Год назад

    I came here for thumbnail only.
    but still not participate in advent of code using best rust practices
    it will be great

  • @DinnelChan
    @DinnelChan Год назад

    TYSM!

  •  Год назад +2

    🤗

  • @susabara
    @susabara Год назад +1

    at 1:17,why do you use a neo fascist neo feudal symbol to signify conservative?
    border patrol or immigration officer would be less loaded.

    • @hdbrot
      @hdbrot 3 месяца назад

      No, this is less loaded as it is more abstract. Calling the symbol of Trump who runs for the conservative (!) party of the US, neo-fascist is a bit crazy. The fact that fascists support Trump is not simply because the party itself is fascist but since there are only two relevant options because of a flawed system.

  • @kratosgodofwar777
    @kratosgodofwar777 9 месяцев назад

    "Idiomatic Rust" eh?
    Well not to brag or anything but I am much of an idiot myself, a dumb*ss some might say 😎

  • @o_q
    @o_q 5 месяцев назад +2

    step one: don't use rust

  • @christiankoch4627
    @christiankoch4627 Год назад +1

    This language is so dump

  • @Originalimoc
    @Originalimoc Год назад

    Oh macro😅

  • @captainfordo1
    @captainfordo1 Год назад

    I really struggle to understand the appeal of Rust

  • @elorrambasdo5233
    @elorrambasdo5233 Год назад +2

    MAGA 🤧🤧🤧

  • @raidensama1511
    @raidensama1511 Год назад +2

    +1 for MAGA