在类型别名上调用静态方法
Calling static method on type alias
在使用盒装闭包时,我 运行 遇到了以下问题:
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
是 unique type of the closure provided, 是 大小。然后,由于 Rc<ClosureType>
在 returns Rc<dyn Fn() -> i64>
的函数中返回,它隐式地将其转换为特征对象。
test_bad
失败是因为它不是从构建大小闭包的 Rc
然后将其转换为未大小化特征对象的 Rc
,而是尝试直接构建 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
。但是,在调用该函数后,编译器会执行 unsizing 强制转换 以将返回的 Rc<anonymous closure type>
转换为 Rc<dyn Fn() -> i64>
.
当您调用 MyConcreteRc::new(<closure>)
时,您不让编译器决定使用哪个 Rc::new
实现,而是告诉它必须使用 Rc::<dyn Fn() -> i64>::new
但不可能满足该实现的要求类型要求,因为 new
需要一个 Sized
参数,但 dyn Fn() -> i64
是 !Sized
,因此您看到的是编译错误消息。
在使用盒装闭包时,我 运行 遇到了以下问题:
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
是 unique type of the closure provided, 是 大小。然后,由于 Rc<ClosureType>
在 returns Rc<dyn Fn() -> i64>
的函数中返回,它隐式地将其转换为特征对象。
test_bad
失败是因为它不是从构建大小闭包的 Rc
然后将其转换为未大小化特征对象的 Rc
,而是尝试直接构建 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
。但是,在调用该函数后,编译器会执行 unsizing 强制转换 以将返回的 Rc<anonymous closure type>
转换为 Rc<dyn Fn() -> i64>
.
当您调用 MyConcreteRc::new(<closure>)
时,您不让编译器决定使用哪个 Rc::new
实现,而是告诉它必须使用 Rc::<dyn Fn() -> i64>::new
但不可能满足该实现的要求类型要求,因为 new
需要一个 Sized
参数,但 dyn Fn() -> i64
是 !Sized
,因此您看到的是编译错误消息。