我很难理解为什么rust不喜欢我的remove_str方法:
use std::cell::RefCell;
use std::collections::HashSet;
#[derive(Hash, Eq, PartialEq)]
struct StringWrap<'a>{
s: &'a String,
}
struct Container<'a>{
m: HashSet<StringWrap<'a>>
}
impl<'a> Container<'a>{
fn remove_str(&mut self, s: &str){
let string = String::from(s);
let to_remove = StringWrap{s: &string};
self.m.remove(&to_remove);
}
}
它窒息了:
error[E0597]: `string` does not live long enough
--> tests/worksheet.rs:17:39
|
14 | impl<'a> Container<'a>{
| -- lifetime `'a` defined here
...
17 | let to_remove = StringWrap{s: &string};
| ^^^^^^^ borrowed value does not live long enough
18 | self.m.remove(&to_remove);
| ------------------------- argument requires that `string` is borrowed for `'a`
19 | }
| - `string` dropped here while still borrowed
据我所知,我的string
和to_remove
的寿命足够长,允许.remove
调用完成它的工作。是因为remove可能是异步的还是类似的原因?
感谢任何帮助或洞察力!
2条答案
按热度按时间flvlnr441#
据我所知,我的字符串和to_remove存活的时间足够长,可以允许。remove调用来完成其工作。是因为remove可能是异步的还是类似的原因?
不,这是因为
HashSet::remove
必须使用借用时项目变成的东西来调用:但是,除非您手动为
StringWrap
实现Borrow
,否则只能应用总括自反实现,因此只能使用&StringWrap<'a>
类型的value
调用remove
。注意使用寿命要求。要完成这项工作,您需要为
StringWrap
实现Borrow
。例如,您可以执行以下操作:然后
Container::remove_str
只能将其参数转发给HashMap::remove
:See it on the playground。
尽管如此,在
HashSet
中存储引用是相当不寻常的:典型地,将所存储的String
s的所有权移动到集合中,这将使得该问题没有实际意义,因为没有使用寿命。hvvq6cgz2#
在HashSet::remove/take/get(arg1:(&Q):
这些内部调用将尝试从HashSet本身内部获取“T的借用版本Q”,以与T的Borrowtrait进行比较。因此,自定义
impl Borrow<Q> for T
具有适当的生存期是一个好主意。