Rust,如何返回对结构中持续时间与结构相同的内容的引用?
我正在移植一个我写给Rust的编译器。在其中,我有一个enumRust,如何返回对结构中持续时间与结构相同的内容的引用?,rust,lifetime,Rust,Lifetime,我正在移植一个我写给Rust的编译器。在其中,我有一个enum实体,它表示函数和变量之类的东西: 发布枚举实体) //以后还有更多的空间。 } 然后我有一个structScope,负责在散列映射中保存这些实体,其中键是程序员给实体的名称。(例如,声明名为sin的函数会将实体放入键sin处的哈希映射中) 发布结构范围>, 家长:选项> } 我希望能够获得HashMap中对象的只读引用,以便可以从其他数据结构中引用它。例如,当我解析函数调用时,我希望能够存储对正在调用的函数的引用,而不仅仅是存储
实体
,它表示函数和变量之类的东西:
发布枚举实体)
//以后还有更多的空间。
}
然后我有一个structScope
,负责在散列映射中保存这些实体,其中键是程序员给实体的名称。(例如,声明名为sin
的函数会将实体
放入键sin
处的哈希映射中)
发布结构范围>,
家长:选项>
}
我希望能够获得HashMap中对象的只读引用,以便可以从其他数据结构中引用它。例如,当我解析函数调用时,我希望能够存储对正在调用的函数的引用,而不仅仅是存储函数的名称,并且每次需要与名称对应的实际实体
对象时都必须查找引用。为此,我采用了以下方法:
impl{
发布fn查找(&self,符号:&str)->选项>{
让结果=self.symbols.get(symbol);
比赛结果{
选项::无=>匹配self.parent{
选项::无=>选项::无,
选项::Some(parent)=>parent.lookup(符号),
},
选项::某些(_值)=>结果
}
}
}
但是,这会导致编译错误:
错误[E0495]:由于需求冲突,无法推断自动引用的适当生存期
-->src/vague/scope.rs:29:31
|
29 |让结果=self.symbols.get(symbol);
| ^^^
|
注意:首先,生命周期不能超过方法体上28:3定义的匿名生命周期#1。。。
-->src/vague/scope.rs:28:3
|
28 |/pub fn查找(&self,symbol:&str)->选项>{
29 | |让结果=self.symbols.get(symbol);
30 | |匹配结果{
31 | |选项::无=>匹配self.parent{
... |
36 | | }
37 | | }
| |___^
注意:…这样引用就不会超过借用的内容
-->src/vague/scope.rs:29:18
|
29 |让结果=self.symbols.get(symbol);
| ^^^^^^^^^^^^
注意:但是,生存期必须对impl上9:6定义的生存期“a”有效。。。
-->src/vague/scope.rs:9:6
|
9 | impl{
| ^^
=注意:…因此表达式是可赋值的:
预期标准::选项::选项>
找到std::option::option>{
但这意味着引用的有效期不够长,因此我无法将其放入结构或任何其他类型的存储中,这些存储将超出调用lookup
的范围。另一种解决方案是:
pub fn lookup(&self,symbol:&str)->Option
导致上一个编译器错误,因为函数从中获取实体的唯一位置是哈希映射,哈希映射定义为具有实体选项>{
这意味着lookup
只能调用一次,这显然是一个问题。我以前的理解是错误的,但问题仍然是要求对self
的引用与整个对象具有相同的生存期严重限制了代码,因为我无法从具有任何更短的生命周期,例如,作为函数参数传入的生命周期或在循环中创建的生命周期
我如何着手解决这个问题?是否有某种方法可以解决我现在所拥有的功能,或者我是否需要以完全不同的方式实现我正在寻找的行为?以下是您想要的签名:
pub fn lookup(&self, symbol: &str) -> Option<&'a Entity<'a>>
这段代码是因为它必须:没有编译器可以用来证明它错误的生存期约束,因为foo
的生存期不与sc
的借用相耦合。但是很明显,如果lookup
是按照您第一次尝试的方式实现的,foo
将在drop(sc)之后包含一个悬空指针
,这就是编译器拒绝它的原因
您必须重新设计数据结构,以使查找的给定签名生效。鉴于问题中的代码,目前尚不清楚如何最好地执行此操作,但以下是一些想法:
- 将
范围中的生存期解耦
,以便借用父项
的生存期不同于符号
。然后进行查找
获取和父项自身
,这可能本身不起作用,具体取决于您需要对实体
执行什么操作,但您可能无法使用如果您需要区分不同数据的生命周期,则可以执行此操作
pub struct Scope<'parent, 'sym> {
symbols: HashMap<String, Entity<'sym>>,
parent: Option<&'parent Scope<'parent, 'sym>>,
}
impl<'parent, 'sym> Scope<'parent, 'sym> {
pub fn lookup(&'parent self, symbol: &str) -> Option<&'parent Entity<'sym>> {
/* ... */
}
}
pub结构范围{
符号:HashMap,
}
impl范围{
发布fn查找(&'parent self,symbol:&str)->Option>{
/* ... */
}
}
- 将你的
范围
和/或你的实体
存储在竞技场中。竞技场可以发出比自我
-借用更久的引用,只要它们不超过竞技场数据结构本身。折衷是,在整个竞技场被摧毁之前,竞技场中的任何内容都不会被释放。它不能替代garbage集合
- 使用
Rc
或Arc
存储你的范围和/或你的实体和/或任何包含引用的实体的数据。这是一种完全消除生存期参数的方法,但运行时成本很小
pub struct Scope<'parent, 'sym> {
symbols: HashMap<String, Entity<'sym>>,
parent: Option<&'parent Scope<'parent, 'sym>>,
}
impl<'parent, 'sym> Scope<'parent, 'sym> {
pub fn lookup(&'parent self, symbol: &str) -> Option<&'parent Entity<'sym>> {
/* ... */
}
}