Str size at compile time

Hi there,
if i write

let s1: str = "hi";

compiler complains:
the size for values of type str cannot be known at compilation time. OK.
but 'h' + 'i' has a well defined size.
So why compiler is unable to evalute the size of "hi"?
Thx.

It’s a fundamental property of the str type that you can’t ever store one directly in a variable. Instead, it can only exist as part of another type, like &str, Box<str>, or (implicitly) String.

The compiler error message is summarizing why str is designed this way, even though it might not be literally true in all cases. You probably want either:

let s1: &str = "hi";  // If the string won’t be edited

or

let mut s1 = String::from("hi");  // If you need to edit the string later
1 Like

To be clear, the compiler is not trying to evaluate the size of "hi". A variable with type str needs to be able to store any possible value of that type, including strings that are two gigabytes long. Because of this, a variable cannot have the type str.

In this particular case, we should add that "hi" doesn't even have the type str. It has the type &str. That's because your code more or less compiles down to this:

static HI_DATA: [u8; 2] = [b'h', b'i'];
let s1 = std::str::from_utf8_unchecked(&HI_DATA);

The thing to notice is that s1 doesn't actually store the string data. It just has a pointer to an immutable global storing the string data.

(the from_utf8_unchecked call converts reference type from &[u8] to &str)

If you want a variable that actually stores the string data directly, you can do this:

let s1 = [b'h', b'i'];

This gives s1 the array type [u8; 2]. You can get a string slice into that string data using std::str::from_utf8.

11 Likes

Note that the error message is (as you say):

error[E0277]: the size for values of type `str` cannot be known at compilation time

It says, "values of type str". It doesn't refer to the particular value "hi", but to values of str in general.

When you declare a variable s1: str in your code, then the compiler will not know how much space to reserve for it.

Rust doesn't have a type for owned string slices of a fixed size, but it does know fixed sized arrays. So what you could do is this:

const CHARS: [char; 2] = ['h', 'i'];

This doesn't make much sense though, as it won't be an UTF-8 string but an array of 32-bit integers internally.

Nonetheless, you could work with this fixed-size array of chars (but note that this is not what you're supposed to do in Rust normally):

fn main() {
    const CHARS: [char; 2] = ['h', 'i'];
    for c in &CHARS {
        print!("{c}");
    }
    println!("");
}

(Playground)

Output:

hi


Instead, the correct way to do it is this:

fn main() {
    const S1: &'static str = "hi";
    println!("{S1}");
}

(Playground)

Output:

hi


You could also do:

fn main() {
    let s1: &'static str = "hi";
    println!("{s1}");
}

(Playground)


Or shorter:

fn main() {
    let s1 = "hi"; // implicit type: &'static str
    println!("{s1}");
}

(Playground)


Honestly, I'm not sure when it's best to use let and when to use const. It confuses me sometimes. When you use const, you will have to specify the type explicitly and you should use all uppercase letters for the name.

1 Like
  1. If you're not sure you need const, that almost always means you need let.
  2. If in C you'd used #define, that means you need const (or macros).
3 Likes

Even better, you can move out of a byte string literal to achieve the same effect in a slightly more ergonomic way:

let s1 = *b"hi";
2 Likes

A let binding (conceptually at least—the optimiser may cause otherwise) occupies some memory on the stack; whereas a const is not stored anywhere (the compiler essentially replaces every usage with its value).

Prefer a const whenever the value is known at compile-time. You have to use let if the value may not be known until runtime.

1 Like

Thx you all for your answers. All this is really instructive in relation to a somewhat anomalous topic for those who come from certain other languages ​​(me, for example)

See also.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.