为什么我不能在解构变量后调用方法,但如果我直接访问该字段就可以?
Why can't I call a method after destructuring a variable but I can if I access the field directly?
The following 没有编译:
use std::any::Any;
pub trait CloneBox: Any {
fn clone_box(&self) -> Box<dyn CloneBox>;
}
impl<T> CloneBox for T
where
T: Any + Clone,
{
fn clone_box(&self) -> Box<dyn CloneBox> {
Box::new(self.clone())
}
}
struct Foo(Box<dyn CloneBox>);
impl Clone for Foo {
fn clone(&self) -> Self {
let Foo(b) = self;
Foo(b.clone_box())
}
}
错误信息:
error[E0495]: cannot infer an appropriate lifetime for pattern due to conflicting requirements
--> src/lib.rs:20:17
|
20 | let Foo(b) = self;
| ^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 19:5...
--> src/lib.rs:19:5
|
19 | / fn clone(&self) -> Self {
20 | | let Foo(b) = self;
21 | | Foo(b.clone_box())
22 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:20:17
|
20 | let Foo(b) = self;
| ^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `&std::boxed::Box<dyn CloneBox>` will meet its required lifetime bounds
--> src/lib.rs:21:15
|
21 | Foo(b.clone_box())
|
然而,如果将 clone()
中的代码从 Foo(b.clone_box())
更改为 Foo(self.0.clone_box())
,则编译没有问题。理论上,字段访问应该和模式匹配一样,但是为什么模式匹配会有生命周期问题呢?
在我的真实代码中,数据在枚举中,而不是结构中,因此模式匹配是唯一的选择。
TL;DR:在调用方法之前取消引用值:
Foo((*b).clone_box())
和let Foo(b) = self
,b
的类型是&Box<(dyn CloneBox + 'static)>
。方法调用有效
Foo(<&Box<dyn CloneBox + 'static> as CloneBox>::clone_box(&b))
由于局部引用,这个值不能做成特征对象Box<dyn CloneBox + 'static>
。有趣的是,我相信如果编译器允许的话,这将递归地使用一揽子实现。
使用self.0.clone_box()
,方法调用有效:
Foo(<dyn CloneBox as CloneBox>::clone_box(&**b)
为了明确起见,我们可以将其写成 Foo((&**b).clone_box())
,但由于没有中间实现,Foo((*b).clone_box())
就足够了。
另请参阅:
The following 没有编译:
use std::any::Any;
pub trait CloneBox: Any {
fn clone_box(&self) -> Box<dyn CloneBox>;
}
impl<T> CloneBox for T
where
T: Any + Clone,
{
fn clone_box(&self) -> Box<dyn CloneBox> {
Box::new(self.clone())
}
}
struct Foo(Box<dyn CloneBox>);
impl Clone for Foo {
fn clone(&self) -> Self {
let Foo(b) = self;
Foo(b.clone_box())
}
}
错误信息:
error[E0495]: cannot infer an appropriate lifetime for pattern due to conflicting requirements
--> src/lib.rs:20:17
|
20 | let Foo(b) = self;
| ^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 19:5...
--> src/lib.rs:19:5
|
19 | / fn clone(&self) -> Self {
20 | | let Foo(b) = self;
21 | | Foo(b.clone_box())
22 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:20:17
|
20 | let Foo(b) = self;
| ^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `&std::boxed::Box<dyn CloneBox>` will meet its required lifetime bounds
--> src/lib.rs:21:15
|
21 | Foo(b.clone_box())
|
然而,如果将 clone()
中的代码从 Foo(b.clone_box())
更改为 Foo(self.0.clone_box())
,则编译没有问题。理论上,字段访问应该和模式匹配一样,但是为什么模式匹配会有生命周期问题呢?
在我的真实代码中,数据在枚举中,而不是结构中,因此模式匹配是唯一的选择。
TL;DR:在调用方法之前取消引用值:
Foo((*b).clone_box())
和let Foo(b) = self
,b
的类型是&Box<(dyn CloneBox + 'static)>
。方法调用有效
Foo(<&Box<dyn CloneBox + 'static> as CloneBox>::clone_box(&b))
由于局部引用,这个值不能做成特征对象Box<dyn CloneBox + 'static>
。有趣的是,我相信如果编译器允许的话,这将递归地使用一揽子实现。
使用self.0.clone_box()
,方法调用有效:
Foo(<dyn CloneBox as CloneBox>::clone_box(&**b)
为了明确起见,我们可以将其写成 Foo((&**b).clone_box())
,但由于没有中间实现,Foo((*b).clone_box())
就足够了。
另请参阅: