Type erasure of a closure that returns an async block: 闭包返回异步块的类型擦除

huangapple go评论48阅读模式
英文:

Type erasure of a closure that returns an async block

问题

Certainly, here's the translated code without the comments:

|entity: &mut Entity| async move {
    entity.foo().await;
}

fn main() {
    erase_and_store(|entity: &mut Entity| async move {
        entity.foo().await;
    });
}

fn erase_and_store<'a, C, F>(closure: C) -> Task where
    C: FnOnce(&'a mut Entity) -> F,
    F: Future<Output = ()> + 'a {
    
    Task::Variant(/* TODO convert closure to something that can be stored */)
}

enum Task {
    Variant(/* TODO store closure */)
}

Please note that the comments indicating "TODO" are not translated as they are code placeholders specific to the programming task.

英文:

Consider the following closure that returns an async block:

|entity: &amp;mut Entity| async move {
    entity.foo().await;
}

Is it possible to type erase and store this closure inside an enum, without specifying a generic type or lifetime on that enum? Consider the following MWE:

use std::future::Future;

struct Entity;
impl Entity {
    async fn foo(&amp;mut self) {} 
}

fn main() {
    erase_and_store(|entity: &amp;mut Entity| async move {
        entity.foo().await;
    });
}

fn erase_and_store&lt;&#39;a, C, F&gt;(closure: C) -&gt; Task where
    C: FnOnce(&amp;&#39;a mut Entity) -&gt; F,
    F: Future&lt;Output = ()&gt; + &#39;a {
    
    Task::Variant(/* TODO convert closure to something that can be stored */)
}

enum Task {
    Variant(/* TODO store closure */)
}

I have tried a couple different approaches but it seems that even if I put everything behind boxed trait objects, I can not stop this generic lifetime &#39;a from leaking through to my Task enum.

type AnyFuture&lt;&#39;a&gt; = Box&lt;dyn Future&lt;Output = ()&gt; + &#39;a&gt;;
type AnyClosure&lt;&#39;a&gt; = Box&lt;dyn FnOnce(&amp;&#39;a mut Entity) -&gt; AnyFuture&lt;&#39;a&gt;&gt;;

enum Task {
    Variant(AnyClosure) // requires &lt;&#39;a&gt;
}

答案1

得分: 3

你想要的是一个更高排名的生命周期:

type AnyFuture<'a> = Pin<Box<dyn Future<Output = ()> + 'a>>;
type AnyClosure = Box<dyn for<'a> FnOnce(&'a mut Entity) -> AnyFuture<'a>>;

可以省略为:

type AnyFuture<'a> = Pin<Box<dyn Future<Output = ()> + 'a>>;
type AnyClosure = Box<dyn FnOnce(&mut Entity) -> AnyFuture<'_>>;
英文:

What you want is a higher-ranked lifetime:

type AnyFuture&lt;&#39;a&gt; = Pin&lt;Box&lt;dyn Future&lt;Output = ()&gt; + &#39;a&gt;&gt;;
type AnyClosure = Box&lt;dyn for&lt;&#39;a&gt; FnOnce(&amp;&#39;a mut Entity) -&gt; AnyFuture&lt;&#39;a&gt;&gt;;

That can be elided:

type AnyFuture&lt;&#39;a&gt; = Pin&lt;Box&lt;dyn Future&lt;Output = ()&gt; + &#39;a&gt;&gt;;
type AnyClosure = Box&lt;dyn FnOnce(&amp;mut Entity) -&gt; AnyFuture&lt;&#39;_&gt;&gt;;

huangapple
  • 本文由 发表于 2023年6月29日 20:38:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76581140.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定