如何在不查看代码的情况下读取终身错误?

Posted

技术标签:

【中文标题】如何在不查看代码的情况下读取终身错误?【英文标题】:How to read a lifetime error without looking at the code? 【发布时间】:2018-08-30 16:21:51 【问题描述】:

我收到以下生命周期错误:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> prusti-viper/src/procedures_table.rs:42:40
   |
42 |         let mut cfg = self.cfg_factory.new_cfg_method(
   |                                        ^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 40:5...
  --> prusti-viper/src/procedures_table.rs:40:5
   |
40 | /     pub fn set_used(&mut self, proc_def_id: ProcedureDefId) 
41 | |         let procedure = self.env.get_procedure(proc_def_id);
42 | |         let mut cfg = self.cfg_factory.new_cfg_method(
43 | |             // method name
...  |
135| |         self.procedures.insert(proc_def_id, method);
136| |     
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> prusti-viper/src/procedures_table.rs:42:23
   |
42 |         let mut cfg = self.cfg_factory.new_cfg_method(
   |                       ^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'v as defined on the impl at 22:1...
  --> prusti-viper/src/procedures_table.rs:22:1
   |
22 | impl<'v, P: Procedure> ProceduresTable<'v, P> 
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: ...so that the expression is assignable:
           expected viper::Method<'v>
              found viper::Method<'_>

error: aborting due to previous error

不看代码,只看错误信息,是否可以理解错误信息指的是哪些生命周期/引用/借用?这是带有我的问题注释的消息:

错误[E0495]:由于要求冲突

,无法推断自动引用的适当生命周期(什么是自动引用?)

注意:首先,生命周期(哪个生命周期?)不能超过方法主体上定义的匿名生命周期#1 &amp;mut self,ok) 40:5...

...所以引用 (哪个引用?) 不会比借用的内容寿命长(哪个借用的内容?)

但是,生命周期必须在 22:1 的 impl 中定义的生命周期 'v 内有效... (为什么有这些限制?)

例如,我正在寻找类似“在错误消息 E0495 中,无法超过匿名生命周期 #1 的生命周期始终是 self 的生命周期,换句话说,又是 #1”这样的解释。

通过查看类似问题的现有答案(https://***.com/a/35519236/2491528、https://***.com/a/30869059/2491528、https://***.com/a/41271422/2491528),我无法找到错误消息所指内容的解释。有时答案只是写“在这种情况下,生命周期是'a”,但我想知道如何理解它是'a,而不是其他'b。其他时候,答案涉及对源代码的推理,但这对我来说是以下步骤之一:首先阅读消息并理解它所指的内容,然后理解错误(在这种情况下,可能是生命周期要求冲突) ,然后查看代码并尝试修复错误。

【问题讨论】:

强烈鼓励您生成一个minimal reproducible example,它会产生这些错误。在tag wiki page 上有一些关于生成 Rust MCVE 的技巧。我们不是神奇地神圣错误信息的神秘大师;我们需要与其他人一样看待代码。在此过程中,请edit您的问题解释为什么现有的讨论这些错误消息的问题还不够好。 我想我澄清了一点问题。重点更多的是错误消息而不是代码本身(我想修复,当然,但稍后)。 没有 MCVE,但故意:我的问题是如何解析错误消息,这似乎非常具体(“the 生命周期”、“that reference"...) 但我个人不知道它指的是什么。没有代码,报错信息就这么没用吗? 【参考方案1】:

由于需求冲突,无法为 autoref 推断出合适的生命周期

这是错误的关键部分。一生中有两个(或更多)要求,并且它们相互冲突。 “autoref”表示通过调用采用&amp;self 的方法获得的引用。引用的代码行表明哪个方法调用是错误的。

注意:首先,生命周期不能超过 40:5 方法主体上定义的匿名生命周期 #1

这是第一个冲突的要求。 “生命周期”是指在第一条消息中提到的那个:它试图推断的那个,对于这个 autoref。它不能比您调用该方法的对象寿命长。引用的代码表示该对象的生命周期。在这种情况下,生命周期是错误行所在的整个方法,因为您借用的对象是该方法的 &amp;mut self 的成员。

注意:...所以引用不会比借来的内容更有效

这只是进一步解释了这一点。 “那个引用”——你试图采用的自动引用——不能比 &amp;mut self 引用的对象寿命长。

注意:但是,生命周期必须在生命周期 'v 内有效,如 22:1 的 impl 中所定义...

这里的“但是”引入了第二个要求,与第一个要求相冲突。

你问“为什么有这些约束?”,编译器马上解释:

注意:...所以表达式是可赋值的: 预期 viper::Method 找到 viper::Method

有问题的作业是错误行中的作业。您将new_cfg_method 的结果分配给cfg。 “预期”是赋值的左侧,cfg,其类型必须为 viper::Method&lt;'v&gt;。 “找到”是右侧,方法调用的结果,类型为viper::Method&lt;'_&gt;'_ 表示编译器试图推断的生命周期。也就是说,这是您随后使用cfg 的方式,这意味着它必须具有'v 的生命周期。为什么会这样取决于错误消息中未引用的代码。

要解决此问题,您需要执行以下操作之一:

    删除第一个要求。更改new_cfg_method,使其结果的生命周期与您调用它的对象的生命周期无关:可能是通过删除它包含的一些引用。 删除第二个要求。更改使用cfg 的代码,使其不需要拥有'v 的生命周期。同样,这可以通过删除 viper::Method 中的一些引用来实现。

如果您不能这样做,您可能需要引入 Cell 或其他东西来动态而不是静态地管理生命周期。

【讨论】:

以上是关于如何在不查看代码的情况下读取终身错误?的主要内容,如果未能解决你的问题,请参考以下文章

(JFrame)如何在不显示的情况下读取随机数进行比较?

如何在不接触缓存的情况下写入或读取内存

Grails:如何在不使用g:view的情况下读取错误(在控制器/服务中)

如何在不实际提取文件的情况下使用 VBScript 读取 .zip 文件的内容?

如何在不读取标准输入的情况下使用“npm login”设置 npm 凭据?

如何在不连接的情况下读取 Python 数据框中的数据?