Hi there,
I'm completely new to Rust and currently working my way through "The Book".
While reading the Chapter on Strings and the invocation of push_str, I got confused about the syntax when invoking a function that takes a string slice as parameter.
Say we have a function fn foo(s: &str) and define a variable let x = "Hello World";.
Are these function calls all equivalent to each other? If so, why?
This is where the "deref coercion" kicks in. It's described in Deref coerctions chapter of The Book. Basically, Rust will strip layers of & from the type, if you passed a "more referenced" type and a "less referenced" type is expected. Like here, when you coerce &&str → &str. (Note that this this coercion won't strip the last &, so eg. no &Foo → Foo, as it's not always possible (eg. when you neither can't Clone nor Copy a Foo)). Deref coercions also works on some "smart pointer" types (which implement Deref trait), so you can also convert &String → &str, &Vec<T> → &[T] or &Rc<T> → &T.
The third example is using a string slice syntax. x[..] desugars to *x.index(..) aka. *x.index(RangeFull). The index returns a &str here, but compiler inserts a *–dereference, so you need to reference it again to come back to str. So foo(&x[..]) → foo(&*x.index(RangeFull)).
I strongly suggest that "The Book" make an annotation here, add the usage of let word = first_word(&my_string); and indicate that this will be covered later in Chapter 15.