![](/img/trans.png)
[英]Tell the Rust compiler that the lifetime of a parameter is always identical to a struct's lifetime
[英]Damned if you do, damned if you don't: Rust compiler complains regardless whether there's a lifetime parameter or not
我正在嘗試決定是否應該在我的 impls 中添加生命周期參數,但似乎我處於“如果你這樣做該死,如果你不這樣做該死”的情況,因為無論是否有生命周期參數,編譯器都會抱怨.
pub struct TurtleRef<'a> {
t: &'a BorrowedTurtle<'a>,
}
impl TurtleRef<'_> {
pub fn borrowed_turtle(&self) -> BorrowedTurtle {
*self.t
}
pub fn new(r: Turtle) -> TurtleRef {
TurtleRef{t: &BorrowedTurtle{ t:r}}
}
}
pub struct BorrowedTurtle<'a> {
t: Turtle<'a>,
}
impl<'a> std::ops::Deref for BorrowedTurtle<'_> {
type Target = Turtle<'a>;
fn deref(&self) -> &Self::Target {
&self.t
}
}
impl<'a> std::ops::DerefMut for BorrowedTurtle<'_> {
type Target = Turtle<'a>;
fn deref_mut(&mut self) -> &mut Self::Target {
&self.t
}
}
pub struct Turtle<'a> {
children: Vec<Turtle<'a>>,
}
Turtle 有更多字段,但為了簡單起見,我刪除了它們。 您可以在此處查看代碼片段。 代碼拋出錯誤
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> src/campus.rs:54:6
|
54 | impl<'a> std::ops::Deref for BorrowedTurtle<'_> {
| ^^ unconstrained lifetime parameter
沒問題,我將刪除該參數,因為它會引起如此大驚小怪。 但是刪除它之后,我得到了一大堆新錯誤:
error[E0261]: use of undeclared lifetime name `'a`
--> src/campus.rs:55:26
|
55 | type Target = Turtle<'a>;
| ^^ undeclared lifetime
|
help: consider introducing lifetime `'a` here
|
54 | impl<'a> std::ops::Deref for BorrowedTurtle<'_> {
| ^^^^
help: consider introducing lifetime `'a` here
|
55 | type Target<'a> = Turtle<'a>;
| ^^^^
不管你說什么,我都會提前 go 並將該參數添加到目標。 但是現在我又遇到了另一個錯誤:
error[E0658]: generic associated types are unstable
--> src/campus.rs:55:5
|
55 | type Target<'a> = Turtle<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
因此,無論我做什么,似乎都遇到了重大錯誤。 如何在不從頭開始的情況下停止這些錯誤? 我想保留 impls、structs 和 deref 函數,所以我唯一應該改變的是它們的實現。
另一方面,我得到了錯誤
error[E0437]: type `Target` is not a member of trait `std::ops::DerefMut`
--> src/campus.rs:64:5
|
64 | type Target = Turtle<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `std::ops::DerefMut`
因為 Turtle 沒有實現 DerefMut,實際上 Turtle 也不應該實現 DerefMut。 是否有對 Turtle 的輕微修改導致已經實現 DerefMut 的東西?
這里有幾個問題。 首先:
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> src/campus.rs:54:6
|
54 | impl<'a> std::ops::Deref for BorrowedTurtle<'_> {
| ^^ unconstrained lifetime parameter
您要么使用匿名生命周期,要么不使用。 在這里,你聲明了'a
,所以使用它:
impl<'a> std::ops::Deref for BorrowedTurtle<'a> {
要使用省略的生命周期,您不必聲明它:
impl std::ops::Deref for BorrowedTurtle<'_> {
但是,這里你必須引用Target
中的生命周期,所以你不能省略它。
第二:
error[E0437]: type `Target` is not a member of trait `std::ops::DerefMut`
--> src/lib.rs:28:5
|
28 | type Target = Turtle<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `std::ops::DerefMut`
DerefMut
沒有Target
成員,因為它重用了它的超特性Deref
中的成員。 這是為了確保項目必須Deref
和DerefMut
到相同的Target
:
impl<'a> std::ops::Deref for BorrowedTurtle<'a> {
type Target = Turtle<'a>;
fn deref(&self) -> &Self::Target {
&self.t
}
}
impl std::ops::DerefMut for BorrowedTurtle<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.t
}
}
最后,您現在將收到'a
未使用的錯誤:
error[E0392]: parameter `'a` is never used
--> src/lib.rs:15:27
|
15 | pub struct BorrowedTurtle<'a> {
| ^^ unused parameter
|
= help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
這是因為您有幾個遞歸類型實際上沒有使用生命周期:
// 'a isn't actually used for anything
pub struct Turtle<'a> {
children: Vec<Turtle<'a>>,
}
pub struct BorrowedTurtle<'a> {
t: Turtle<'a>,
}
我將假設出於此答案的目的,您省略了使用'a
其他相關字段,僅此而已!
由於DerefMut
繼承自Deref
,因此您不必指定Target
, pub trait DerefMut: Deref {
在Deref
實現中使用Target
定義。
Deref trait 非常特殊,“普通”用戶不能真正使用它,幾乎只有 std 可以為新類型實現它。
這是因為它借用了自我並返回了“其他”問題的引用,這不是暫時的,std 使用它來控制 rust 生態系統以便能夠做到這一點,例如Vec
實現:
impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
fn deref_mut(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
}
}
如您所見, slice 是一個“胖指針”,因此它只需要一個有效的引用即可,您幾乎只能實現Deref
以返回Target
之類的類型slice
。
另一個例子是PathBuf
:
impl ops::Deref for PathBuf {
type Target = Path;
#[inline]
fn deref(&self) -> &Path {
Path::new(&self.inner)
}
}
這里更清楚Path::new
創建一個胖指針。 因此, Target 不能是其他不能自包含或已存在於您Self
中的東西。
正如文檔所說:
因此,應該只為智能指針實現 Deref 以避免混淆。
我認為您真正想要的是實施Borrow
。 所有這一切......這里有一個工作代碼:
impl<'a> std::ops::Deref for BorrowedTurtle<'a> {
type Target = Turtle<'a>;
fn deref(&self) -> &Self::Target {
&self.t
}
}
impl std::ops::DerefMut for BorrowedTurtle<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.t
}
}
你愛怎么做就怎么做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.