Is `x: T` inferred to `x: &dyn Trait`?

I have the following code:

use std::any::type_name;

struct A {}
trait Trait {
    fn show(&self) {
        println!("hello")
    }
}
impl Trait for A {}
impl Trait for &A {}
impl Trait for &dyn Trait {}

// See the question below.
fn doit<T: Trait + ?Sized>(x: T) {
    println!("T == {}", type_name::<T>());
    x.show()
}

fn main() {
    let a: Box<dyn Trait> = Box::new(A {});
    doit(a.as_ref());
}

To what type does T get inferred? If it is &dyn T which I expect, then why is it not Sized, since I have then x: &dyn Trait which is for sure Sized?

error[E0277]: the size for values of type `T` cannot be known at compilation time
   |
17 | fn doit<T: I + ?Sized>(x: T) {
   |         -              ^ doesn't have a size known at compile-time
   |         |
   |         this type parameter needs to be `Sized`
   |
   = help: unsized fn params are gated as an unstable feature
help: consider removing the `?Sized` bound to make the type parameter `Sized`
   |
17 - fn doit<T: I + ?Sized>(x: T) {
17 + fn doit<T: I>(x: T) {
   |
help: function arguments must have a statically known size, borrowed types always have a known size
   |
17 | fn doit<T: I + ?Sized>(x: &T) {
   |                           +

Type inference has nothing to do with your error. You can never create a function that takes an unsized T as a parameter directly, without any sort of indirection, like & or Box. The size of all function parameters (and the return type as well) must be known at compile time. Removing the ?Sized from T will make doit compile.

3 Likes

You say takes an unsized T as parameter, that is the x: T above.
I thought my doit function will check the ?Sized := can be Sized or unsized when it matched the T -> In my case T is &dyn Trait and that makes some confusion. So when are the bounds checked?

&dyn Trait is sized because it's a reference. When you write T: ?Sized you're allowing the substitution of an unsized type directly; that is, we may have T = dyn Trait, so the signature becomes:

fn doit(x: dyn Trait) {...}

which is accepting an unsized value directly, without any reference or any other container, which is not something that is currently permitted. So, your function definition is invalid by itself — the call site doesn't matter.

But if your intent is to be able to pass &dyn Trait, not dyn Trait, then you don't need the ?Sized. Remove it and the program will compile.

2 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.