Probably a silly question but I don't have much background on this area.
I've noticed that str isn't ever in the code directly, or as type annotation. Only &str, Box<str>, Arc<str> etc.
So it seems that the reason which I got from the compiler, by doing:
let a = String::from("h");
let b = a.into_boxed_str();
let c = *b;
}
Is that all variables need to be sized (including function arguments etc.)
The basic question is: why do all variables need to be sized? Does it mean as well that one never sees the type [T] (which I guess str is that i.e [u8]) but only arrays which are [T, N]?
In a way, one can still have them unsized on the Heap since Box<str> is allowed, but somehow not elsewhere.
To allocate exactly this much. Stack is limited, after all.
This is in general - that is, it's technically possible to circumvent (otherwise that RFC would not happen in the first place), but in almost all cases no one knows how exactly to do it, AFAIK.
Passing unsized arguments to functions is in principle "easy" to implement because the caller (which must know the size) can just pass a pointer+size to the callee. Returning unsized values would be much harder to implement, because the caller can't know beforehand how much stack space to reserve, and the callee can't reserve stack space "on behalf" of the caller because of LIFO.
One possible implementation strategy would be compiling an unsized-returning function into a coroutine that first yields the size to the caller, which then allocates that amount and passes a pointer to it back to the callee. Another way might be just leaving the callee's stack frame (containing the return value) as is, essentially jumping back to the caller rather than returning, leaving it to the caller to clean up after both itself and the callee. Yet another method could be maintaining a parallel stack only meant for passing unsizeds.
Well… if you have to have C99 compiler then you need a way to circumvent that.
But, on the other hand, MSVC never supported C99 precisely for that reason. C11 relaxed that requirement, it's optional now… and that's why in 2020 MSVC was able, to, finally, update their C support from C89 to something more modern.
let a: str = first_str();
let mut b: str = second_str();
let c: str = third_str();
b = fourth_str();
Variables on the stack don't currently change their addresses when something is assigned to them. But if a, b, c are laid out consecutively in memory, and fourth_str is longer than second_str, there isn't enough space to store the new value there. So it's impossible. One would have to change the rules and allow variables to change their addresses on assignment. Even then, this would leave a hole behind where b used to be, leading to memory fragmentation. Imagine you do this in a loop: it could waste a lot of memory.