What is DST, how can we identify a type is DST or not?

fn main() {
    call_me("hello"); //This will not work
    call_me1("hello"); // This will work

}

fn call_me<T>(input: &T){
    
}

fn call_me1(input: &str){
    
}

The error is call_me("hello"); //This will not work
| ------- ^^^^^^^ doesn't have a size known at compile-time

You can search Google or the documentation directly for "dynamically-sized type". Here's the second hit.

To determine whether something is a DST: a type is sized unless it can be, so DSTs are:

  • either it's one of the built-in DSTs: slices, string slices, or trait objects
  • or it's a user-defined type that transitively contains a DST.
2 Likes

This is the definition i got from your link " A type with a size that is known only at run-time is called a dynamically sized type (DST )"

But here , i'm passing "hello" string literal, its size is known at compile time, then how can it be DST

call_me("hello");

Yes, and no.

The compiler knows that "hello" is five bytes long. However, there is no such thing as a sized string type in Rust. That is, the compiler has no way to encode this "five bytes" into a type. Note that &str doesn't say anything about the length.

Aside: arrays don't have this problem. You have sized types like [u8; 5] along with the dynamically sized [u8]. str doesn't have corresponding sized types.

The compiler is not complaining that a string doesn't have a length, it's complaining that the type itself doesn't have a length. For example, the compiler couldn't define a local variable of type str because... how much space would it reserve? It doesn't (and can't) know.

It's fine to have a reference to such types (like &str or Box<str>), but you can't ever have values of that type. By default, generics assume you want "sized" types (since that's overwhelmingly the case). If you want to also allow unsized types, you'd use T: ?Sized.

2 Likes

Just because you can see that the value has 5 bytes doesn't mean that the type contains that information.

To illustrate further: there is a function to obtain the size of a type, std::mem::size_of. If you call size_of::<i32>() it will return 4. But there is no correct answer to size_of::<str>() because each instance of str has its own particular size. That's what “dynamically sized” means.

3 Likes

The compiler sets the generic type T to str because it try to resolve &T == &str since "hello" is a &str and input is &T.

Implicitly all generic types have a Sized bound. You can remove this constraint with ?Sized.

fn main() {
    call_me("hello"); // This will work
}

fn call_me<T: ?Sized>(input: &T){
    
}
5 Likes

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.