Skip to content
← Back to Community
Borrow of moved value in Rust?
Profile icon
h
has Hacker Plan
DynamicSquid

I'm getting this weird error: "Borrow of moved value in Rust"

I looked online but I can't find anything. Does it have to do with the fact that your transferring ownership or something?

Thanks

Answered by fuzzyastrocat [earned 5 cycles]
View Answer
Voters
Profile icon
ishankarmakar
Profile icon
programmeruser
Profile icon
HahaYes
Profile icon
fuzzyastrocat
Profile icon
DynamicSquid
Comments
hotnewtop
Profile icon
fuzzyastrocat

You've just hit rust's biggest annoyance factor: memory safety. See, in Rust, memory is super safe — like, you literally can't get a memory error at runtime. However, this means you get all your memory errors are compile-time, which saves you the pain of runtime debugging but can get super annoying for a newbie rustacean.

So, let's look at what's going on here. In this loop:

for ch in line.chars() { token.push(ch); if token == "s" { tokens.push(Token{ value: token }); token.clear(); } }

On the first iteration where token == "s", the variable token gets moved into the token struct you create (Token { value: token }). It's there now. It's been moved out of the variable "token" and into the Token struct you've just made. So on the next loop where token == "s", it tries to move it out of the token variable again. But oh no, we've already moved it out of the token variable, so there's nothing in there! To fix this, instead of moving the token into the Token struct we can make a copy of the token and put it in that struct. You can do this like so:

for ch in line.chars() { token.push(ch); if token == "s" { tokens.push(Token{ value: token.clone() }); token.clear(); } }

Note the .clone(). Now, this will only work if the thing we are cloning implements the clone method (which std::String does) — if not, add #[derive(Clone)] above the definition of the struct that you're cloning.

Profile icon
Coder100

wait you can't do &token? @fuzzyastrocat

Profile icon
fuzzyastrocat

@Coder100 That's a reference. It will now reference token, and since token is mutable that means it won't have the desired behavior. (You'll have multiple references to the same thing instead of many distinct things)

Profile icon
DynamicSquid

@fuzzyastrocat Ohh.. I see now. thanks!!

Profile icon
DynamicSquid

@fuzzyastrocat and #[derive(Clone)] is similar to inheritance?

Profile icon
fuzzyastrocat

@DynamicSquid Eh, kinda. #[derive(Clone)] is automatic inheritance — it basically auto-defines the .clone method for you, instead of you having to manually implement it.

Profile icon
DynamicSquid

@fuzzyastrocat Oh I see. Is the same true for parameters as well? So if I do line: String will the value be moved into the function?

Profile icon
fuzzyastrocat

@DynamicSquid Yep. Unless you otherwise specify, things will get moved.

How do you otherwise specify? Well, I've shown you the clone method, which is when you need to make several copies of something (as with this case – you need to copy token since you'll be modifying it later). But what if you don't need a copy? In that case, you can use a reference. I won't explain it here in too much detail, but there's some good info on it on the rust site.

Basically, a reference is when you don't need to have a copy of something. For instance, suppose you want to write a function which returns 2 * the length of the string. You don't need a copy for that, so you can use a reference instead:

fn double_length(s: &String) -> usize { // s is a reference to a String 2 * s.len() }

And now, you call it by passing a reference:

double_length(&my_str);
Profile icon
DynamicSquid

@fuzzyastrocat Okay. So just to be clear, I still have to use .clone() even when passing by reference right? And I have to use &mut if I want to change that reference?

Profile icon
fuzzyastrocat

@DynamicSquid No, I updated my comment. The point of a reference is to avoid .clone(). But yes, if you want to change the referenced value you'll need &mut.

Profile icon
DynamicSquid

@fuzzyastrocat Oh, okay, I get it now, thanks!

Profile icon
fuzzyastrocat

@DynamicSquid Great! Ownership in Rust is kinda hard at first, but once you do enough Rust it'll come naturally.

Profile icon
DynamicSquid

Oh @fuzzyastrocat, do you mind if I ask you another question? Sorry if I'm bothering you too much...

Profile icon
fuzzyastrocat

@DynamicSquid No, ask me as many questions as you like!

Profile icon
DynamicSquid

@fuzzyastrocat Okay, so I'm trying to create a vector of vectors, and I have to fill it with values, but I'm not sure how. Here's the repl. I know I can just .push() the 1D vector into the 2D vector, but I need to use a for loop for that since I'm doing some other stuff with it.

But I got a weird error about borrowing as mutable and immutable. Not sure what that means or how I can fix it... Do I have to use .clone()?

Profile icon
fuzzyastrocat

@DynamicSquid Thanks for inviting me to the repl. I'll help there.

Profile icon
DynamicSquid

@fuzzyastrocat Hi! I have another question if you don't mind :)

How do you turn a splice into a vector? Because I have a Vec, and I'm trying to pass it into another function, but I only want part of that Vec to be passed through. So my first though was to turn that Vec into a splice, and turn that splice into a Vec... or is that not the best way?

Profile icon
fuzzyastrocat

@DynamicSquid Nope, it's fine :D

(It's "slice" btw). Easy! Just call .to_vec() on the slice.

Profile icon
fuzzyastrocat

@DynamicSquid Note that using this method requires all the Vec elements to have the Clone trait, ie you can call .clone() on them, because it's creating a new vec. Therefore, it's not the most efficient in some cases — I'd look at the difference between to_vec and into_vec on the rust site.

Profile icon
DynamicSquid

@fuzzyastrocat oh okay, thanks!

Profile icon
DynamicSquid

@fuzzyastrocat Hey, I have another question if that's okay :) So I'm making an AST, and I just realized now that with unary operators, and multiple levels of precedence, it's getting quite complex. Do you think you could help me out?

Profile icon
fuzzyastrocat

@DynamicSquid HOW DARE YOU ASK ME A QUESTION (no, it's fine :D)

Sure! Do you mean me helping you with the code or with the theory?

Profile icon
DynamicSquid

@fuzzyastrocat More of the theory part. Is it okay if I invite you to a repl?

Profile icon
fuzzyastrocat
Profile icon
DynamicSquid
Profile icon
Summit

wait why is everyone learning rust
i should learn rust
but i need to learn node.js first

waaa whichh should i learn first

Profile icon
DynamicSquid

@Summit lol learn what you want first, so nodejs

Profile icon
HahaYes

Rust: Laughs in memory safety

Profile icon
DynamicSquid

@HahaYes Rust is so memory safe it's insane

Profile icon
DynamicSquid

@HahaYes it's basically a super extra safer safe version of C++

Profile icon
DynamicSquid

@HahaYes with the naming conventions of Python... which I find quite weird

Profile icon
HahaYes

@DynamicSquid ikr rust memory safe is like a garbage can that asks you whether or not to put the garbage in i dunno

Profile icon
RayhanADev

Hey @DynamicSquid do you not have hacker?

Profile icon
DynamicSquid

@RayhanADev not anymore

Profile icon
RayhanADev
Profile icon
DynamicSquid

@RayhanADev yeah :( but it shouldn't be to much of a problem since I don't much coding here, and I don't need private repls

Profile icon
fuzzyastrocat

@DynamicSquid I've never had hacker. What does it give you again? I know private repls, but other than that I forget.

Profile icon
RayhanADev

@fuzzyastrocat private repls, more storage, faster speeds. That’s pretty much it I believe.

Profile icon
fuzzyastrocat
Profile icon
RayhanADev

@fuzzyastrocat I got Hacker for a year free and I also got my bot account @HelperFurret hacker too for flex xD.

Profile icon
Coder100

typo? Do tokens.push lol

Profile icon
DynamicSquid

@Coder100 wdym? where?

Profile icon
Coder100
Profile icon
DynamicSquid

@Coder100 no it's supposed to be token. I'm appending a char to a string

Profile icon
fuzzyastrocat

@Coder100 Lol no, @DynamicSquid is right...

Profile icon
Coder100

ah oops, but it got borrowed onto line 16, try referencing it instead @DynamicSquid

Profile icon
Coder100

something like tokens.push(Token{ value: &token }) i believe @DynamicSquid

Profile icon
fuzzyastrocat

@DynamicSquid Don't do what @Coder100 is saying, you'll now have several references to the same token which isn't what you want. (All your Token structs will have the same value by the end of the loop.)

Profile icon
Coder100
Profile icon
Coder100

actually im curious what it does imma test it out @fuzzyastrocat