-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Ensure that statics are always ByRef #50690
Conversation
r? @eddyb (rust_highfive has picked a reviewer for you, use r? to override) |
r? @eddyb |
src/librustc_trans/mir/constant.rs
Outdated
@@ -171,11 +128,11 @@ pub fn trans_static_initializer<'a, 'tcx>( | |||
let param_env = ty::ParamEnv::reveal_all(); | |||
let static_ = cx.tcx.const_eval(param_env.and(cid))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking const_eval
isn't the best, but it's probably an okay compromise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could create a separate query for statics.
@bors r+ |
📌 Commit 89201f3 has been approved by |
This makes |
if layout.is_zst() { | ||
return ty::Const::from_const_value( | ||
tcx, | ||
ConstValue::ByVal(PrimVal::Undef), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is ZST always ByVal(PrimVal::Undef)
in Miri?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. Accessing a zst field of a ByRef will return a ByRef
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then this code should still be here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? Won't we simply get an empty allocation in the ByRef?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each Rust value should only map to one ConstValue
. so a ZST type cannot be both ByVal(PrimVal::Undef)
and ByRef
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that would require us to spray is_zst checks everywhere. Miri already "violates" your assumption left and right.
The current code tries to reduce special cases, only ignoring zst memory reads in Memory, not earlier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait. wouldn't it actually make more sense to try to move to ByRef for zst everywhere? You can't ever have a zst value. They have no values (well one value, but we don't ever read/write it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that would require us to spray is_zst checks everywhere. Miri already "violates" your assumption left and right.
Miri doesn't use ConstValue
. It is not an assumption but an invariant of the ConstValue
type. You just need to check for ZST types when converting to a ConstValue
. Having this invariant for ConstValue is very useful since:
- it reduces memory usage when it is interned
- if you want to check for a specific value, you only need to look at one of it's variants, for example
true
only needs to check forByVal(PrimVal::Bytes(1))
and can ignoreByRef
entirely. There is a fair amount of code which relies on this properly which has to be updated if you want to make static always returnByRef
.
We can get rid of the special case for ZST by making them have a Scalar
ABI so they can be stored in ByVal
instead of ByRef
which would otherwise be required since they have Aggregate
ABI currently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait. wouldn't it actually make more sense to try to move to ByRef for zst everywhere? You can't ever have a zst value. They have no values (well one value, but we don't ever read/write it).
Then we'd have to create allocations for ZST types, which we want to avoid for performance reasons. That is why ConstValue::ByVal
and ConstValue::ByValPair
exist at all.
if let Value::ByValPair(a, b) = val { | ||
ConstValue::ByValPair(a, b) | ||
} else { | ||
bug!("expected ByValPair value, got {:?}", val); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please keep these sanity checks. At least when debug-assertions is on. I really don't trust Miri code to be correct.
@bors r- more sanity checks |
☔ The latest upstream changes (presumably #50710) made this pull request unmergeable. Please resolve the merge conflicts. |
7d96991
to
dd048e9
Compare
☔ The latest upstream changes (presumably #50615) made this pull request unmergeable. Please resolve the merge conflicts. |
src/librustc/mir/interpret/value.rs
Outdated
// Used only for the remaining cases | ||
ByRef(&'tcx Allocation), | ||
/// Used only for the remaining cases. An allocation + offset into the allocation | ||
ByRef(&'tcx Allocation, u64), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use Size
for offsets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
MemoryPointer { alloc_id, offset } | ||
} | ||
|
||
pub(crate) fn wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self { | ||
MemoryPointer::new( | ||
self.alloc_id, | ||
cx.data_layout().wrapping_signed_offset(self.offset, i), | ||
Size::from_bytes(cx.data_layout().wrapping_signed_offset(self.offset.bytes(), i)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would wrapping_signed_offset
not work on a Size
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because SIze
doesn't have a sign. I mean we could create an Offset
type (which would then also be the Output
of impl Sub for Size
)...
@bors r+ |
📌 Commit 7c25aa7 has been approved by |
@bors p=38 |
☀️ Test successful - status-appveyor, status-travis |
Statics aren't values to be used, they are names for memory locations.
r? @eddyb
cc @Zoxc
fixes #50706