我们可以实现这些特征 core::ops
定义我们类型的运算符的行为。特征本身用注释 #[lang =...]
属性,因此编译器知道哪些特征和运算符属于一起。
例如, Add
原始类型的实现看起来像这样(宏从手动扩展和简化 这里):
impl Add for i32 {
type Output = i32;
fn add(self, other: i32) -> i32 {
self + other
}
}
令我惊讶的是,实现使用了 +
内部运营商,可能是电话 self.add(other)
,导致无限递归。显然,事情并不像这样发生,因为表达式就像 3 + 4
(假设没有不断的折叠)工作完全正常。
现在考虑一下这个天真的实现 Add
特征:
use std::ops::Add;
struct Foo;
impl Add for Foo {
type Output = Foo;
fn add(self, other: Foo) -> Foo {
self + other
}
}
fn main() {
let two_foo = Foo + Foo;
}
编译器警告说 function cannot return without recurring
并在调试模式下运行此程序正确停止 fatal runtime error: stack overflow
。
编译器如何知道如何添加两个数字而不会陷入递归漏洞?