2

Consider the following bit of code:

pub trait Trait {
    fn foobar(&self) {
        baz(self)
    }
}

fn baz<T: Trait>(t: &T) {
    println!("asdfadsf");
}

Note that baz is intentionally left outside the trait: it's an implementation detail that shouldn't leak outside the module. The above does not compile and gives the following error:

error[E0277]: the size for values of type `Self` cannot be known at compilation time
 --> src/lib.rs:3:9
  |
3 |         baz(self)
  |         ^^^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `Self`
  = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-sized>
  = help: consider adding a `where Self: std::marker::Sized` bound
note: required by `baz`
 --> src/lib.rs:7:1
  |
7 | fn baz<T: Trait>(t: &T) {
  | ^^^^^^^^^^^^^^^^^^^^^^^

Why does baz care about the size of T? It takes a reference as its parameter; there's no need to know about the size of the referenced thing. Sure, I can stick a + ?Sized to the trait bound on baz, but why is it required, and what is the Rust-y way to deal with this?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Michail
  • 1,843
  • 1
  • 17
  • 21
  • 1
    *I can stick a `+ ?Sized` to the trait bound on `baz`, but why is it required*? `Sized` is a default trait bound for (almost?) all generic types. If it weren't, you would have to write `+ Sized` a lot more often than you have to write `+ ?Sized` today. *and what is the Rust-y way to deal with this?* Adding `+ ?Sized` is pretty Rusty. – trent Sep 21 '18 at 20:39
  • @trentcl that's basically what I'd put in an answer ;-) – Shepmaster Sep 21 '18 at 20:42

0 Answers0