patternrustMajor
What does "Sized is not implemented" mean?
Viewed 0 times
implementeddoesmeannotwhatsized
Problem
I wrote the following code:
And then
Why is this
In Rust 1.0, this similar code produces the same problem:
With the error:
Later versions of Rust have the error
--> src/main.rs:8:13
|
8 | handler(w)
|
use std::io::{IoResult, Writer};
use std::io::stdio;
fn main() {
let h = |&: w: &mut Writer| -> IoResult {
writeln!(w, "foo")
};
let _ = h.handle(&mut stdio::stdout());
}
trait Handler where W: Writer {
fn handle(&self, &mut W) -> IoResult;
}
impl Handler for F
where W: Writer, F: Fn(&mut W) -> IoResult {
fn handle(&self, w: &mut W) -> IoResult { (*self)(w) }
}And then
rustc in my terminal:$ rustc writer_handler.rs
writer_handler.rs:8:15: 8:43 error: the trait core::marker::Sized is not implemented for the type std::io::Writer
writer_handler.rs:8 let _ = h.handle(&mut stdio::stdout());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
writer_handler.rs:8:15: 8:43 error: the trait core::marker::Sized is not implemented for the type std::io::Writer
writer_handler.rs:8 let _ = h.handle(&mut stdio::stdout());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
Why is this
Writer required to implement Sized? It appears to me that the Sized is not needed. What I should do while keeping trait Handler to have this generic argument?In Rust 1.0, this similar code produces the same problem:
use std::io::{self, Write};
fn main() {
handle(&mut io::stdout());
}
fn handle(w: &mut Write) -> io::Result {
handler(w)
}
fn handler(w: &mut W) -> io::Result
where
W: Write,
{
writeln!(w, "foo")
}With the error:
error[E0277]: the trait bound std::io::Write: std::marker::Sized is not satisfied
--> src/main.rs:8:5
|
8 | handler(w)
| ^^^^^^^ std::io::Write does not have a constant size known at compile-time
|
= help: the trait std::marker::Sized is not implemented for std::io::Write
= note: required by handler
Later versions of Rust have the error
error[E0277]: the size for values of type dyn std::io::Write` cannot be known at compilation time--> src/main.rs:8:13
|
8 | handler(w)
|
Solution
The
Types that aren't sized are much more restricted, and a value of type
This explains why
In any case, for your code, this is popping up because you're using
And for the Rust 1.0 code:
I also wrote a blog post about
Sized trait is rather special, so special that it is a default bound on type parameters in most situations. It represents values that have a fixed size known at compile time, like u8 (1 byte) or &u32 (8 bytes on a platform with 64-bit pointers) etc. These values are flexible: they can be placed on the stack and moved onto the heap, and generally passed around by-value, as the compiler knows how much space it needs where-ever the value goes.Types that aren't sized are much more restricted, and a value of type
Writer isn't sized: it represents, abstractly, some unspecified type that implements Writer, with no knowledge of what the actual type is. Since the actual type isn't known, the size can't be known: some large types are Writers, some small types are. Writer is one example of a trait object, which at the moment, can only appear in executed code behind a pointer. Common examples include &Writer, &mut Writer, or Box.This explains why
Sized is the default: it is often what one wants.In any case, for your code, this is popping up because you're using
handle with h, which is a Fn(&mut Writer) -> IoResult. If we match this against the F: Fn(&mut W) -> IoResult type that Handle is implemented for we find that W = Writer, that is, we're trying to use handle with the trait object &mut Writer, not a &mut W for some concrete type W. 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:use std::io::{IoResult, Writer};
use std::io::stdio;
fn main() {
let h = |&: w: &mut Writer| -> IoResult {
writeln!(w, "foo")
};
let _ = h.handle(&mut stdio::stdout());
}
trait Handler where W: Writer {
fn handle(&self, &mut W) -> IoResult;
}
impl Handler for F
where W: Writer, F: Fn(&mut W) -> IoResult {
fn handle(&self, w: &mut W) -> IoResult { (*self)(w) }
}And for the Rust 1.0 code:
use std::io::{self, Write};
fn main() {
handle(&mut io::stdout());
}
fn handle(w: &mut Write) -> io::Result {
handler(w)
}
fn handler(w: &mut W) -> io::Result
where
W: Write,
{
writeln!(w, "foo")
}I also wrote a blog post about
Sized and trait objects in general which has a little more detail.Code Snippets
use std::io::{IoResult, Writer};
use std::io::stdio;
fn main() {
let h = |&: w: &mut Writer| -> IoResult<()> {
writeln!(w, "foo")
};
let _ = h.handle(&mut stdio::stdout());
}
trait Handler<W: ?Sized> where W: Writer {
fn handle(&self, &mut W) -> IoResult<()>;
}
impl<W: ?Sized, F> Handler<W> for F
where W: Writer, F: Fn(&mut W) -> IoResult<()> {
fn handle(&self, w: &mut W) -> IoResult<()> { (*self)(w) }
}use std::io::{self, Write};
fn main() {
handle(&mut io::stdout());
}
fn handle(w: &mut Write) -> io::Result<()> {
handler(w)
}
fn handler<W: ?Sized>(w: &mut W) -> io::Result<()>
where
W: Write,
{
writeln!(w, "foo")
}Context
Stack Overflow Q#28044231, score: 54
Revisions (0)
No revisions yet.