在类型别名上调用静态方法



在使用框闭包时,我遇到了以下问题:

type Test = Rc<dyn Fn() -> i64>;
fn test_bad() -> Test {
Test::new(|| 42)
}
fn test_good() -> Test {
Rc::new(|| 42)
}

在第一种情况下,我使用类型别名来引用new方法,而在第二种情况下,我直接使用Rc

在第一种情况下,编译器报错:

|       Test::new(|| 42)
|             ^^^ function or associated item not found in `Rc<(dyn Fn() -> i64 + 'static)>`
|
= note: the method `new` exists but the following trait bounds were not satisfied:
`dyn Fn() -> i64: Sized`

但是第二种情况很好。有人能解释一下这两者的区别吗?是否有任何方法可以通过类型别名引用new,或者我需要自己包装它?

test_good中,通过在|| 42上调用Rc::new,您创建一个Rc<dyn Fn() -> i64>,但是一个Rc<ClosureType>,其中ClosureType是所提供闭包的唯一类型,并且大小的。然后,由于Rc<ClosureType>是在返回Rc<dyn Fn() -> i64>的函数中返回的,因此它将其隐式地强制转换为trait对象。

test_bad失败了,因为它不是从构造一个有大小的闭包的Rc然后将其强制转换为一个没有大小的trait对象的Rc,而是试图直接构造一个没有大小的trait对象的Rc,这失败了,因为函数的所有参数都必须有大小。

我不认为有一个直接的方法来引用new通过类型别名,虽然你可以很容易地创建自己的:

fn new_test(func: impl 'static + Fn() -> i64) -> Test {
Rc::new(func)
}

泛型类型别名有效,但具体类型别名失败:

use std::rc::Rc;
type MyGenericRc<T> = Rc<T>;
// works
fn construct_with_generic_alias() -> MyGenericRc<dyn Fn() -> i64> {
MyGenericRc::new(|| 42)
}
type MyConcreteRc = Rc<dyn Fn() -> i64>;
// fails
fn construct_with_concrete_alias() -> MyConcreteRc {
MyConcreteRc::new(|| 42)
}

当你调用MyGenericRc::new(<closure>)时,编译器选择Rc::<closure type>::new(<closure>)作为要使用的具体函数实现,因为Rc::new需要Sized参数,并且每个匿名闭包类型都是Sized。然而,在调用该函数之后,编译器执行取消大小强制转换将返回的Rc<anonymous closure type>转换为Rc<dyn Fn() -> i64>

当你调用MyConcreteRc::new(<closure>)时,你不让编译器决定使用哪个Rc::new实现,你告诉它必须使用Rc::<dyn Fn() -> i64>::new,但它不可能满足该实现的类型要求,因为new期望Sized参数,但dyn Fn() -> i64!Sized,因此你看到的编译错误消息。

最新更新