1

Why does this code fail to compile?

trait TFoo {}

fn foo<T: TFoo>(v: Box<T>) {}

fn bar(v: Box<TFoo>) {
    foo(v);
}

fn main() {}

compilation error:

error[E0277]: the trait bound `TFoo: std::marker::Sized` is not satisfied
 --> src/main.rs:6:5
  |
6 |     foo(v);
  |     ^^^ `TFoo` does not have a constant size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `TFoo`
  = note: required by `foo`

This code compiles if the signature of foo is fn foo(v: Box<TFoo>). Why can Box<T> where T: Trait not be passed as a parameter, but Box<Trait> can be passed?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
chabapok
  • 921
  • 1
  • 8
  • 14
  • Didn't you mean `fn bar(v: Box)`? – ljedrz Nov 06 '17 at 16:47
  • 1
    The other answer doesn't cover the question here, which is why `Box` works as a parameter but `Box` doesn't. – user4815162342 Nov 06 '17 at 19:10
  • with signature `fn foo(v: Box)` this code compiled ok – chabapok Nov 06 '17 at 19:40
  • @user4815162342 I'm not following you. This code is trying to pass a `Box` to a function that accepts a `Box`. This means that `T` must be `TFoo`, which is not sized, but the `T` is `Sized` by default. This **is covered** in the duplicate: *this is popping up because [...] `Fn(&mut Writer) -> IoResult<()>`. If we match this against the `F: Fn(&mut W) -> IoResult<()>` [...] we find that `W = Writer` [...] This is illegal because the `W` parameters in both the trait and the impl are defaulting to have a `Sized` bound, if we manually override it with `?Sized` then everything works fine*. – Shepmaster Nov 06 '17 at 22:00
  • @Shepmaster `Box` is ultimately a pointer, so it may not be obvious why `Box` containing an unsized type is itself unsized. (One could imagine `Box` being pointer-sized for any T, like C++'s `unique_ptr`.). The linked answer does not mention `Box` at all. – user4815162342 Nov 06 '17 at 22:59
  • @user4815162342 OK, I can fix that. – Shepmaster Nov 06 '17 at 23:25
  • @Shepmaster Your other answer still doesn't address why the size of the type is relevant when moving a box. Nor does it need to, because the other question is not specifically about `Box`. Instead of editing the other answer, please reopen this question, so that it can be answered properly. – user4815162342 Nov 07 '17 at 07:23
  • @user4815162342 I disagree — both questions are "why does passing a trait object (`&Trait` / `Box` / `Rc`, etc.) to a function that accepts a generic of the same shape (`&T` / `Box` / `Rc`, etc.) generate a warning about `Sized`". `Box` vs `&` is simply incidental. – Shepmaster Nov 07 '17 at 14:10

0 Answers0