Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move_semantics3: Why can I pass to a function an argument that is immutable and have it be received as a value that is mutable? #631

Closed
gabrivera opened this issue Jan 27, 2021 · 8 comments

Comments

@gabrivera
Copy link

Hi, you could help me learn Rust through Rustlings solving this question on mutability and moving.

So here's the code in question. Notice vec0 is immutable and I'm passing it to fill_vec, which by definition receives mutable vectors.

// move_semantics3.rs
// Make me compile without adding new lines-- just changing existing lines!
// (no lines with multiple semicolons necessary!)
// Execute `rustlings hint move_semantics3` for hints :)

// I AM NOT DONE

fn main() {
    let vec0 = Vec::new();

    let mut vec1 = fill_vec(vec0);

    println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);

    vec1.push(88);

    println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}

fn fill_vec(mut vec: Vec<i32>) -> Vec<i32> {
    vec.push(22);
    vec.push(44);
    vec.push(66);

    vec
}

So v0 changes ownership. It goes from main as an immutable to fill_vec as a mutable. How does this work?

Given the Rustlings hint for this question ("You can [...] add mut in one place that will change an existing binding to be a mutable binding instead of an immutable one"), bindings can vary. Fair enough, but what are they binding to? Is it a bind from a symbol to a pointer?

I'm not sure if I missed something in the Klabnik Nichols book on how to think about this, but if my interpretation is correct, thanks, Rustlings!

@gabrivera gabrivera changed the title move_semantics3: why can I pass an immutable as an argument and receive a mutable as a parameter? move_semantics3: Why can I pass to a function an argument that is immutable and have it be received as a value that is mutable? Jan 27, 2021
@fraterenz
Copy link

fraterenz commented Jan 27, 2021

It is not clear to me neither.

@Michael1015198808
Copy link

To my point of view, passing a variable without & means that you pass the ownership to that function. Since you have the ownership, so you can do nearly whatever you want to do on that variable. Thus, it's legal to make the variable mutable.

@fraterenz
Copy link

But I think the point is that fill_vec expects a mut vector, but instead receives vec0 which is not mutable, hence the confusion.

@Michael1015198808
Copy link

But I think the point is that fill_vec expects a mut vector, but instead receives vec0 which is not mutable, hence the confusion.

Well, if we pass a reference, things will like what you say. But for ownership, things are different.
For example, the following codes are equivalent

let mut var = val; // create a mutable object
let var = val;
let mut var = var; // change make variable mutable

@fraterenz
Copy link

I see, thank you very much!

But I still don't get how can we move val to var:

let val = Vec::<u32>::new();
let mut var = val; // create a mutable object

since var is mut and val is immutable. How does that work?

@tal-zvon
Copy link
Contributor

tal-zvon commented Feb 2, 2021

For example, the following codes are equivalent

let mut var = val; // create a mutable object
let var = val;
let mut var = var; // change make variable mutable

Can someone explain this? This seems insane to me.

From what I understand, the underlying memory in use to store values of variables is never immutable. Every memory address can technically be written to. Immutability is an artificial constraint.

When I say:

let x = 5;

I'm saying that I want a variable in memory with the value 5, and I don't want it changed by any code later on. If I try to change this variable at some point, give me an error. This is me defining the constraint.

If you can later just do:

let mut x = x;

make it mutable, and change it, this seems to defeat the entire purpose of immutable variables. At that point, you might as well just make all variables mutable, because immutability is not guaranteed.

At least with constants, there's a guarantee of immutability. The purpose of a regular immutable variable is unclear.

@tal-zvon
Copy link
Contributor

tal-zvon commented Feb 4, 2021

For those curious, I posted the same question here to reach a wider audience.

@shadows-withal
Copy link
Member

Closing as stale.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants