7

I quote the official documentation:

A reference represents a borrow of some owned value.

Coming from C, Java, Perl and PHP, I see a "reference" as an address (or pointer) to a value. It is possible to declare a variable of type "T" or a reference (or pointer) to a variable of type "T" (using & - or \ in Perl).

However, I am not sure that this representation is totally valid with Rust. Something bothers me.

I always see the "string slice" manipulated as a reference, that is, in its borrowed form (&str).

I have (so far) never seen a variable of type "str".

I tried to declare a variable of type "str"... but the compiler does not let me do that.

QUESTION: can we define a variable of type "str" ?

If it is impossible, then it means that we are facing a type of data that cannot be declared other than as a reference. This seems weird...

Denis Beurive
  • 305
  • 2
  • 10
  • Does this answer your question: https://stackoverflow.com/questions/24158114/what-are-the-differences-between-rusts-string-and-str ? – at54321 Oct 20 '22 at 20:09

2 Answers2

6

No, you can't define a variable of type str. This is because variables are stack-allocated, and for this to be possible, the compiler needs to know at compile time the size of the variable (this is a general rule, not specific to Rust). But str: !Sized, which means the size of a value of type str cannot be known at compile time. For this reason, str must always be allocated elsewhere: on the heap, or in the data segment for example.

But this does not mean that you are forced to "hide" it behind a borrow &, there are other pointers in Rust. For instance, it would be possible to cross a &mut str, a *const str, a *mut str, a Rc<str>, a Box<str>, and the list goes on and on.

jthulhu
  • 7,223
  • 2
  • 16
  • 33
  • It seems to me that, in C, what we call a "type" is necessarily "something" that has a known length (at compile time). But this is not the case in Rust : in Rust a "type" is *NOT* necessarily "something" that has a known length (at compile time). Thus we are not talking about the same "thing" when we use the term "type." The Rust definition of "type" differs from the C one. This can be confusing (because we try to stick to something we already know). – Denis Beurive Oct 21 '22 at 08:48
  • I found this post very interesting : https://stackoverflow.com/questions/24158114/what-are-the-differences-between-rusts-string-and-str – Denis Beurive Oct 21 '22 at 16:56
5

Using unstable feature unsized_locals, it is possible to move a dynamically-sized value into a stack variable:

#![feature(unsized_locals)]

fn main() {
    let x: Box<str> = "abc".into();
    let y: str = *x;
    
    println!("{}", &y);
}

This feature is incomplete — it can only be used on nightly releases of the Rust compiler and may misbehave. It may not ever get into a stable Rust version.

Even then, there are good reasons not to do this: you're allocating an amount of stack memory determined by the input data. That puts you at great risk of a stack overflow if the data happens to be larger than fits on your stack together with everything else using the stack.

Today, you almost never need an unsized local: you can always put the value in a Box (at least, if you aren't programming without a memory allocator). So, the lack of this feature does not really limit what programs you can write. But, in principle, it could exist.

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108