0

I was going through the Rust documentation where I read about slices. As per the page's text, a slice is an immutable reference:

This is also why string literals are immutable; &str is an immutable reference.

I would expect 2 things in below code:

  • yetnewstring = "we"; to give a compile time error
  • Even if I'm wrong about the above, I still expect the output of the last print statement for newstring2 to be westtheSlice.

How does the below code work?

fn main() {
    let mut newstring2: String; //declare new mutable string
    newstring2 = String::from("Hello");    // add a value to it 
    println!("this is new newstring: {}", newstring2); // output = Hello

    let mut yetnewstring = test123(&mut newstring2); // pass a mutable reference of newstring2 , and get back a string literal
    println!("this is yetnewstring :{}", yetnewstring); // output = "te"
    yetnewstring = "we"; // how come this is mutable now ? arent string literals immutable?
    println!("this is the Changed yetnewstring  :{}", yetnewstring); // output = "we"
    println!("this is newstring2 after change of yetnewstring = 'we' : {}" , newstring2); // output  = "testtheSlice"
    // if string literal yetnewstring was reference to a slice of  newstring2 ,
    //then shouldnt above  output have to be :"westtheSlice"
}

fn test123(s: &mut String) -> &str {
     *s = String::from("testtheSlice");  
    &s[0..2]
} 
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 1
    Thanks , the answers in the post are very infromative. So yes, `*s = String::from("testtheSlice");` cahnges :"Hello" to "testtheSlice". But I'm confused about the remaining part of code . How is the `yetnewstring = test123(&mut newstring2);` takings value from `newstring2 ` ? Also if `yetnewstring` is a mutable variable referring to a `&str` type , does it mean it can change the value held by `&str` that its referring to ? And if it is , why dint `newstring2 `'s value change in that case after we updated value of `yetnewstring ` to "we"? – nullPointerException Aug 25 '20 at 13:11
  • 1
    That aside, `&str` is not a string literal. A string literal is `&str` (`&'static str` specifically) but there are lots of ways to create an `&str` besides that, it's just a non-owning reference to string data which lives *somewhere*. – Masklinn Aug 25 '20 at 13:14
  • 1
    " Also if yetnewstring is a mutable variable referring to a &str type , does it mean it can change the value held by &str that its referring to ?" no, you can change what it's referring to to be an other thing, but you can't change the *contents* of what it's referring to. – Masklinn Aug 25 '20 at 13:16
  • 1
    "why dint newstring2 's value change in that case after we updated value of yetnewstring to "we"?" because you just changed what `yetnewstring` points to. `newstring2` independently pointed to the same place, but you didn't (and could not) change the pointee. – Masklinn Aug 25 '20 at 13:18
  • 2
    Think of it this way: Harold and Kumar both have a car. It's the same car, which they share. Kumar gets a new car, Kumar's car is different than it used to be, but it's Kumar which changed, not the car itself, so Harold and their (now exclusive) car is unaffected. – Masklinn Aug 25 '20 at 13:19
  • Thanks for all the answers Masklinn , really helpful – nullPointerException Aug 25 '20 at 13:25

1 Answers1

2

yetnewstring's type is &str, only the binding is mutable. The assignment is valid because you're assigning another &str value to a &str variable, which is perfectly fine.

  • If the bindling is mutable, that means its editing the value of `newstring2 ` under the hood in that case? Then shouldnt the last print statement output "westtheSlice"? – nullPointerException Aug 25 '20 at 12:52
  • 3
    It is not modifying `newstring2`. You are modifying `yetnewstring` to reference a string literal, rather than a portion of `newstring2`. In other words, you are changing what `newstring2` is pointing to, not the value of that. – justinas Aug 25 '20 at 13:14