Change:
Some people were of the opinion that this shouldn't work, but it currently does. : cc
cc
it's just super scary. EDIT: it should not and does not work. If we allowed this, various surprising things can happen, especially around implicit promotion. If you want to store pointers and integers, you can use a raw pointer.
For my own education, can you elaborate on why function pointers are ok? I'd thought that the runtime addresses of things -- including functions -- shouldn't be accessible at const-time since we don't know where they'll live at runtime. Could I make a const array that usize long?
When compiling to LLVM, the real function handle or pointer address is obtained. If you try doing anything weird with pointers at compile time, you will quickly notice that you are not at runtime. For example, you cannot divide such a usize by anything. You can add or subtract integers, because that's just pointer offsetting, but you can't inspect the address in any way. This also means that no, you cannot use this usize for array lengths or enum discriminants. This is due to the fact that miri pointers are not just addresses, but abstract pointers that are in a separate layer from the bytes of normal memory like the one of integers.
Thanks for the explanation. I guess that means that such a couldn't be passed to a const generic either?
The thing is const generics don't know where the usize comes from, so they could try to do something with it that is not allowed if it is just a pointer address. Until monomorphization we can't know if there is an issue. Note that converting a pointer to an usize and back just to be able to put it in const, statics, or use it with const generics, is a real pain. We would be better off in this case with an type, such that I can write and avoid the conversion to usize. For const generics, C++ accepts function pointers at the type level and that works just fine with clang, so I expect to work fine as well.
How would work? is disallowed but and work? that seems very weird and special cased (especially for fn types that involve higher rank lifetimes, as in my example) or is ~= ? then is a double indirection and to use it you need to worry about managing the memory it points to (which contains the )
I haven't thought this through beyond having used the atomic pointers in the C++ standard library: One way to implement this could be where we provide blanket impls for , , , , , , , ... or use some compiler magic to achieve a similar effect...
This is a bit offtopic, but regarding , mentioned at least once the possibility of introducing some new type, to make sugar for . I guess it can't entirely be "sugar", because of existing impls, but at least both could work the same.
Hehe, this is cute. :) And I agree it is working as intended. (Nice that the translation to LLVM actually gets this right, should there be a testcase to make sure it stays that way? :D )
So... other than testing this, all we need is a PR that adds -casts in constants under a feature gate (and makes those casts unsafe in constants and )
I've opened to brainstorm how to either add an type or retrofit to support items.
These kind of operations are now unsafe in contexts (impl PR: )
So do we have a test that you cannot use such usize as array length? :D
hmm... apparently not... Test-instructions: (via the feature gate) to turn various kinds of references and function pointers into these expressions in array length, repeat lengths and enum discriminant initializers (e.g. ) Note: Do not use items, everything needs to be inline in the use site to be properly tested
this is no longer allowed by any means:
Yes that is intended. This issue is for adding a regression test testing what happens when you use a pointer casted to a usize in an array length.

Discussion:
<ins> #![feature(const_raw_ptr_to_usize_cast)] const BAR: *mut () = ((|| 3) as fn() -> i32) as *mut (); pub const FOO: usize = unsafe { BAR as usize }; //~^ ERROR it is undefined behavior to use this value fn main() {} </ins>

<ins> error[E0080]: it is undefined behavior to use this value --> $DIR/issue-51559.rs:4:1 | LL | pub const FOO: usize = unsafe { BAR as usize }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error: aborting due to previous error For more information about this error, try `rustc --explain E0080`. </ins>