Under What Circumstances Does Rust Promote a Value to a 'static Lifetime?

I’m developing a compiler and recently came across something I’m not completely sure about.

example:

enum Foo {
    A,
    B,
}

An AI told me that values like Foo::A can be promoted to a 'static lifetime because they don’t contain any data:

let x: &'static Foo = &Foo::A;

Is this correct? If so, what are the conditions under which Rust performs constant promotion and allows a value to have a 'static reference?

Const promotion is detailed here:

For all intents and purposes, 'static means "this value can live for as long as necessary". A type that owns / captures / holds onto its own state - as is the case for your enum Foo { A, B }, where the only "state" stored is the implicit discriminant of tagged union itself - is implicitly 'static. So is every other "owner" types that fully captures, and is ultimately responsible for cleaning up deallocating the underlying memory at the end of its own "life". Therefore:

struct A; // 'static
struct B<T>(T); // `static *only if* `T` is 'static
struct C<T: 'static, U: 'static> { 
  t: Box<T>, 
  u: Pin<Rc<U>> 
}; // 'static, as per the `'static` bound

Compare that to a struct Ref<'r, T>(&'r T). It is tied to, and is bound by, the lifetime 'r of the reference &T it is holding onto. It is not allowed to live for as long as needed, since the &'r T is only valid for the given lifetime 'r as per the type definition itself. The 'r can be 'static, yet if you want to be able to use it as 'static, you'll have to explicitly handle that case on its own:

pub struct Ref<'r, T>(&'r T);

impl<T: 'static> Ref<'static, T> {
  fn detach(&self) -> Box<&'static T> {
    Box::new(self.0)
  }
}

what is detach supposed to achiever here ? a Boxed reference is almost always useless, and given Ref could be copy simply through a derive, i can't imagine what the use case is supposed to be.

The short explanation is at Destructors - The Rust Reference

For the long explanation, and some gory details, see Promotion rules are surprising and insufficiently documented · Issue #105270 · rust-lang/rust · GitHub and Clean up implicit const promotion behavior · Issue #124328 · rust-lang/rust · GitHub

Just an example for its own sake. I was thinking about calling it "promote" instead of "detach" for a minute, yet decided to backtrack at the last minute as that particular promotion would have very little to do with the OP's own question. Looking back it, I might have answered a completely different question altogether. Others have already covered the compiler specifics well enough, though.

If you're working on a new language, learn from Rust's mistakes here.

Originally lots of stuff magically promoted, and it caused a ton of messiness. We've been slowly and painfully rolling it back for years.

With a time machine, I suspect we'd just remove this and insist that you opt-in to it with a const { … } in places you want it. It's very common that foo(&4) didn't actually want that 4 promoted to mapped-forever-in-the-binary memory, but we do it anyway because we have to.

So if you want it, use const { &Foo::A } or const { &Bar { a: …, b: … } } or whatever, and don't learn the complicated and messy detailed rules.