作为更大系统的一部分,我有一组可以回调的强类型函数.尽管由于该系统的动态特性,提供给这些函数的实际参数存储为Rc<dyn Any>
.为了使API保持尽可能强的类型,函数参数都是运行时可转换的From<&'a dyn Any>
.这些函数参数的生存期限制为'a
(它们可以被视为视图,或者只是公开对dyn Any
的底层实例的引用).
当用户注册一个新函数时,会自动为它们添加一个执行从Rc<dyn Any>
到强类型参数转换的闭包.代码可以简化为以下内容:
use std::{any::Any, rc::Rc};
struct View<'a, T> {
view: &'a [T],
}
struct Foo {
bar: String,
}
impl<'a, T: 'static> From<&'a dyn Any> for View<'a, T> {
fn from(value: &'a dyn Any) -> Self {
Self {
view: value.downcast_ref::<Vec<T>>().unwrap(),
}
}
}
impl<'a> From<&'a dyn Any> for &'a Foo {
fn from(value: &'a dyn Any) -> Self {
value.downcast_ref().unwrap()
}
}
fn print_content(view: View<i32>, foo: &Foo) {
println!("view: {:?}", view.view);
println!("foo: {}", foo.bar);
}
fn create_function() -> Box<dyn Fn(&[Rc<dyn Any>])> {
Box::new(|args: &[Rc<dyn Any>]| print_content(args[0].as_ref().into(), args[1].as_ref().into()))
}
fn main() {
let a = Rc::new(vec![1, 2, 3]);
let b = Rc::new(Foo {
bar: "hello".into(),
});
let args = vec![a as Rc<dyn Any>, b];
let f: Box<dyn Fn(&[Rc<dyn Any>])> = create_function();
f(&args);
}
到目前一切尚好.将print_content()
方法显式提供给编译器后,生存期得到了正确解析,代码编译和运行都很好,打印:
view: [1, 2, 3]
foo: hello
当我试图创建一个以该函数为参数的泛型方法时,事情就变得一团糟:
fn create_function_with<'a, Function, A, B>(f: Function) -> Box<dyn Fn(&'a [Rc<dyn Any>])>
where
Function: 'static + Fn(A, B),
A: From<&'a dyn Any>,
B: From<&'a dyn Any>,
{
Box::new(move |args| f(args[0].as_ref().into(), args[1].as_ref().into()))
}
fn main() {
let a = Rc::new(vec![1, 2, 3]);
let b = Rc::new(Foo {
bar: "hello".into(),
});
let args = vec![a as Rc<dyn Any>, b];
let f: Box<dyn Fn(&[Rc<dyn Any>])> = create_function_with(print_content);
f(&args);
}
编译错误为:
error[E0308]: mismatched types
--> src/main.rs:54:42
|
54 | let f: Box<dyn Fn(&[Rc<dyn Any>])> = create_function_with(print_content);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected trait object `dyn for<'a> Fn(&'a [Rc<dyn Any>])`
found trait object `dyn Fn(&[Rc<dyn Any>])`
暗示create_function_with()
的生命周期 限制并不完全返回dyn Fn(&[Rc<dyn Any>]) that works independently of the lifetime of
&;[RC]`.
我已经try 了上面的许多变体,包括使用更高等级的特征界限.我不知道我是否已经达到了我对Rust知识的限制(可能)或语言本身的限制(不太可能).
同时,我已经设法使用宏解决了这个问题(有效地返回到转换闭包中内联了函数名称的初始工作版本).
这里是否遗漏了一些高级生命周期约束/定义?