-
Notifications
You must be signed in to change notification settings - Fork 13.5k
add const_leak
and reject interning non-leaked const_allocate
ptrs
#143595
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
base: master
Are you sure you want to change the base?
Conversation
67537c4
to
911c6a6
Compare
I'm really excited about this experiment and the movement on const alloc, so thanks for working on it <3 |
), | ||
}; | ||
|
||
// If an allocation is created in an another const, |
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.
For now we could just error on this. I don't think this should really happen. Either you leaked, then you don't have an owned value anymore, or you didn't, then it got an error
@@ -7,5 +7,6 @@ use std::intrinsics; | |||
|
|||
const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; | |||
//~^ error: mutable pointer in final value of constant | |||
//~| error: encountered `const_allocate` pointer in final value that was not leaked |
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 also need a test that only errors with this error message and looks otherwise benign
size, | ||
align, | ||
interpret::MemoryKind::Machine(MemoryKind::Heap), | ||
interpret::MemoryKind::Machine(MemoryKind::HeapLeaked), |
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.
Do we need a separate memory kind? I think the interner will be happy with anything that didn't get deallocated
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.
Similar to how it interns stack allocations from the trailing expression
This comment has been minimized.
This comment has been minimized.
return Err(()); | ||
}; | ||
|
||
if matches!(kind, MemoryKind::Machine(x) if x.is_const_heap()) { |
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 turn this into an exhaustive match on the base memory kind enum.
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 is this not reusing the may_leak method?
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.
This isn't about leaking though, it's about interning. I don't think it is the same condition as what Miri's leak check needs?
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 intern stack allocations and those are marked as may_leak = false
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 turn this into an exhaustive match on the base memory kind enum.
I agree with this part though -- we should have a list of that we are allowed to intern. So the trait should be called AllowIntern
or so, and it should be defined in intern.rs
as that's the one place it is needed (not machine.rs
).
kind: MemoryKind<M::MemoryKind>, | ||
new_kind: MemoryKind<M::MemoryKind>, | ||
) -> InterpResult<'tcx, Pointer<M::Provenance>> { | ||
self.reallocate_ptr_inner( |
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 does this reallocate? I don't think that is the right semantics. It will be very hard to use this to intern a graph of allocations since you need to mutate the all pointers into the allocation. And it will be impossible to do this in a cyclic graph.
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.
It will be very hard to use this to intern a graph of allocations since you need to mutate the all pointers into the allocation.
True. I originally went with a "just change the original memory kind" approach but got really scared by the following lines:
rust/compiler/rustc_const_eval/src/interpret/memory.rs
Lines 1609 to 1614 in 688ea65
/// The result must be used immediately; it is not allowed to convert | |
/// the returned data back into a `Pointer` and store that in machine state. | |
/// (In fact that's not even possible since `M::ProvenanceExtra` is generic and | |
/// we don't have an operation to turn it back into `M::Provenance`.) | |
#[inline(always)] | |
pub fn ptr_get_alloc_id( |
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.
Hm, I don't see how that comment would conflict with "change the memory kind"?
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 made it so that it now makes the allocation global (tcx
managed).
In terms of naming, I think we said that The original plan I proposed also makes the allocation immutable when it gets marked as global -- basically, this operation should indicate that you are done preparing this allocation and it is ready to be interned. (We actually intern it later as that's easier, but for the API this does not matter.) |
aa4e8a9
to
a1ef719
Compare
alloc.mutability = Mutability::Not; | ||
let alloc = self.tcx.mk_const_alloc(alloc); | ||
self.tcx.set_alloc_id_memory(alloc_id, alloc); | ||
interp_ok(()) |
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.
This risks breaking key invariants like "tcx-managed allocations do not have any dangling pointers". So as nice as this is I think it won't work.
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 pretty sure both ptr_get_alloc_id
and self.memory.alloc_map.remove(&alloc_id)
calls above ensure that this allocation is valid, unless you mean that the allocation itself could contain values that are dangling pointers to other stuff?
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.
Yes that's what I mean.
a1ef719
to
575f024
Compare
575f024
to
b1cc426
Compare
Implements as discussed on Zulip: #t-compiler/const-eval > const heap
r? @rust-lang/wg-const-eval
Fixes #129233