为什么使用 "Self" 作为参数类型会引发生命周期错误?
Why does using "Self" as a parameter type raise a lifetime error?
我目前正在关注 https://raytracing.github.io/books/RayTracingInOneWeekend.html,但我正在用 Rust 实现所有内容。这是我的向量实现的摘录:
type Scalar = f64;
#[derive(Debug, Default, Clone)]
pub struct Vector {
x: Scalar,
y: Scalar,
z: Scalar,
}
impl Vector {
fn new(x: Scalar, y: Scalar, z: Scalar) -> Self {
Self { x, y, z }
}
fn x(&self) -> Scalar {
self.x
}
fn y(&self) -> Scalar {
self.y
}
fn z(&self) -> Scalar {
self.z
}
}
impl std::ops::Mul<&Vector> for &Vector {
type Output = Scalar;
fn mul(self, rhs: Self) -> Self::Output {
self.x() * rhs.x() + self.y() * rhs.y() + self.z() * rhs.z()
}
}
当我尝试编译它时,我收到以下消息:
error[E0308]: method not compatible with trait
--> src/point.rs:33:5
|
33 | fn mul(self, rhs: Self) -> Self::Output {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&point::Vector, &point::Vector) -> _`
found fn pointer `fn(&point::Vector, &point::Vector) -> _`
note: the lifetime `'_` as defined on the impl at 30:20...
--> src/point.rs:30:20
|
30 | impl std::ops::Mul<&Vector> for &Vector {
| ^
note: ...does not necessarily outlive the lifetime `'_` as defined on the impl at 30:20
--> src/point.rs:30:20
|
30 | impl std::ops::Mul<&Vector> for &Vector {
| ^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `raytracing`.
但是,如果我将 mul
函数上的 Self
参数更改为 &Vector
,它编译得很好:
[...]
fn mul(self, rhs: &Vector) -> Self::Output {
[...]
这只是生命周期推断失败的情况吗?如果是这样,为什么会失败,因为编译器似乎已正确推断出所有内容?
因为lifetime elision的规则,报错信息告诉它:
note: the lifetime '_
as defined on the impl at 30:20...
行:
impl std::ops::Mul<&Vector> for &Vector {
解释为:
impl<'a, 'b> std::ops::Mul<&'a Vector> for &'b Vector // Self is &'b Vector
因此生命周期不匹配,因为:
fn mul(self, rhs: Self) -> Self::Output {
是
fn mul(self, rhs: &'b Vector) -> Self::Output {
&'a Vector
!= &'b Vector
所以它无法编译。因为 rhs
应该是 &'a Vector
.
当您使用Self
时:
impl std::ops::Mul<Self> for &Vector {
成为:
impl<'a> std::ops::Mul<&'a Vector> for &'a Vector {
所以在 fn mul(self, rhs: Self) -> Self::Output {
rhs
中会有正确的生命周期 <'a>
如果出现生命周期问题,请尝试明确检查编译器是否出错。
最终代码不应包含任何 Self
关键字以允许不同的生命周期:
impl std::ops::Mul<&Vector> for &Vector {
type Output = Scalar;
fn mul(self, rhs: &Vector) -> Self::Output {
self.x() * rhs.x() + self.y() * rhs.y() + self.z() * rhs.z()
}
}
显式:
impl<'a, 'b> std::ops::Mul<&'a Vector> for &'b Vector {
type Output = Scalar;
fn mul(self, rhs: &'a Vector) -> Self::Output {
self.x() * rhs.x() + self.y() * rhs.y() + self.z() * rhs.z()
}
}
我目前正在关注 https://raytracing.github.io/books/RayTracingInOneWeekend.html,但我正在用 Rust 实现所有内容。这是我的向量实现的摘录:
type Scalar = f64;
#[derive(Debug, Default, Clone)]
pub struct Vector {
x: Scalar,
y: Scalar,
z: Scalar,
}
impl Vector {
fn new(x: Scalar, y: Scalar, z: Scalar) -> Self {
Self { x, y, z }
}
fn x(&self) -> Scalar {
self.x
}
fn y(&self) -> Scalar {
self.y
}
fn z(&self) -> Scalar {
self.z
}
}
impl std::ops::Mul<&Vector> for &Vector {
type Output = Scalar;
fn mul(self, rhs: Self) -> Self::Output {
self.x() * rhs.x() + self.y() * rhs.y() + self.z() * rhs.z()
}
}
当我尝试编译它时,我收到以下消息:
error[E0308]: method not compatible with trait
--> src/point.rs:33:5
|
33 | fn mul(self, rhs: Self) -> Self::Output {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&point::Vector, &point::Vector) -> _`
found fn pointer `fn(&point::Vector, &point::Vector) -> _`
note: the lifetime `'_` as defined on the impl at 30:20...
--> src/point.rs:30:20
|
30 | impl std::ops::Mul<&Vector> for &Vector {
| ^
note: ...does not necessarily outlive the lifetime `'_` as defined on the impl at 30:20
--> src/point.rs:30:20
|
30 | impl std::ops::Mul<&Vector> for &Vector {
| ^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `raytracing`.
但是,如果我将 mul
函数上的 Self
参数更改为 &Vector
,它编译得很好:
[...]
fn mul(self, rhs: &Vector) -> Self::Output {
[...]
这只是生命周期推断失败的情况吗?如果是这样,为什么会失败,因为编译器似乎已正确推断出所有内容?
因为lifetime elision的规则,报错信息告诉它:
note: the lifetime
'_
as defined on the impl at 30:20...
行:
impl std::ops::Mul<&Vector> for &Vector {
解释为:
impl<'a, 'b> std::ops::Mul<&'a Vector> for &'b Vector // Self is &'b Vector
因此生命周期不匹配,因为:
fn mul(self, rhs: Self) -> Self::Output {
是
fn mul(self, rhs: &'b Vector) -> Self::Output {
&'a Vector
!= &'b Vector
所以它无法编译。因为 rhs
应该是 &'a Vector
.
当您使用Self
时:
impl std::ops::Mul<Self> for &Vector {
成为:
impl<'a> std::ops::Mul<&'a Vector> for &'a Vector {
所以在 fn mul(self, rhs: Self) -> Self::Output {
rhs
中会有正确的生命周期 <'a>
如果出现生命周期问题,请尝试明确检查编译器是否出错。
最终代码不应包含任何 Self
关键字以允许不同的生命周期:
impl std::ops::Mul<&Vector> for &Vector {
type Output = Scalar;
fn mul(self, rhs: &Vector) -> Self::Output {
self.x() * rhs.x() + self.y() * rhs.y() + self.z() * rhs.z()
}
}
显式:
impl<'a, 'b> std::ops::Mul<&'a Vector> for &'b Vector {
type Output = Scalar;
fn mul(self, rhs: &'a Vector) -> Self::Output {
self.x() * rhs.x() + self.y() * rhs.y() + self.z() * rhs.z()
}
}