首页 > 解决方案 > 闭包作为通用返回 `impl FnMut(T)`

问题描述

我已经实现callback_list_stream了通用,但我似乎无法以专门的方式使用它。如果我复制/粘贴每个T.

use futures::channel::mpsc::Receiver;
use futures::{channel::mpsc::channel};
use libpulse_binding::{
    callbacks::ListResult,
    context::introspect::{SinkInfo, SinkPortInfo, SourceInfo, SourcePortInfo},
};
use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll, Waker};
use std::{borrow::Cow, boxed::Box};

pub fn callback_list_stream<T: MakeOwned >() -> (impl FnMut(ListResult<&T>), Receiver<<T as MakeOwned>::Owned>) {
    let (mut sender, recv) = channel(1024); // TODO channel size?
    let cb = {
        move |c: ListResult<&T>| match c {
            ListResult::Item(it) => match sender.try_send(it.make_owned()) {
                Ok(_) => (),
                Err(err) => eprintln!("Failed to send message {:?}", err),
            },
            ListResult::End => sender.disconnect(),
            ListResult::Error => (), // TODO
        }
    };
    (cb, recv)
}

pub fn foo() -> (
    impl FnMut(ListResult<&SourceInfo<'_>>),
    Receiver<SourceInfo<'static>>
) {
    callback_list_stream()
}

编译器抱怨:

error[E0277]: expected a `std::ops::FnMut<(pulse::callbacks::ListResult<&pulse::context::introspect::SourceInfo<'_>>,)>` closure, found `impl for<'r> std::ops::FnMut<(pulse::callbacks::ListResult<&'r _>,)>`
   --> src/futuristic_pulse/callback_future.rs:230:5
    |
230 |     impl FnMut(ListResult<&SourceInfo<'_>>),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut<(pulse::callbacks::ListResult<&pulse::context::introspect::SourceInfo<'_>>,)>` closure, found `impl for<'r> std::ops::FnMut<(pulse::callbacks::ListResult<&'r _>,)>`
...
233 |     callback_list_stream()
    |     ---------------------- this returned value is of type `(impl for<'r> std::ops::FnMut<(pulse::callbacks::ListResult<&'r _>,)>, futures_channel::mpsc::Receiver<pulse::context::introspect::SourceInfo<'static>>)`
    |
    = help: the trait `for<'r, 's> std::ops::FnMut<(pulse::callbacks::ListResult<&'r pulse::context::introspect::SourceInfo<'s>>,)>` is not implemented for `impl for<'r> std::ops::FnMut<(pulse::callbacks::ListResult<&'r _>,)>`
    = note: the return type of a function must have a statically known size

error[E0271]: type mismatch resolving `for<'r, 's> <impl for<'t0> std::ops::FnMut<(pulse::callbacks::ListResult<&'t0 _>,)> as std::ops::FnOnce<(pulse::callbacks::ListResult<&'r pulse::context::introspect::SourceInfo<'s>>,)>>::Output == ()`
   --> src/futuristic_pulse/callback_future.rs:230:5
    |
230 |     impl FnMut(ListResult<&SourceInfo<'_>>),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime
    |
    = note: the return type of a function must have a statically known size

标签: rust

解决方案


我认为需要SourceInfo在原始参考中添加对内部数据生命周期的约束:

pub fn foo<'a, 'b>() -> (
    impl FnMut(ListResult<&'a SourceInfo<'b>>),
    Receiver<SourceInfo<'static>>,
) where 'b : 'a {
    let (cb, recv) = callback_list_stream();
    (cb, recv)
}

推荐阅读