代码之家  ›  专栏  ›  技术社区  ›  Aaa

为什么我不能在返回impl特性的impls中的方法上使用引用参数?

  •  3
  • Aaa  · 技术社区  · 6 月前
    struct TestStruct { }
    trait TestTrait  { }
    impl TestTrait for TestStruct { }
    
    struct ResultStruct { }
    
    trait ResultTrait {
        fn make_struct(&self, str: &String) -> impl TestTrait;
        fn test_lifetime(&self) -> impl TestTrait;
    }
    
    impl ResultTrait for ResultStruct {
        fn make_struct(&self, str: &String) -> impl TestTrait {
            TestStruct { }
        }
        fn test_lifetime(&self) -> impl TestTrait {
            let str = "foo".to_string();
            self.make_struct(&str) // error occurs here
        }
    }
    

    在这个示例中,编译器给了我错误:

    error[E0597]: `str` does not live long enough
      --> src/lib.rs:18:26
       |
    16 |     fn test_lifetime(&self) -> impl TestTrait {
       |                      - let's call the lifetime of this reference `'1`
    17 |         let str = "foo".to_string();
       |             --- binding `str` declared here
    18 |         self.make_struct(&str) // error occurs here
       |         -----------------^^^^-
       |         |                |
       |         |                borrowed value does not live long enough
       |         argument requires that `str` is borrowed for `'1`
    19 |     }
       |     - `str` dropped here while still borrowed
    

    TestStruct 直接没有 impl TestTrait 实施 ResultStruct 随着 impl ResultStruct { } ResultTrait

    这种情况似乎只发生在返回impl trait的trait方法中。

    为什么会出现这种错误?我能做些什么来修复它?我可以用 dyn ,删除参考参数,或完全删除沟渠特征。但是,是否有一种解决方案可以保持 impl

    1 回复  |  直到 6 月前
        1
  •  3
  •   user4815162342    6 月前

    您需要添加 + use<> make_struct() 实现以防止它捕获其生命周期 str 论点:

    impl ResultTrait for ResultStruct {
        fn make_struct(&self, str: &String) -> impl TestTrait + use<> {
            TestStruct {}
        }
        // ...
    }
    

    Playground

    use<> 这两个参数的生命周期都记录在 impl TestTrait 返回,因为这是默认值,因为编译器只使用签名来推断生存期,而不是函数体。这个默认值是合理的,因为它允许返回的值使用传递给函数的引用,这是经常需要的。没有 use

    // anonymous struct returned by `make_struct()`
    struct Anon<'a, 'b> {
        inner: TestStruct,
        _phantom: PhantomData<(&'a ResultStruct, &'b String)>,
    }
    
    impl TestTrait for Anon<'_, '_> {
        // if TestTrait had methods, they'd forward to self.inner
    }
    
    impl ResultTrait for ResultStruct {
        fn make_struct<'a, 'b>(&'a self, str: &'b String) -> Anon<'a, 'b> {
            // returns an anonymous struct tied to the lifetimes of self and str
            Anon {
                inner: TestStruct {},
                _phantom: PhantomData,
            }
        }
        // ...
    }
    

    Playground

    该实现导致了相同的借用检查错误,这是由以下原因引起的 Anon 从返回 test_lifetime() 同时捕获局部变量的生存期 怎么翻译 .

    使用<> 导致脱糖,其中 匿名 no longer captures 'b 寿命( &self 仍然被捕获,据我所知,这不能被排除在外)。有了这样的去糖,编译就成功了,就像它对 使用<> .

    使用 this article .

    推荐文章