这个特征定义编译得很好:
trait Works {
fn foo() -> Self;
}
然而,这确实会导致错误:
trait Errors {
fn foo() -> Option<Self>;
}
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> src/lib.rs:6:5
|
6 | fn foo() -> Option<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-the-sized-trait>
= help: consider adding a `where Self: std::marker::Sized` bound
= note: required by `std::option::Option`
随着: Sized
超特质绑定,它有效。
我知道Self
输入特征不会自动绑定为Sized
。我明白Option<Self>
不能返回(通过堆栈),除非它的大小(反过来,需要Self
来确定尺寸)。然而,同样的情况也适用于Self
作为返回类型,对吧?除非调整了大小,否则它也不能存储在堆栈中。
为什么第一个特征定义没有触发该错误?
(这个问题 https://stackoverflow.com/questions/30938499/why-is-the-sized-bound-necessary-in-this-trait是相关的,但它并没有回答我的确切问题——除非我不明白。)
这里发生了两组检查,这就是差异看起来令人困惑的原因。
-
检查函数签名中的每种类型的有效性。Option
本质上需要T: Sized
。不需要的返回类型Sized
很好:
trait Works {
fn foo() -> Box<Self>;
}
The 现有答案 https://stackoverflow.com/a/54465962/155423很好地涵盖了这一点。
-
任何功能与身体还检查所有参数是否Sized
。没有主体的特征函数不应用此检查。
为什么这有用?允许在特征方法中使用未确定大小的类型是允许按值特征对象,一个非常有用的功能。例如,FnOnce
不需要Self
be Sized
:
pub trait FnOnce<Args> {
type Output;
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}
fn call_it(f: Box<dyn FnOnce() -> i32>) -> i32 {
f()
}
fn main() {
println!("{}", call_it(Box::new(|| 42)));
}
非常感谢pnkfelix 和 nikomatsakis 回答了我关于这个主题的问题 https://rust-lang.zulipchat.com/#narrow/stream/144729-wg-traits/topic/questions.20from.20Stack.20Overflow/near/157298199.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)