当涉及到生命周期时,我是否遗漏了什么?

3

我刚开始学习Rust,之前主要使用Java和JavaScript,所以请容忍我,因为我的生命周期理解显然还有所欠缺。

fn main() {
    struct Appearance<'a> {
        identity:       &'a u64, 
        role:           &'a str
    };
    impl<'a> PartialEq for Appearance<'a> {
        fn eq(&self, other: &Appearance) -> bool {
            self.identity == other.identity && self.role == other.role
        }
    };
    let thing = 42u64;
    let hair_color = "hair color";
    let appearance = Appearance { 
        identity: &thing, 
        role: &hair_color 
    };
    let another_thing = 43u64;    
    let other_appearance = Appearance { 
        identity: &another_thing, 
        role: &hair_color 
    };
    println!("{}", appearance == other_appearance);
}

当编译器到达other_appearance时,我遇到了编译错误,告诉我another_thing没有足够长的生命周期。然而,如果我省略创建other_appearance,程序就可以编译和运行正常。为什么会出现这个错误?

2个回答

6
PartialEq特质有一个类型参数,指定右侧的类型。由于您没有指定它,它默认为左侧相同的类型。这意味着两侧被假定具有相同的生命周期。 这会导致错误,因为another_thingappearance之前被删除,但是other_appearance(其持有对another_thing的引用)被假定具有与appearance相同的生命周期。
您可以通过在右侧使用不同的生命周期来解决此问题:
impl<'a, 'b> PartialEq<Appearance<'b>> for Appearance<'a> {
    fn eq(&self, other: &Appearance<'b>) -> bool {
        self.identity == other.identity && self.role == other.role
    }
};

这实际上很有趣,因为由#[derive(PartialEq)]创建的实例与OP的问题相同。 - Peter Hall
顺便提一下,由于值的丢弃顺序与它们声明的顺序相反,您也可以通过交换顺序来修复此问题,即使用 other_appearance == appearance 而不是 appearance == other_appearance。是的,Rust 有一些缺陷... - Peter Hall
谢谢!即使我在概念上理解了你说的内容,我还需要深入研究语法 :) - Lars Rönnbäck

1
这似乎是寿命推断/方差与==语法糖结合时的问题 - 请注意,将比较替换为PartialEq :: eq(&appearance,&other_appearance)可行。我不知道这是否是已知的错误。

奇怪。这一定是一个bug。尤其令人惊讶的是,当你使用#[derive(PartialEq)]时,行为与OP相同,这让我想知道为什么之前没有被发现。 - Peter Hall
我偶然发现了这个问题,很好奇;这个问题的代码在 Rust 1.33.0 版本中可以编译。一些搜索结果表明,这是通过此提交进行修复的:https://github.com/rust-lang/rust/commit/1a7fb7dc78439a704f024609ce3dc0beb1386552,该提交是为了解决此 SO 问题中描述的问题:https://stackoverflow.com/questions/46857955/why-does-this-result-of-a-binary-operator-need-an-appropriate-lifetime。 - carols10cents

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接