Rust 是否有方法将引用传递给泛型函数并返回一个不为';t与参数有关';什么是生命?

Rust 是否有方法将引用传递给泛型函数并返回一个不为';t与参数有关';什么是生命?,rust,Rust,我已经在下面的示例中解决了一个问题,我使用了不必要的堆分配来解决这个问题: // Try replacing with (_: &String) fn make_debug<T>(_: T) -> impl std::fmt::Debug { 42u8 } fn test() -> impl std::fmt::Debug { let value = "value".to_string(); // try removing the am

我已经在下面的示例中解决了一个问题,我使用了不必要的堆分配来解决这个问题:

// Try replacing with (_: &String)
fn make_debug<T>(_: T) -> impl std::fmt::Debug {
    42u8
}

fn test() -> impl std::fmt::Debug {
    let value = "value".to_string();

    // try removing the ampersand to get this to compile
    make_debug(&value)
}

pub fn main() {
    println!("{:?}", test());
}
我至少可以通过两种方式修复此错误:

  • 不要在
    test()
    中传入对
    value
    的引用,而是传入
    value
    本身
  • 不要使用参数
    T
    ,而是将
    make_debug
    的参数类型显式声明为
    &String
    &str
  • 我对发生的情况的理解是,当存在一个参数时,借用检查器假设该参数的任何生存期都会影响输出
    impl Debug


    有没有办法保持代码参数化,继续传递引用,并让借用检查器接受它?

    我认为这是由于
    impl-trait
    不透明类型如何捕获生存期的规则造成的

    如果参数
    T
    中存在生存期,则
    impl trait
    必须合并它们。类型签名中的其他生存期遵循正常规则

    有关更多信息,请参阅:

    更完整的答案 最初的目标:send_form函数接受一个类型为&T的输入参数,该参数被呈现为二进制表示形式。这种二进制表示法归最终的impl Future所有,原始&T的任何残余都不存在。因此,&T的寿命不必超过impl特性。一切都好

    此外,当T本身包含具有生存期的引用时,问题就出现了。如果我们不使用impl-Trait,我们的签名将如下所示:

    fn发送表单(self,data:&T)->SendFormFuture;
    
    通过查看
    SendFormFuture
    ,我们可以很容易地观察到那里根本没有
    T
    的残余。因此,即使
    T
    有自己的生命周期需要处理,我们知道所有引用都在send\u表单的主体中使用,并且以后再也不会被
    SendFormFuture
    使用

    但是,使用
    impl Future
    作为输出,我们没有得到这样的保证。无法知道Future的具体实现是否实际上保留了
    T

    T
    没有引用的情况下,这仍然不是问题。要么是
    impl Future
    引用了
    T
    ,并完全拥有它的所有权,要么是它没有引用它,并且不会出现生存期问题

    但是,如果
    T
    确实有引用,您可能最终会遇到这样的情况:具体的
    impl Future
    保存在
    T
    中的引用。即使
    impl Future
    拥有
    T
    本身的所有权,它也不拥有
    T
    引用的值的所有权

    这就是为什么借阅支票必须是保守的,并且坚持
    T
    中的任何引用都必须有
    的静态寿命

    我能看到的唯一解决方法是绕过
    impl Future
    ,并在返回类型中显式显示。然后,您可以很容易地向借阅检查器演示输出类型根本不引用输入
    T
    类型,其中的任何引用都是无关的

    actix web客户端中
    发送表单
    的原始代码如下所示:

    发布fn发送表单(
    自己
    值:&T,
    )->impl未来<
    Item=ClientResponse,
    Error=SendRequestError,
    > {
    let body=match serde_urlencoded::to_字符串(值){
    Ok(body)=>body,
    Err(e)=>返回::A(Err(Error::from(e).into()),
    };
    //设置内容类型
    如果没有,则设slf=self.set\u header\u(
    标题::内容类型,
    “application/x-www-form-urlencoded”,
    );
    或者::B(slf.send_body(body::Bytes(Bytes::from(body)))
    }
    
    您可能需要对库进行修补,或者编写自己的函数来执行相同的操作,但使用具体的类型。如果其他人知道如何处理
    impl trait
    这个明显的局限性,我很乐意听到

    下面是我在
    awc
    (actix web客户端库)中重写
    send\u form
    所取得的进展:

    pub fn send\u form\u alt(
    自己
    值:&T,
    //)->impl未来<
    //Item=ClientResponse,
    //Error=SendRequestError,
    )->要么<
    未来结果,
    暗示未来<
    Item=板条箱::响应::ClientResponse,
    Error=SendRequestError,
    >,
    > {
    
    到目前为止,有一些警告:

    • other::B
      必然是
      未来的一种不透明的
      impl特征
    • futuresult
      的第一个参数实际上可能是
      Void
      或其他类似的参数

    您链接到的第一个问题已关闭,而且显然已修复。为什么您认为它与今天的代码相关?@Shepmaster设计背景风格。我预期会收到此评论,人们可能会误解,因此我将删除。我的最终目标是为我不知道的设计开发足够的直觉不需要搜索编译器错误。查看过去的错误是如何修复的(即与预期设计不一致的行为)可以告诉我很多。我得到的印象是,这不是一个喜欢塔木德式方法的地方,所以我编辑了参考资料。我完全认为提供背景信息是合理的,但提供没有上下文的链接是没有用的。介绍链接并解释基本内容。然而,大多数人确实希望得到答案太长了,读不下去了,所以现在把代码放在上面,用复制PA来做。