-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How should const generics with references work around pointer identity and padding? #120961
Comments
We could encode relocations to statics as a separate valtree variant, but I'm not sure how we can handle offsets into statics properly. I also am not sure how weird things get if we do make references to statics ignore what's behind the reference and use the identity of the static instead. |
Depends on what you call "weird". ;) static S1: i32 = &42;
static S2: i32 = &42;
const C1: &i32 = &S1;
const C2: &i32 = &S2;
|
The variant would have to be some kind of
That would be more consistent with the distinction between |
Actually, stuff gets a bit weirder with promoted from statics. Those would have to be handled like statics, adding a |
Sure, but it would mean that |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
FWIW I think this is not just about pointer identity, it is in general about all aspects of the const that are lost in valtree conversion. So besides pointer identity this also affects padding, where passing a const as a const generic will reset its padding -- which makes sense for the by-value part of the const (copying a value does not copy the padding), but is somewhat odd for the part of the const that lives behind a reference (where usually padding is guaranteed to be preserved). Here is an example of that. So I am in general not convinced that passing constants involving references as generics is coherent. (A similar example could be constructed showing that provenance is lost in the conversion, if an |
The fact that If we were to go down the path of "const generics should not re-serialize data behind a references" then it seems like this is effectively representing references as pointing to arbitrary bytes. As far as I know this is accurate to how references are actually thought about by the opsem people (@RalfJung is that right?). Currently we forbid So all in all I guess we have the options of:
@RalfJung do you have thoughts on whether it is even physically possible for us to be able to track provenance in Regardless of that I think what I would like to do here is the following:
|
It's also worth mentioning that if we support references in const parameters' types then we need some way of mangling them. |
The main concern isn't really about provenance, it's about the answer to
Yeah, in the opsem a reference is the same as a raw pointer -- it is an (absolute) address and provenance.
Yeah, sounds right.
Even representing the "arbitrary bytes" of the pointee of a reference does not suffice, since it can still change what
Yes that sounds good to me. |
I didn't meant to auto close this... still an issue for |
Interesting quirk: #![feature(adt_const_params, unsized_const_params, const_refs_to_static)]
#![allow(incomplete_features)]
use std::marker::{ConstParamTy_, UnsizedConstParamTy};
static FOO: &'static Foo = unsafe { const { &std::mem::transmute::<[u8; 4], Foo>([1, 0, 1, 0]) } };
static BAR: &'static Foo = unsafe { const { &std::mem::transmute::<[u8; 4], Foo>([1, 1, 1, 0]) } };
#[repr(C)]
#[derive(Debug, UnsizedConstParamTy, Eq, PartialEq)]
struct Foo(u8, u16);
impl ConstParamTy_ for Foo {}
fn erase<const S1: &'static Foo, const S2: &'static Foo>() {
assert!(std::ptr::eq(S1, S2));
}
fn main() {
assert!("{}", !std::ptr::eq(FOO, BAR));
erase::<FOO, BAR>();
} This currently runs just fine, erasing padding means that the Valtree's for On a related note the following currently runs fine even though maybe it shouldn't since we aren't trying to track addresses of references: #![feature(adt_const_params, unsized_const_params, const_refs_to_static)]
#![allow(incomplete_features)]
static FOO: &'static u32 = &10;
fn erase<const S1: &'static u32, const S2: &'static u32>() {
assert!(std::ptr::eq(S1, S2));
}
fn main() {
erase::<FOO, FOO>();
} |
Const generics currently completely deconstruct the value into a valtree and then reconstruct it, which destroys pointer identity. As long as this is just about purely immutable
const
values we might be able to argue that they "don't have pointer identity" (though it is entirely unclear to me what exactly that should mean). But if consts can point to statics, that doesn't really work any more.Example:
Arguably this should print, but currently it does not.
Cc #95174, #119618
Similarly, this example demonstrates that padding is lost when passing an
&(u8, u16)
as a const generic, which is not how passing a reference usually behaves:The text was updated successfully, but these errors were encountered: