为什么这种相互引用的结构在 Rust 中以指定的生命周期工作?

Why does this mutual referencing structures work in Rust with specified lifetimes?

为什么下面的代码可以编译?

我希望 Rust 编译器告诉我

"borrowed value does not live long enough" when setting the reference (store.barber.set(Some(&barber));

因为理发师的寿命比商店短。

use core::cell::Cell;

struct Shop<'a> {
    barber: Cell<Option<&'a Barber<'a>>>,
}

struct Barber<'a> {
    shop: Cell<Option<&'a Shop<'a>>>,
}

fn main() {
    let shop = Shop { barber: Cell::new(None) };
    {
        let barber = Barber { shop: Cell::new(Some(&shop))};
        shop.barber.set(Some(&barber));
    }
}

Playground

@jmb 的回答证实了我的假设 ()。

代码示例来自here。 但是为什么整个事情有效或者我的误解在哪里我仍然不清楚。

Edit/Enlightenment

我在@Netwaves answer 上评论的代码。

以防 link 不再起作用并澄清问题。

内部范围只是为了让生命周期更清晰。

用法看起来更像这样:

use core::cell::Cell;

struct Shop<'a> {
    barber: Cell<Option<&'a Barber<'a>>>,
    shop_state: Cell<bool>,
}

impl<'a> Shop<'a> {
    fn change_barber_state(&self) {
        self.barber.get().unwrap().change_state();
    }

    fn change_state(&self) {
        self.shop_state.set(!self.shop_state.get());
    }
}

struct Barber<'a> {
    shop: Cell<Option<&'a Shop<'a>>>,
    barber_state: Cell<bool>,
}

impl<'a> Barber<'a> {
    fn change_state(&self) {
        self.barber_state.set(!self.barber_state.get());
    }

    fn change_shop_state(&self) {
        self.shop.get().unwrap().change_state();
    }
}

fn main() {
    let shop = Shop {
        barber: Cell::new(None),
        shop_state: Cell::new(false),
    };

    let barber = Barber {
        shop: Cell::new(Some(&shop)),
        barber_state: Cell::new(false),
    };
    shop.barber.set(Some(&barber));

    println!("{:?}", barber.barber_state);
    println!("{:?}", shop.shop_state);

    shop.change_barber_state();
    barber.change_shop_state();

    println!("{:?}", barber.barber_state);
    println!("{:?}", shop.shop_state);
}

相同范围内的生命周期是否相同?

我认为生命周期也是通过释放资源给出的,这与声明的顺序相反。或者这是否仅在实施 drop 特征时才相关?

Why does this mutual referencing structures work in Rust with specified lifetimes?

简答:

确实如此,因为根据您的代码,它实际上寿命足够长。

说明

问题(没问题)是您在内部范围之后不再使用 shop,因此编译器足够聪明,可以说您的程序没有问题。 但是,如果您添加访问权限,他会开始抱怨,并且有充分的理由:

fn main() {
    let shop = Shop { barber: Cell::new(None) };
    {
        let barber = Barber { shop: Cell::new(Some(&shop))};
        shop.barber.set(Some(&barber));
    }
    shop.barber.get();
}

编译失败:

error[E0597]: `barber` does not live long enough
  --> src/main.rs:15:30
   |
15 |         shop.barber.set(Some(&barber));
   |                              ^^^^^^^ borrowed value does not live long enough
16 |     }
   |     - `barber` dropped here while still borrowed
17 |     shop.barber.get();
   |     ----------------- borrow later used here

Playground

关于问题扩展:

fn main() {
    let shop = Shop {
        barber: Cell::new(None),
        shop_state: Cell::new(false),
    };

    let barber = Barber {
        shop: Cell::new(Some(&shop)),
        barber_state: Cell::new(false),
    };
    shop.barber.set(Some(&barber));

    println!("{:?}", barber.barber_state);
    println!("{:?}", shop.shop_state);

    shop.change_barber_state();
    barber.change_shop_state();

    println!("{:?}", barber.barber_state);
    println!("{:?}", shop.shop_state);
}

Why do you think this should not compile?

很明显,shopbarber 的生命周期相同,直到 main 完成。在这种情况下,free 的顺序无关紧要,因为编译器已经知道其中 none 个将被使用,所以上面的代码是完全安全的。