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

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>,其中 ClosureTypeunique 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,因此您看到的是编译错误消息。