简体   繁体   English

我如何解决导致错误的闭包[E0495]:无法推断适当的生存期

[英]How do I work around closures causing error[E0495]: cannot infer an appropriate lifetime

I have this "simplified" code to demonstrate a problem I am having with a more complicated project. 我有这个“简化的”代码来演示我在一个更复杂的项目中遇到的问题。

I have created a closure to capture some parameters so I can invoke a small function in two places without repeating the code. 我创建了一个闭包以捕获一些参数,因此可以在两个地方调用一个小函数而无需重复代码。 Unfortunately, lifetimes are now involved, and I am having difficulty understanding what exactly has the compiler confused: 不幸的是,现在涉及生命周期,并且我很难理解编译器到底混淆了什么:

use std::io::Write;

pub struct X<'c>
{
    maybe_file: Option<Box<dyn Write+'c>>,
}

impl<'c> X<'c>
{
    pub fn wrap<'a:'c,'b:'c> (prefix:&'a str, base: &'b mut X<'b>) ->X<'c>
    {
        return X::<'c> {
            maybe_file: Some(Box::new(X::wrapper(prefix, base))),
        }
    }
    pub fn wrapper<'a, 'b>(prefix:&'a str, base:&'b mut X<'b>) -> Wrapper<'a,'b>
    {
        Wrapper {
            prefix:prefix, base:base
        }
    }

    pub fn boop_the_snoot(&self) {}
}

//

pub struct Wrapper<'a,'b>
{
    pub prefix: &'a str,
    pub base: &'b X<'b>,
}

impl<'a,'b> Write for Wrapper<'a,'b>
{
    fn write(&mut self, buf:&[u8]) ->Result<usize, std::io::Error> { Ok(0) }
    fn flush(&mut self) ->Result<(), std::io::Error> { Ok(()) }
}


pub fn bacon(x:&mut X, scale:f32)
{

}

pub fn eggs<'c>(x:&'c mut X<'c>, scale:f32)
{
    bacon( & mut X::wrap("A:\t", x), scale);

    let f = |x:& mut X| {
        bacon(& mut X::wrap("B:\t", x), scale);
    };

    f(x);

    f(x);
}

This gives me the following compile error: 这给了我以下编译错误:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
  --> /home/thoth/src/embroidery/filler/src/lifetimes_shenanigans.rs:68:19
   |
68 |       bacon(& mut X::wrap("B:\t", x), scale);
   |                   ^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 67:13...
  --> /home/thoth/src/embroidery/filler/src/lifetimes_shenanigans.rs:67:13
   |
67 |       let f = |x:&mut X| {
   |  _____________^
68 | |       bacon(& mut X::wrap("B:\t", x), scale);
69 | |     };
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> /home/thoth/src/embroidery/filler/src/lifetimes_shenanigans.rs:68:35
   |
68 |       bacon(& mut X::wrap("B:\t", x), scale);
   |                                   ^
note: but, the lifetime must be valid for the anonymous lifetime #2 defined on the body at 67:13...
  --> /home/thoth/src/embroidery/filler/src/lifetimes_shenanigans.rs:67:13
   |
67 |       let f = |x:&mut X| {
   |  _____________^
68 | |       bacon(& mut X::wrap("B:\t", x), scale);
69 | |     };
   | |_____^
   = note: ...so that the expression is assignable:
           expected &mut lifetimes_shenanigans::X<'_>
              found &mut lifetimes_shenanigans::X<'_>

What sort of lifetime crimes is this logic protecting me from? 这种逻辑可以保护我免受一生的罪行吗? What should I add to this code to enable the rust compiler to understand the lifetimes of the various objects? 我应该在代码中添加些什么,以使rust编译器了解各种对象的生存期?

I was able to get the code to compile by replacing the declarations of the form &'b mut X<'b> with &'z mut X<'b> , basically decoupling the lifetime of the reference from the lifetime of the field inside X. 我可以通过将&'b mut X<'b>形式的声明替换为&'z mut X<'b>声明要编译的代码,基本上将引用的生存期与字段内部的生存期解耦X。

Another important change was to remove all lifetimes from the eggs() function. 另一个重要的更改是删除了eggs()函数的所有生命周期。 This actually raises its own question: Is it possible to explcitly declare the lifetimes in the eggs function and still get it to compile? 这实际上提出了自己的问题:是否有可能在eggs函数中明确声明生命周期并仍然可以对其进行编译? I have made a few clumsy attempts and ended up with [E0502]: cannot borrow *x as immutable because it is also borrowed as mutable which confirms there are subtleties I do not yet understand. 我做了一些笨拙的尝试,并以[E0502]: cannot borrow * x as immutable because it is also borrowed as mutable [E0502]: cannot borrow as immutable because it is also borrowed as mutable从而证实了我尚不了解的微妙之处。

The patch looks like this: 该补丁看起来像这样:

@@ -7,13 +7,13 @@

 impl<'c> X<'c>
 {
-    pub fn wrap<'a:'c,'b:'c> (prefix:&'a str, base: &'b mut X<'b>) ->X<'c>
+    pub fn wrap<'a:'c,'b:'c,'z:'c> (prefix:&'a str, base: &'z mut X<'b>) ->X<'c>
     {
         return X::<'c> {
             maybe_file: Some(Box::new(X::wrapper(prefix, base))),
         }
     }
-    pub fn wrapper<'a, 'b>(prefix:&'a str, base:&'b mut X<'b>) -> Wrapper<'a,'b>
+    pub fn wrapper<'a, 'b, 'z>(prefix:&'a str, base:&'z mut X<'b>) -> Wrapper<'a,'b, 'z>
     {
         Wrapper {
             prefix:prefix, base:base
@@ -25,13 +25,13 @@

 //

-pub struct Wrapper<'a,'b>
+pub struct Wrapper<'a,'b, 'z>
 {
     pub prefix: &'a str,
-    pub base: &'b X<'b>,
+    pub base: &'z X<'b>,
 }

-impl<'a,'b> Write for Wrapper<'a,'b>
+impl<'a,'b,'z> Write for Wrapper<'a,'b,'z>
 {
     fn write(&mut self, buf:&[u8]) ->Result<usize, std::io::Error> { Ok(0) }
     fn flush(&mut self) ->Result<(), std::io::Error> { Ok(()) }
@@ -43,7 +43,7 @@

 }

-pub fn eggs<'c>(x:&'c mut X<'c>, scale:f32)
+pub fn eggs(x:& mut X, scale:f32)
 {
     bacon( & mut X::wrap("A:\t", x), scale);

@@ -53,5 +53,7 @@

     f(x);

+    x.boop_the_snoot();
+
     f(x);
 }

And the complete "fixed" source code is 完整的“固定”源代码是

use std::io::Write;

pub struct X<'c>
{
    maybe_file: Option<Box<dyn Write+'c>>,
}

impl<'c> X<'c>
{
    pub fn wrap<'a:'c,'b:'c,'z:'c> (prefix:&'a str, base: &'z mut X<'b>) ->X<'c>
    {
        return X::<'c> {
            maybe_file: Some(Box::new(X::wrapper(prefix, base))),
        }
    }
    pub fn wrapper<'a, 'b, 'z>(prefix:&'a str, base:&'z mut X<'b>) -> Wrapper<'a,'b, 'z>
    {
        Wrapper {
            prefix:prefix, base:base
        }
    }

    pub fn boop_the_snoot(&self) {}
}

//

pub struct Wrapper<'a,'b, 'z>
{
    pub prefix: &'a str,
    pub base: &'z X<'b>,
}

impl<'a,'b,'z> Write for Wrapper<'a,'b,'z>
{
    fn write(&mut self, buf:&[u8]) ->Result<usize, std::io::Error> { Ok(0) }
    fn flush(&mut self) ->Result<(), std::io::Error> { Ok(()) }
}


pub fn bacon(x:&mut X, scale:f32)
{

}

pub fn eggs(x:& mut X, scale:f32)
{
    bacon( & mut X::wrap("A:\t", x), scale);

    let f = |x:&mut X| {
        bacon(& mut X::wrap("B:\t", x), scale);
    };

    f(x);

    x.boop_the_snoot();

    f(x);
}

So, this is basically half an answer: the code compiles and I can continue with my project using this pattern; 因此,这基本上是一半的答案:代码可以编译,我可以使用这种模式继续我的项目; However it relies on the rust compiler to do some lifetime inferences while compiling eggs(). 但是,它依赖rust编译器在编译egg()时进行一些生命周期推断。 What would the code look like if we were to annotate eggs() with lifetime information that matches what the compiler infers? 如果我们用与编译器推断的匹配的生存期信息注释egg(),代码将是什么样? The answer to that would be educational. 答案将是教育性的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Rust:错误[E0495]:由于闭包中的冲突要求,无法为自动拒绝推断适当的生命周期 - Rust: error[E0495]: cannot infer an appropriate lifetime for autorefdue to conflicting requirements in closure 错误:由于需求冲突,无法推断autoref的适当生命周期[E0495] - error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495] Rust:错误[E0495]:由于需求冲突,无法为 autoref 推断合适的生命周期 - Rust: error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements 无法为结构内具有相同生命周期的多个引用推断生命参数的适当生命周期 [E0495] - cannot infer an appropriate lifetime for lifetime parameter with multiple references with the same lifetime inside a struct [E0495] Rust 错误代码 E0495 是什么意思? - What does the Rust error code E0495 mean? Rust 错误 E0495 在闭包中使用 split_at_mut - Rust error E0495 using split_at_mut in a closure 从向量返回元素时出错E0495 - Error E0495 when returning an element from a vector 如何在闭包的生命周期和闭包借用的变量上解释 Rust 错误 E0495 - How to interpret Rust error E0495 on the lifetimes of a closure and a variable borrowed by the closure 无法推断出合适的生命周期 - cannot infer an appropriate lifetime for lifetime 为什么在使用嵌套的可变引用时,我会收到错误“无法推断泛型参数的适当生命周期”? - Why do I get the error “cannot infer an appropriate lifetime for lifetime parameter in generic type” when using nested mutable references?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM