Why isn't a const for the address of a static allowed?


#1

Currently, Rust has these three characteristics:

  1. The RHS of a const can’t refer to any static in any way.
  2. The initializer of a static array of references cannot use reference-typed named statics but can use reference-typed consts.
  3. A reference-typed const that has an anonymous referent results in a different referent instance in each crate that the const is used in.

This makes it hard to expose named references to statically-allocated objects such that those named references could be used in initializers of static arrays.

I have trouble seeing a good reason for this considering that if the object itself is publicly named, it is legal to take its address in an initializer for a static array. (I’d like to make the exposed names be reference-typed, because they only need to be used in contexts that call for references, and it seems sad to require the user of the API to prefix non-reference-typed names with an ampersand at each point of use.)

Since it seems that #3 above is the result of const being a (visibility-piercing) shorthand for its RHS expression rather than shorthand for the value of the RHS expression where declared, I fail to see why declaring a const as a reference to a static has to be prohibited.

What’s the design rationale for it being prohibited to declare a const for a reference to a static when the name of a static prefixed by & is allowed in places where similarly-typed const with an anonymous referent would be allowed and const seems to be a way to have a visibility-piercing shorthand for an expression? That is, why can’t a const expand to any constant expression that itself would be legal (ignoring visibility)?


#2

I agree that 1 should be allowed and 2 should probably be allowed, too.

What’s the problem you have with 3? It’s only observable through the address. You can’t put Cell types into constants.


#3

The problem with 3 is that I want to observe the address. In Rust, I want to implement == as an address comparison for efficiency. On the C side of FFI, I want == to work both for efficiency and ergonomics.

Additionally, if there are different copies of what’s logically supposed to be a singleton, that’s wasteful in terms of binary size, and I want to avoid that kind of waste, too.


#4

Maybe because, in general, an address of a static is not a compile-constant? (e.g. in position-independent modules)


#5

Yeah fix 1 and 2, and then 3 is no longer a problem.


#6

The short answer is that it’s actually safe, more or less, but the current implementation can’t handle it correctly in many cases. IMO even reading from statics should be safe (you’d see the initial value, with no way to mutate it before program start).

If we were to enable it right now, you’d get LLVM assertions all over the place.

The way forward is to integrate @scott’s miri project into the compiler and have that enforce the language semantics in a more permissive way, at least for global initializers (as desired here).


#7

What’s the time frame for miri integration? Should I file a bug to track this (enable const to refer to an address of a static) specifically to keep the issue on radar?


#8

there are still a few issues left on the miri repository that indicate to me, that miri can’t yet evaluate everything that const eval can.

The relevant issues are