rust - "Sized is not implemented"是什么意思?

标签 rust

我写了下面的代码:

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> where W: Writer {
    fn handle(&self, &mut W) -> IoResult<()>;
}

impl<W, F> Handler<W> for F
where W: Writer, F: Fn(&mut W) -> IoResult<()> {
    fn handle(&self, w: &mut W) -> IoResult<()> { (*self)(w) }
}

然后在我的终端中使用 rustc:

$ 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());
                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

为什么这个Writer需要实现Sized?在我看来,不需要 Sized。在保持 trait Handler 具有此通用参数的同时我应该做什么?


在 Rust 1.0 中,这段类似的代码会产生同样的问题:

use std::io::{self, Write};

fn main() {
    handle(&mut io::stdout());
}

fn handle(w: &mut Write) -> io::Result<()> {
    handler(w)
}

fn handler<W>(w: &mut W) -> io::Result<()>
where
    W: Write,
{
    writeln!(w, "foo")
}

出现错误:

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`

Rust 的更高版本有错误

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)
   |             ^ doesn't have a size known at compile-time
...
11 | fn handler<W>(w: &mut W) -> io::Result<()>
   |    ------- - required by this bound in `handler`
   |
   = help: the trait `std::marker::Sized` is not implemented for `dyn std::io::Write`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

最佳答案

Sized trait 相当特殊,特殊到在大多数情况下它是类型参数的默认绑定(bind)。它表示在编译时具有已知固定大小的值,例如 u8 (1 字节)或 &u32 (在具有 64 位指针的平台上为 8 个字节)等。这些值是灵活的:它们可以放在堆栈上并移动到堆上,并且通常按值传递,因为编译器知道它在哪里需要多少空间-无论值(value)如何。

未确定大小的类型受到更多限制,并且类型为 Writer 的值大小不一:它抽象地表示一些实现了 Writer 的未指定类型,不知道实际类型是什么。由于不知道实际类型,因此无法知道大小:一些大类型是 Writer s,一些小类型是。 Writer是特征对象的一个​​例子,目前它只能出现在指针后面的已执行代码中。常见示例包括 &Writer , &mut Writer , 或 Box<Writer> .

这解释了为什么 Sized是默认值:它通常是人们想要的。

无论如何,对于您的代码,这是弹出的,因为您正在使用 handleh ,这是一个 Fn(&mut Writer) -> IoResult<()> .如果我们将其与 F: Fn(&mut W) -> IoResult<()> 进行匹配输入 Handle实现是因为我们发现 W = Writer ,也就是说,我们正在尝试使用 handle使用特征对象 &mut Writer , 不是 &mut W对于一些具体类型 W .这是非法的,因为 W trait 和 impl 中的参数默认为 Sized绑定(bind),如果我们用 ?Sized 手动覆盖它然后一切正常:

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) }
}

对于 Rust 1.0 代码:

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")
}

我还写了一个blog post about Sized 和一般特征对象,其中有更多细节。

关于rust - "Sized is not implemented"是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47141543/

相关文章:

generics - 如何从盒装特征对象获取对结构的引用?

rust - 为什么我需要使用 `&` 来触发 Rust 中的 deref 强制转换?

rust - 如何配置 actix-web 以接受来自任何来源的 CORS 请求?

opengl - 如何翻转OpenGL的三角形颜色?

rust - 我怎样才能简洁地组合许多不同类型的 `Result` ?

vector - 我如何从 Rust 中的 Vec 中取出一个项目?

rust - 无需代码重复即可在单项测试中多次 panic

for-loop - 在其 for 循环中访问迭代器

callback - 无法从回调向量调用函数,获取 `expected function, found ` Box<std::ops::FnMut(T) + 'a>`

rust - 使用 if let 时如何指定无法推断的类型?