Hacker News new | ask | show | jobs
by tmp538394722 1640 days ago
Just guessing, but speaking from my own experience, the trouble came when interacting with existing APIs, where you can’t choose what to pass around.

Some expect String while others expect &str.

Once you understand why, it’s easy to intuit which one should be used where, but it was a day 1 speed bump for me.

1 comments

If you have a String, passing a &str is free, you just.. put a & before your string. that's because if you expect a &str and pass a &String, the &String auto-derefs to &str. This is called a deref coercion[0]

Like, if you have fn f(s: &str), you can do:

    let x: String = String::from(something);
    f(&x);
You can see this in playground here [1] (click "Run")

To explain: both String and &str is essentially a pointer plus metadata, but &String is a double pointer (a pointer to a pointer). Rust knows how to convert double pointers to pointers, using the Deref trait. This implicit conversion is applied only in a handful of places, and only if it doesn't lead to any ambiguity (if f received a generic parameter it wouldn't work for example).

If you wanted to convert String to &str explictly, you would need to write &*x, like this (see in the playground here [2]):

    let x: String = String::from(something);
    f(&*x);
That's because if x has type String, *x has type str (because String impls Deref<Target = str> [3]) and &*x has type &str. This means that auto-deref changed your &x into &*x automatically.

[0] https://doc.rust-lang.org/book/ch15-02-deref.html#implicit-d...

[1] https://play.rust-lang.org/?version=stable&mode=debug&editio...

[2] https://play.rust-lang.org/?version=stable&mode=debug&editio...*

[3] https://doc.rust-lang.org/alloc/string/struct.String.html#im...