为何Rust在两个相似Trait中对Self大小的报错逻辑不同?
Rust Trait中Sized约束的差异问题
问题代码
trait FromSomeStr { // Rust未在此Trait中报错Self大小未知 fn from_input(input: String) -> Self; } trait FromOtherStr: FromSomeStr { // Rust在此Trait中报错Self大小未知,但在FromSomeStr中未报错 fn from_some_other_str(input: String) -> Self { Self::from_input(input) } }
编译器报错信息
Compiling playground v0.0.1 (/playground) error[E0277]: the size for values of type `Self` cannot be known at compilation time --> src/main.rs:9:46 | 9 | fn from_some_other_str(input: String) -> Self { | ^^^^ doesn't have a size known at compile-time | = note: the return type of a function must have a statically known size help: consider further restricting `Self` | 9 | fn from_some_other_str(input: String) -> Self where Self: Sized { | +++++++++++++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time --> src/main.rs:10:9 | 10 | Self::from_input(input) | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = note: the return type of a function must have a statically known size help: consider further restricting `Self` | 9 | fn from_some_other_str(input: String) -> Self where Self: Sized { | +++++++++++++++++ For more information about this error, try `rustc --explain E0277`. error: could not compile `playground` due to 2 previous errors
疑问
from_input和from_some_other_str方法均返回Self,在结构体实现Trait前无法确定其大小。但Rust仅要求在FromOtherStr中为Self添加Sized约束,却未对FromSomeStr做此要求,请问该行为的原因是什么?
解答
核心原因在于Trait中抽象方法与默认实现方法的编译检查逻辑不同:
对于
FromSomeStr中的from_input:这是一个无默认实现的抽象方法。Rust允许这种写法,因为抽象方法的具体实现由后续的类型提供——当某个类型实现该Trait时,该类型必须是Sized(除非显式声明?Sized),此时返回Self的大小是确定的。编译器会把合法性检查延迟到Trait被具体类型实现的阶段,而非Trait定义阶段。对于
FromOtherStr中的from_some_other_str:这是带有默认实现的方法。默认实现的代码需要能被所有符合Trait约束的类型直接复用,因此编译器在Trait定义阶段就必须确保这段代码是合法的。当默认实现中调用Self::from_input并返回Self时,编译器需要确定Self的大小在编译期可知,否则无法生成通用的执行代码(栈上返回值要求大小静态确定)。因此必须为Self添加Sized约束,或者改为返回Box<Self>这类大小确定的类型。
简单总结:抽象方法的合法性检查延迟到实现阶段,而默认实现的代码必须在Trait定义阶段就满足编译要求,因为它是现成的可复用逻辑。
内容的提问来源于stack exchange,提问作者akhildevelops
相关产品推荐
相关产品推荐

