Types Rust:返回非对象安全特性的实现的特性中的通用返回类型

Types Rust:返回非对象安全特性的实现的特性中的通用返回类型,types,rust,serde,return-type-deduction,tokio,Types,Rust,Serde,Return Type Deduction,Tokio,我是个新手,我想通过实施一些小项目来学习这门语言并获得更好的理解。我的第一次尝试是解析从MQTT代理接收的JSON数据。 我很高兴在tornado和serde的帮助下很容易做到这一点。然而,很快就出现了一种模式,我想(理想地)将其提取成一种特征 let person_stream=sender.subscribe().filter_map(|数据|{ 如果让Ok(值)=数据{ 返回serde_json::from_slice::(&value).ok(); } 没有一个 }); 其中sende

我是个新手,我想通过实施一些小项目来学习这门语言并获得更好的理解。我的第一次尝试是解析从MQTT代理接收的JSON数据。 我很高兴在
tornado
serde
的帮助下很容易做到这一点。然而,很快就出现了一种模式,我想(理想地)将其提取成一种特征

let person_stream=sender.subscribe().filter_map(|数据|{
如果让Ok(值)=数据{
返回serde_json::from_slice::(&value).ok();
}
没有一个
});
其中
sender
通常是
tokio::sync::*::sender
Person
将实现
serde::de::DeserializeOwned
特征

因此,我们的目标是实现一个将
tokio::stream::StreamExt
转换为另一个
StreamExt
的东西,其中关联的
项将实现
反序列化

我花了相当长的时间才弄明白(因为我最初想在泛型中使用特征或函数),然后我想出了

fn变换(流:U)->impl-streamxt
哪里
T:serde::de::反序列化拥有,
U:,
{
stream.filter|map(|数据|{
如果让Ok(值)=数据{
返回serde_json::from_slice::(&value).ok();
}
没有一个
})
}
虽然这是可行的,但我最初想要的是

trait变换
{
fn变换(自)->T;
}
或者将
实现为
,这实际上是相同的,我可以为
StreamExt
实现。由于
impl Trait
return对Traits不可用,因此这是我认为唯一的选择。然而,在实现这一点时,我面临着几个问题

  • 对于
    T
    (这是
    filter\u-map()
    的返回类型),无法使用
    tokio::stream::filter\u-map::filter\u-map
    ),因为模块
    filter\u-map
    私有的
  • 使用
    Box
    也不可能,因为
    StreamExt
    在几个函数中返回
    Self
    。不过,我一开始不希望堆开销;) 所以我的问题是:如果
    filter\u map()
    的返回类型是
    private
    并且
    StreamExt
    不是对象安全的,那么我在这里可以做些什么来获得Trait实现的语法糖呢?使用它会很酷

    let person_stream=receiver.transform();
    
    into()
    。显然,我有一个有效的实现,所以这对我来说并不是一个真正关键的问题。但正如我一开始所说的,我首先想对锈病有一个更深入、更好的了解

    我注意到有
    tokio serde
    板条箱,但乍一看它只处理框架数据,所以我没有深入研究

    附言: 当类型推断失败时,我实现的自由函数
    transform
    I也遇到了一个问题。例如,当将新流传递给函数

    async-fn-debug\u接收器(mut-receiver:T)
    哪里
    T:streamxt+Unpin,
    T::Item:std::fmt::Debug,
    {
    而让一些(项目)=receiver.next().等待{
    println!(“项目:{:#?}”,项目);
    }
    }
    
    在这种情况下,它显然无法在
    transfer
    中推断
    t
    ,而不是像这样

    异步fn个人接收器(mut接收器:impl-streamxt+Unpin){
    而让一些(人)=接收者。下一步()等待{
    println!(“Person:{:#?}”,Person);
    }
    }
    
    但是,我不想注释所有类型参数,只注释它无法推断的类型参数。经过反复试验,我发现我可以使用

    transform::(流);
    

    我完全不知道。不过,我在文档中找不到这个。这是某种隐藏的功能,还是我只是无法正确rtfm?:)

    我认为您需要的东西可以在夜间使用
    type\u alias\u impl\u trait
    功能。基本上,它允许您在trait中编写关联的类型,然后在实现中,使用
    impl BaseTrait
    语法而不是编写命名类型

    我懒得用
    type\u alias\u impl\u trait
    编写代码(而且您没有提供可编译的代码段),但这里是一个工作示例():


    注意
    ()::dou_something
    实际上返回了一个
    &'static str
    ,但是从来没有提到过这种类型。

    谢谢!这似乎就是我要找的。然而,我无法让它满足我的要求。您可能想看看这个示例。@BeneSim:我认为您的代码基本上是正确的。可能应该是
    type Output=impl-StreamExt,或者可能不需要该注释。但是请注意,在需要错误类型注释之后,您会得到一个
    内部编译器错误
    。这个特性仍然不稳定是有原因的……我确实用
    typeoutput=impl-StreamExt尝试过它但它也不起作用。我猜你是对的,
    rustc
    crash应该给我一个暗示,这个特性还没有我想要的那么稳定。也许我只是在等待,直到事情变得不稳定甚至稳定。在此之前,我将使用free函数
    transform
    #![feature(type_alias_impl_trait)]
    
    use std::fmt::Debug;
    
    trait Foo {
        type Output: Debug;
    
        fn do_something() -> Self::Output;
    }
    
    impl Foo for () {
        type Output = impl Debug;
    
        fn do_something() -> Self::Output {
            "hello!"
        }
    }