有没有一种方法可以表达具有不同生命周期限制的“相同”泛型类型?

时间:2018-09-20 11:45:45

标签: generics rust lifetime type-constraints

考虑以下(不完整的)函数签名:

unsafe fn foo<'a, T: 'a>(func: impl FnOnce() -> T + 'a) -> ...

有没有一种方法(当然是不安全地)transmute的输入函数,因此它变成impl FnOnce() -> S + 'static,其中S与T的类型相同,但带有S: 'static

我知道可以通过使用带框特征(FnBox)然后在框上调用transmute来改变封闭本身的生命周期界限。但是,这不会影响返回类型(T)。据我了解,就类型系统而言,T: 'aT: 'static是不同的类型。所以我想知道是否有可能在Rust中表达这一点。

我想签名必须看起来像这样(忽略闭包本身的生命周期限制):

unsafe fn<'a, T, S>(func: impl FnOnce() -> T) -> impl FnOnce() -> S
where
    T: 'a,
    S: 'static`

但是您如何在没有规定TS除了生命周期相同的情况下调用此函数。

免责声明 我知道,修改生命周期界限通常不是一个好主意,但是,这是为了生成通过其他方式强制执行生命周期限制的线程。

1 个答案:

答案 0 :(得分:2)

如果您只想使用简单的类型来做到这一点,那将很简单,但是您要尝试的操作有很多障碍。在尝试寻找答案时,我会按照遇到它们的顺序来解释它们。

首先,您不能使用impl trait类型来实现此功能,因为函数本身必须选择将要返回的具体实现,但不能这样做,因为实现将始终基于选择调用者的参数func的类型。这排除了“自然”类型:

unsafe fn foo<'a, T>(func: impl FnOnce() -> T + 'a) -> impl FnOnce() -> T + 'static

并导致更像:

unsafe fn foo<'a, T, F, G>(func: F) -> G
where
    F: FnOnce() -> + 'a,
    G: FnOnce() -> + 'static,

但是,呼叫者如何知道G是什么类型?

如果您尝试使用mem::transmute来欺骗借阅检查器,则需要告诉它要转换成什么。问题在于,您仅知道类型(例如)impl FnOnce() -> T + 'static,但是您实际上无法写下闭包的具体类型,因此这也行不通。

所以我认为答案是Box的结果。这听起来可能不尽人意,但情况会变得更糟!虽然可以创建一个Box<dyn FnOnce()>,但它是currently impossible to call that function later,这意味着您必须做出另一个妥协,即从FnOnce升级到{{1} }。

Fn

总而言之,也许您应该退后一步,找到另一个要解决的问题,而不是这个问题。