如何在不查看代码的情况下读取终身错误?
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 (
&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”表示通过调用采用&self
的方法获得的引用。引用的代码行表明哪个方法调用是错误的。
注意:首先,生命周期不能超过 40:5 方法主体上定义的匿名生命周期 #1
这是第一个冲突的要求。 “生命周期”是指在第一条消息中提到的那个:它试图推断的那个,对于这个 autoref。它不能比您调用该方法的对象寿命长。引用的代码表示该对象的生命周期。在这种情况下,生命周期是错误行所在的整个方法,因为您借用的对象是该方法的 &mut self
的成员。
注意:...所以引用不会比借来的内容更有效
这只是进一步解释了这一点。 “那个引用”——你试图采用的自动引用——不能比 &mut self
引用的对象寿命长。
注意:但是,生命周期必须在生命周期 'v 内有效,如 22:1 的 impl 中所定义...
这里的“但是”引入了第二个要求,与第一个要求相冲突。
你问“为什么有这些约束?”,编译器马上解释:
注意:...所以表达式是可赋值的: 预期 viper::Method 找到 viper::Method
有问题的作业是错误行中的作业。您将new_cfg_method
的结果分配给cfg
。 “预期”是赋值的左侧,cfg
,其类型必须为 viper::Method<'v>
。 “找到”是右侧,方法调用的结果,类型为viper::Method<'_>
。 '_
表示编译器试图推断的生命周期。也就是说,这是您随后使用cfg
的方式,这意味着它必须具有'v
的生命周期。为什么会这样取决于错误消息中未引用的代码。
要解决此问题,您需要执行以下操作之一:
-
删除第一个要求。更改
new_cfg_method
,使其结果的生命周期与您调用它的对象的生命周期无关:可能是通过删除它包含的一些引用。
删除第二个要求。更改使用cfg
的代码,使其不需要拥有'v
的生命周期。同样,这可以通过删除 viper::Method
中的一些引用来实现。
如果您不能这样做,您可能需要引入 Cell
或其他东西来动态而不是静态地管理生命周期。
【讨论】:
以上是关于如何在不查看代码的情况下读取终身错误?的主要内容,如果未能解决你的问题,请参考以下文章
Grails:如何在不使用g:view的情况下读取错误(在控制器/服务中)
如何在不实际提取文件的情况下使用 VBScript 读取 .zip 文件的内容?