#Issues with unsized types

1 messages · Page 1 of 1 (latest)

rocky blaze
#

Here's my code:

struct Handle<'a, T> {
    name: &'a str,
    object: &'a T
}

pub trait Portable {
    fn port_as(&self, name: &str) -> String;
}

impl dyn Portable {
    pub fn make_handle(&self, name: &str) -> Handle<Self> {
        Handle {name, object: self }
    }
}

Here's the error:
```error[E0277]: the size for values of type (dyn logic::Portable + 'static) cannot be known at compilation time
--> src\logic.rs:13:46
|
13 | pub fn make_handle(&self, name: &str) -> Handle<Self> {
| ^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait Sized is not implemented for (dyn logic::Portable + 'static)
note: required by a bound in Handle
--> src\logic.rs:3:19
|
3 | struct Handle<'a, T> {
| ^ required by this bound in Handle
help: consider relaxing the implicit Sized restriction
|
3 | struct Handle<'a, T: ?Sized> {
| ++++++++


I understand why T could be unsized, but Handle<T> is just two references and is sized, correct?
olive seal
#

You need to specify that unsized is allowed

struct Handle<'a, T: ?Sized> {
#

as the compiler's last help message suggests

rocky blaze
#

It does clear the error, but I guess I am wondering why an error is thrown at all. I don't understand why THESE generics need the unsized marker

winged vine
#

You should also use Box<dyn Portable>

olive seal
winged vine
#
object: Box<T>```
olive seal
#

struct Foo<T> has an implicit T: Sized bound. so does impl<T>

winged vine
olive seal
#

@winged vine OP understands this. Notice that each place the dyn is stored it is behind an &

rocky blaze
#

I do understant that dyns are unsized, but I don't understand why this T needs the unsized marker

olive seal
#

because there is an implicit T: Sized.

#

that is all there is to it

#

there is no deep meaning; it is just a default the language has

#

you need to opt out of the default, and your problem is solved.

rocky blaze
#

Like, other times I make a type, I don't get a compiler error for leaving T: sized

olive seal
#

You only get an error if you in fact try to put an unsized type in the T

#

as you do here with Handle<Self> = Handle<dyn Portable>

rocky blaze
#

OH the dyn portable is going in as T isn't it

olive seal
#

yes

rocky blaze
#

Got it, thank you so much

olive seal
#

if you want to extract the underlying T you need to put that as a method on Portable

rocky blaze
#

I am not used to thinking of dyns as types in their own right

olive seal
#

you can never get the concrete type using impl dyn Trait

#

in fact, impl dyn Trait is rarely useful (but not never)

rocky blaze
#

Hmm. Any better structure I should be using, to put a method on anything that impls Portable?

olive seal
#

in order to do that in general, you have to write a trait and a blanket impl for it

#

this is commonly called an “extension trait”

winged vine
olive seal
#

I don't know what you mean.

#

Guessing:
Sized is important, yes, but the language could have chosen to not provide these implicit bounds and required you to write T: Sized when you want that, and that would work exactly the same.

#

But in most cases, that would be annoying because most generic types and functions do need T: Sized.

winged vine
#

or it doesn't have relation ?

rocky blaze
#

Or, I guess I could put my function in the trait block, right? And just leave a default implementation?

#

I should look at other types that do this

olive seal
olive seal
# winged vine or it doesn't have relation ?

The idea of Sized is important to how Rust is compiled. The fact that Sized is implied when you write generics is not important at all; it's just syntax. And removing or adding a Sized bound never changes the resulting code; it only changes whether your program compiles successfully.

winged vine
#

Thank you so much