Generics 有没有一种表达方式;“相同”;具有不同生存期界限的泛型类型?

Generics 有没有一种表达方式;“相同”;具有不同生存期界限的泛型类型?,generics,rust,lifetime,type-constraints,Generics,Rust,Lifetime,Type Constraints,考虑以下(不完整)函数签名: unsafe-fn-foo(func:impl-FnOnce()->T+'a)->…… 是否有一种方法(当然是不安全的)转换输入函数,使其成为impl FnOnce()->S+'static,其中S与T的类型相同,但与S:'static 我知道可以通过使用一个装箱特征(FnBox)然后在箱子上调用transmute来改变闭包本身的生存期界限。但是,这并不影响返回类型(T)。据我所知,T:'a和T:'static就类型系统而言是不同的类型。所以我想知道是否有可能用锈来

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

unsafe-fn-foo(func:impl-FnOnce()->T+'a)->……

是否有一种方法(当然是不安全的)
转换输入函数,使其成为
impl FnOnce()->S+'static
,其中S与T的类型相同,但与
S:'static

我知道可以通过使用一个装箱特征(
FnBox
)然后在箱子上调用transmute来改变闭包本身的生存期界限。但是,这并不影响返回类型(
T
)。据我所知,
T:'a
T:'static
就类型系统而言是不同的类型。所以我想知道是否有可能用锈来表达这一点

我认为签名必须如下所示(忽略闭包本身的生命周期界限):


unsafe fn如果您只想使用简单类型执行此操作,那么这将非常简单,但在您尝试的过程中存在许多障碍。我会按照我在寻找答案时遇到它们的顺序来解释它们

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


总之,也许你应该退一步,找到一个不同的问题来解决,而不是这个问题。

我认为你想要的签名实际上是:
unsafe-fn-foo-impl-FnOnce()->T+'static
。但我不确定它是否会起作用,因为参数中
impl
的具体类型是由调用方确定的,但是返回位置的
impl
由函数决定。但不知何故,它们必须是一样的?我认为你做不到。如果你试图转化,你需要说转化成什么类型,但你实际上不能说出闭包的类型。这是一个非常不寻常的要求,我不得不想象你忽略了实现你真正想做的事情的其他方法。为什么不问一个关于底层问题的问题(通过其他方式强制执行生存期限制的生成线程)?例如,作用域线程可以解决许多生存期问题()。“这是一个非常不寻常的请求…”-同意。请参阅我答案末尾的摘要。感谢您的回答,使用盒装闭包作为trait对象对闭包非常有效,但我的问题主要是闭包的返回类型。我也不需要像欺骗类型系统那样欺骗借阅检查器,因为一旦建立了生存期界限,它似乎就与(泛型)类型密不可分。然而,您可能是对的,没有一个真正好的方法来实现这一点。我的意图正是实现作用域线程。stdlib线程spawn的签名是
pub-fn-spawn(f:f)->JoinHandle,其中f:FnOnce()->T,f:Send+'static,T:Send+'static
,我试图找到一种方法来欺骗类型系统,让我使用具有较不严格生存期限制的闭包/返回类型。在深入研究了一些作用域线程实现之后,我发现它们必须跨越很多障碍才能让这种事情正常工作,我希望找到一种更简单的方法。
unsafe fn<'a, T, S>(func: impl FnOnce() -> T) -> impl FnOnce() -> S
where
    T: 'a,
    S: 'static`
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,
use std::mem;

unsafe fn foo<'a, T>(func: impl Fn() -> T + 'a) -> Box<dyn Fn() -> T + 'static> {
    let boxed: Box<dyn Fn() -> T + 'a> = Box::new(func);
    mem::transmute(boxed)
}