Rust 什么是;“未实施大小调整”;什么意思?

Rust 什么是;“未实施大小调整”;什么意思?,rust,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>

我编写了以下代码:

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) }
}
为什么需要使用此
编写器来实现
大小调整
?在我看来,不需要
大小的
。在保留
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")
}
Rust的更高版本有此错误

error[E0277]:编译时无法知道'dyn std::io::Write'类型的值的大小
-->src/main.rs:8:13
|
8 |装卸工(w)
|^在编译时没有已知的大小
...
11 | fn处理程序(w:&mut w)->io::Result
|----此绑定在`handler'中需要`
|
=help:trait`std::marker::Sized`未为`dyn std::io::Write'实现`
=注意:要了解更多信息,请访问

首先,请注意,
h
属于实现
Fn(&mut Writer)->IoResult
的类型

h.handle
正在被调用;因此,这取决于
处理程序
实现,其中
W
Writer
——请注意:W是
Writer
,一种未分级的类型。因此,
&mut stdio::stdout()
将被强制转换到
&mut Writer
trait对象。这在理论上是非常好的,但是当回到实现时,就会失败。当涉及到约束时,默认情况下会调整它们的大小,因此它会抱怨您试图为
W
分配的值
Writer
,没有调整大小

这里有两个主要的解决方案:

  • 切换到使用
    h
    上的具体书写器类型,以便处理大小不同的类型:

    use std::io::{IoResult, Writer, stdio, LineBufferedWriter};
    use std::io::stdio::StdWriter;
    
    fn main() {
        let h = |&: w: &mut LineBufferedWriter<StdWriter>| -> 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) }
    }
    

  • 我建议支持一个非大小化的
    W
    ,即使在这种情况下不使用它,也没有理由需要调整大小。

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

    未调整大小的类型受到更多的限制,类型
    Writer
    的值也没有调整大小:它抽象地表示实现
    Writer
    的一些未指定类型,而不知道实际类型是什么。由于实际类型未知,因此无法知道大小:一些大类型是
    Writer
    s,一些小类型是
    Writer
    是trait对象的一个示例,目前它只能出现在指针后面的已执行代码中。常见的示例包括
    &Writer
    &mut Writer
    ,或

    这就解释了为什么默认设置为
    size
    :这通常是一个人想要的

    在任何情况下,对于您的代码,这都会弹出,因为您正在使用
    handle
    h
    ,这是一个
    Fn(&mut Writer)->IoResult
    。如果我们将其与实现
    Handle
    F:Fn(&mut W)->IoResult
    类型匹配,我们会发现
    W=Writer
    ,也就是说,我们试图对trait对象
    &mut Writer
    使用
    Handle
    ,而不是对某些具体类型
    W
    使用
    &mut W
    。这是非法的,因为trait和impl中的
    W
    参数默认具有
    size
    绑定,如果我们手动使用
    ?size
    覆盖它,则一切正常:

    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) }
    }
    
    使用std::io::{IoResult,Writer};
    使用std::io::stdio;
    fn main(){
    设h=|&w:&mut Writer |->IoResult{
    写!(w,“foo”)
    };
    let=h.handle(&mut stdio::stdout());
    }
    特征处理程序,其中W:Writer{
    fn句柄(&self,&mut W)->IoResult;
    }
    F的impl处理程序
    其中W:Writer,F:Fn(&mut W)->IoResult{
    fn句柄(&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")
    }
    
    使用std::io::{self,Write};
    fn main(){
    句柄(&mut io::stdout());
    }
    fn句柄(w:&mut Write)->io::Result{
    处理程序(w)
    }
    fn处理程序(w:&mut w)->io::Result
    哪里
    W:写,
    {
    写!(w,“foo”)
    }
    

    我还写了一篇关于一般对象和特性的文章,其中有一些更详细的内容。

    非常感谢。我确认你的代码工作正常。我的理解是,
    size
    实现是必需的,因为rust运行时需要知道它在调用堆栈上占用了多少字节。所以,我打算使用指针避免未知大小的类型,在本例中是
    &mut
    。。。我还不能理解在我的代码中哪里需要
    size
    。它不是必需的,正如第二组代码工作所演示的,这只是一个默认值问题:编译器默认在该类型参数上设置
    size
    绑定,因为这是编译器对几乎所有类型参数的定义。哦。我得到了它!很抱歉,我没有完全理解您的回答:“impl默认使用
    大小的
    绑定”。再次感谢你,巴普!
    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")
    }