类型不匹配“绑定寿命参数” vs“混凝土寿命”当填充从闭合的集合 [英] Type mismatch "bound lifetime parameter" vs "concrete lifetime" when filling a collection from a closure

查看:119
本文介绍了类型不匹配“绑定寿命参数” vs“混凝土寿命”当填充从闭合的集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在可迭代序列中找到重复。此外,我想知道发生在那个序列中的元素,直到那一点。



因此,我创建了一个 HashMap ,并尝试调用 insert take_while 中使用的闭包内。但是,到目前为止,由于与具体/绑定的生命周期相关的类型不匹配,我还没有设法让它编译。<​​/ p>

这里是我的代码的简化版本,同样的错误:

 使用std :: collections :: HashSet; 
fn main(){
let mut seq = HashSet :: new();
let mut insert = | k | seq.insert(k);
(1..10).cycle()。take_while(insert);
}

这里是我得到的错误:

  main.rs:5:18:5:36错误:类型不匹配解析`for<'r> < [closure@main.rs:4:19:4:36 seq:_] as core :: ops :: FnOnce<(&'r _,)> :: Output == bool`:
期望的绑定生命周期参数,
查找具体生存期[E0271]
main.rs:5(1..10).cycle()。take_while(insert);
^ ~~~~~~~~~~~~~~~~~~~
main.rs:5:18:5:36帮助:运行`rustc --explain E0271`查看详细解释
main.rs:5:18:5:36错误:类型不匹配:类型`[closure@main.rs:4:19:4:36 seq:& mut std :: collections :: hash :: set :: HashSet< _>]`实现trait`core :: ops :: FnMut<(_,)>`, core :: ops :: FnMut<(&'r i32,)>`是必需的(期望的具体生存期,找到的绑定生命期参数)
main.rs:5(1..10)。 cycle()。take_while(insert);
^ ~~~~~~~~~~~~~~~~~~
main.rs:5:18:5:36帮助:运行`rustc --explain E0281`来查看详细说明
错误:由于前面的2个错误而中止

如何更改

解决方案

这是一个伪装的借用错误。



Iterator ::< Item = T> :: take_while() 接受 FnMut(& T) bool - 也就是说,它通过引用将每个元素传递给闭包。这是非常自然的,因为 take_while()必须能够产生成功测试的元素,所以它不能通过它的值。



这意味着 insert 参数类型被推断为& _ ,因此 HashSet 的泛型参数也被推断为& _ 。但是,这意味着您试图将对 cycle()迭代器产生的临时值的引用存储到寿命更长的结构中。这是借用规则不允许的。不幸的是,Rust不显示这个推理,因为有些原因,它不能推断数字类型是i32,它也不能推断闭包的正确的生存期参数。这是你的错误。



而是,你的闭包应该解引用参数,然后将它存储到集合。 这项工作

  use std :: collections :: HashSet; 
fn main(){
let mut seq = HashSet :: new();
let mut insert = |& k:& i32 | seq.insert(k);
(1..10).cycle()。take_while(insert);
}

我必须添加参数的完整类型;如上所述,我认为类型推断不够强大,不足以推断它。



如果你明确指定类型,你可以得到borrowck错误:

 使用std :: collections :: HashSet; 
fn main(){
let mut seq = HashSet :: new();
let mut insert = | k:& i32 | seq.insert(k); // no dereference
(1..10).cycle()。take_while(insert);
}

上面的代码等价于你的原始示例,除了显式类型注释,并导致以下错误:

 < anon>:4:43:4:44错误:由于冲突的要求,生命周期
< anon>:4 let mut insert = | k:& i32 | seq.insert(k);
^
< anon>:4:32:4:45注意:首先,生命周期不能超过4:31时块上定义的匿名生命周期#1 ...
< ; anon>:4 let mut insert = | k:& i32 | seq.insert(k);
^ ~~~~~~
< anon>:4:43:4:44注意:...表达式是可赋值的(预期` ,found`& i32`)
< anon>:4 let mut insert = | k:& i32 | seq.insert(k);
^
< anon>:5:32:5:38注意:但是,生命周期必须对于表达式在5:31 ...
< anon>:5 (1..10).cycle()。take_while(insert);
^ ~~~~~
< anon>:5:32:5:38注意:所以键入`[closure @< anon>:4:22:4:45 seq :& mut std :: collections :: hash :: set :: HashSet<& i32>]表达式在表达式
< anon>期间有效:5(1..10).cycle ).take_while(insert);
^ ~~~~~


I am trying to find repetitions in an iterable sequence. Furthermore, I want to know the elements that occurred in that sequence up to that point.

Therefore, I created a HashMap and am trying to call insert on it from within a closure used by take_while. However, I have so far not managed to get it to compile due to type mismatches related to concrete / bound lifetimes.

Here is a simplified version of my code which exhibits the same error:

use std::collections::HashSet;
fn main() {
    let mut seq = HashSet::new();
    let mut insert = |k| seq.insert(k);
    (1..10).cycle().take_while(insert);
}

And here are the errors I get:

main.rs:5:18: 5:36 error: type mismatch resolving `for<'r> <[closure@main.rs:4:19: 4:36 seq:_] as core::ops::FnOnce<(&'r _,)>>::Output == bool`:
 expected bound lifetime parameter ,
    found concrete lifetime [E0271]
main.rs:5       (1..10).cycle().take_while(insert);
                                ^~~~~~~~~~~~~~~~~~
main.rs:5:18: 5:36 help: run `rustc --explain E0271` to see a detailed explanation
main.rs:5:18: 5:36 error: type mismatch: the type `[closure@main.rs:4:19: 4:36 seq:&mut std::collections::hash::set::HashSet<_>]` implements the trait `core::ops::FnMut<(_,)>`, but the trait `for<'r> core::ops::FnMut<(&'r i32,)>` is required (expected concrete lifetime, found bound lifetime parameter ) [E0281]
main.rs:5       (1..10).cycle().take_while(insert);
                                ^~~~~~~~~~~~~~~~~~
main.rs:5:18: 5:36 help: run `rustc --explain E0281` to see a detailed explanation
error: aborting due to 2 previous errors

How do I need to change the code for it to work?

解决方案

This is in fact a borrowing error in disguise.

Iterator::<Item=T>::take_while() accepts a closure of kind FnMut(&T) -> bool - that is, it passes each element to the closure by reference. This is pretty much natural because take_while() must be able to yield the successfully tested element, so it can't pass it by value.

This means that insert argument type is inferred to be &_, and so HashSet's generic parameter is also inferred as &_. However, this means that you're attempting to store references to temporary values yielded by the cycle() iterator to a structure which lives much longer. This is not allowed by borrowing rules. Unfortunately, Rust doesn't show exactly this reasoning because for some reason it can't infer that the numeric type is i32 and it also can't infer the correct lifetime parameter for the closure. That's what your error is about.

Instead, your closure should dereference the argument before storing it to the set. This works:

use std::collections::HashSet;
fn main() {
    let mut seq = HashSet::new();
    let mut insert = |&k: &i32| seq.insert(k);
    (1..10).cycle().take_while(insert);
}

I had to add the full type of the argument too; as I said above, I think that the type inference is not powerful enough to deduce it.

BTW, you can actually get the borrowck error if you specify the type explicitly:

use std::collections::HashSet;
fn main() {
    let mut seq = HashSet::new();
    let mut insert = |k: &i32| seq.insert(k);  // no dereference
    (1..10).cycle().take_while(insert);
}

The code above is equivalent to your original example except for the explicit type annotation, and it results in the following error:

<anon>:4:43: 4:44 error: cannot infer an appropriate lifetime due to conflicting requirements
<anon>:4     let mut insert = |k: &i32| seq.insert(k);
                                                   ^
<anon>:4:32: 4:45 note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the block at 4:31...
<anon>:4     let mut insert = |k: &i32| seq.insert(k);
                                        ^~~~~~~~~~~~~
<anon>:4:43: 4:44 note: ...so that expression is assignable (expected `&i32`, found `&i32`)
<anon>:4     let mut insert = |k: &i32| seq.insert(k);
                                                   ^
<anon>:5:32: 5:38 note: but, the lifetime must be valid for the expression at 5:31...
<anon>:5     (1..10).cycle().take_while(insert);
                                        ^~~~~~
<anon>:5:32: 5:38 note: ...so type `[closure@<anon>:4:22: 4:45 seq:&mut std::collections::hash::set::HashSet<&i32>]` of expression is valid during the expression
<anon>:5     (1..10).cycle().take_while(insert);
                                        ^~~~~~

这篇关于类型不匹配“绑定寿命参数” vs“混凝土寿命”当填充从闭合的集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆