以下代码在每晚1.7.0编译时没有警告:
trait FnBox {
fn call_box(self: Box<Self>);
}
impl <F: FnOnce()> FnBox for F {
fn call_box(self: Box<F>) {
(*self)()
}
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
但是当我进行这种轻微修改时,我认为这意味着完全相同的事情,我得到一个关于FnOnce
未经确定而且不能移动的错误.
trait FnBox {
fn call_box(self: Box<Self>);
}
impl FnBox for FnOnce() {
fn call_box(self: Box<FnOnce()>) {
(*self)();
}
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
错误信息:
error[E0161]: cannot move a value of type dyn std::ops::FnOnce(): the size of dyn std::ops::FnOnce() cannot be statically determined
--> src/main.rs:7:9
|
7 | (*self)();
| ^^^^^^^
Run Code Online (Sandbox Code Playgroud)
这两个例子有什么区别,为什么第一个例子没有问题?
实际上,有很大的不同.在第一段代码中:
impl<F: FnOnce()> FnBox for F {
fn call_box(self: Box<F>) {
(*self)()
}
}
Run Code Online (Sandbox Code Playgroud)
声明对于任何F
实现FnOnce
我们实现的类型FnBox
.F
是一种具体类型,并且在每个调用站点call_box()
方法将被单态化.F
每个调用站点的具体类型及其大小都是编译器已知的,因此该定义没有问题.
但是,在第二段代码中:
impl FnBox for FnOnce() {
fn call_box(self: Box<FnOnce()>) {
(*self)();
}
}
Run Code Online (Sandbox Code Playgroud)
声明裸特征对象类型实现FnBox
.但是,这个实现是不合理的:虽然Box<FnOnce()>
是一个正确的,大小适合变量和函数参数的FnOnce()
类型,但它本身不是 - 它是一个简单的特征对象类型而且它是未定义的,也就是说,它的大小是不知道的.编译器.这对您使用此类型可以执行的操作设置了一些限制,其中一个主要限制是您不能按值使用此类型的值.但是,这正是此代码中发生的情况:您尝试取消引用Box<FnOnce()>
以获取FnOnce()
.
以前的按值self
方法意味着特征不是对象安全的,并且因为FnOnce::call_once
按值使用实现实例,所以它不是对象安全的.但是,self
自从RFC 817实现以来,按值方法不会使特征对象不安全.self
但是,根据上述推理,仍然不能在特征对象上调用按值方法.
归档时间: |
|
查看次数: |
138 次 |
最近记录: |