【发布时间】:2022-02-23 15:36:32
【问题描述】:
我有两个特征Foo 和Bar:
trait Bar {
fn get_name(&self) -> &str;
}
trait Foo {
type B: Bar + ?Sized;
fn get_bar(&self) -> &Self::B;
}
实际上,我会有许多不同类型的Foos 和Bars,但每个Foo 都具有Bar 类型的相关特征。现在保持简单,SimpleFoo 与SimpleBar 相关联:
struct SimpleBar {
name: String,
}
impl Bar for SimpleBar {
fn get_name(&self) -> &str {
&self.name
}
}
struct SimpleFoo {
bar: Rc<SimpleBar>,
}
impl Foo for SimpleFoo {
type B = SimpleBar;
fn get_bar(&self) -> &SimpleBar {
&self.bar
}
}
在某些地方我可以使用泛型和单态,但在某些地方我需要动态调度,比如这个函数需要dyn Foo,而Bar 是dyn Bar:
fn some_func_that_needs_dyn_foo_returning_a_dyn_bar(foo: &dyn Foo<B = dyn Bar>) {
// do stuff
}
由于SimpleFoo 实现Foo<B = SimpleBar> 而不是Foo<B = dyn Bar> 我不能直接传递它(我希望编译器或派生或其他东西可以在这里做魔法并使这成为可能),所以我有一个包装类对某些特定Foo 的引用,可以获取其特定的Bar 并将其变为dyn Bar:
struct DynamicFooWrapper<'a, F: Foo> {
foo: &'a F,
}
impl<'a, F> Foo for DynamicFooWrapper<'a, F>
where
F: Foo,
<F as Foo>::B: Sized,
{
type B = dyn Bar;
fn get_bar(&self) -> &'a Self::B {
self.foo.get_bar()
}
}
fn main() {
let b = Rc::new(SimpleBar {
name: "Bar101".to_owned(),
});
let f = SimpleFoo { bar: b.clone() };
some_func_that_needs_dyn_foo_returning_a_dyn_bar(&DynamicFooWrapper { foo: &f })
}
对返回生命周期的不满在于包装器的实现:
error[E0310]: the associated type `<F as Foo>::B` may not live long enough
--> src/main.rs:45:9
|
45 | self.foo.get_bar()
| ^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<F as Foo>::B: 'static`...
= note: ...so that the type `<F as Foo>::B` will meet its required lifetime bounds
For more information about this error, try `rustc --explain E0310`.
我不想在这里有任何静态数据。我想将这里返回的&dyn Bar 的生命周期与DynamicFooWrapper 包装的foo 的生命周期联系起来,因为&dyn Bar 的寿命至少与包装的Foo 一样长。例如,在Foo 包装器上调用get_bar() 之后,我什至想销毁Foo 包装器并且只要原始Foo 项目还活着。这应该是可能的,因为这保证了Bar 的生命周期——我只是不确定如何表达这一切。
【问题讨论】:
-
你能发送一些操场代码吗?
-
this 能解决你的问题吗?
-
我不想在这里有任何静态数据 — 阅读链接到 What does the 'static lifetime mean in a trait bound in a Rust future? 和 this TL;DR 的骗子。你确定你理解正确吗?
-
Re:我希望编译器或派生或其他东西可以在这里发挥作用并使这成为可能,这可能通过为特征中的 async fn 所做的工作而成为可能。请参阅 Niko 的系列“Dyn async traits”(最后一个是here)。
-
感谢@Jmb,这行得通!但是这里有生命周期是什么意思:
fn some_func_that_needs_dyn_foo_returning_a_dyn_bar<'a>(_foo: &dyn Foo<B=dyn Bar + 'a>),dyn Bar +'a。我知道编译方式无关紧要,因为所有生命周期都被删除了,但是它“证明”了 rustc 什么?
标签: rust associated-types