Skip to content
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

handle diverging functions forwarding their return place #66827

Merged
merged 2 commits into from
Dec 2, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 23 additions & 15 deletions src/librustc_mir/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,20 +651,28 @@ where
use rustc::mir::PlaceBase;

let mut place_ty = match &place.base {
PlaceBase::Local(mir::RETURN_PLACE) => match self.frame().return_place {
Some(return_place) => {
// We use our layout to verify our assumption; caller will validate
// their layout on return.
PlaceTy {
place: *return_place,
layout: self.layout_of(
self.subst_from_frame_and_normalize_erasing_regions(
self.frame().body.return_ty()
)
)?,
}
PlaceBase::Local(mir::RETURN_PLACE) => {
// `return_place` has the *caller* layout, but we want to use our
// `layout to verify our assumption. The caller will validate
// their layout on return.
PlaceTy {
place: match self.frame().return_place {
Some(p) => *p,
// Even if we don't have a return place, we sometimes need to
// create this place, but any attempt to read from / write to it
// (even a ZST read/write) needs to error, so let us make this
// a NULL place.
//
// FIXME: Ideally we'd make sure that the place projections also
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like just doing a place projection on a null place should error?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Place projections should have inbounds rules, basically. We have an implementation of that in Miri, and these days I am actually not ashamed of it any more. ;)

But I am worried about the perf impact of this and I think it is currently actually impossible to violate the inbounds requirement, so I didn't bother working on moving that into the core engine.

// bail out.
None => Place::null(&*self),
},
layout: self.layout_of(
self.subst_from_frame_and_normalize_erasing_regions(
self.frame().body.return_ty()
)
)?,
}
None => throw_unsup!(InvalidNullPointerUsage),
},
PlaceBase::Local(local) => PlaceTy {
// This works even for dead/uninitialized locals; we check further when writing
Expand Down Expand Up @@ -791,8 +799,8 @@ where
// to handle padding properly, which is only correct if we never look at this data with the
// wrong type.

let ptr = match self.check_mplace_access(dest, None)
.expect("places should be checked on creation")
// Invalid places are a thing: the return place of a diverging function
let ptr = match self.check_mplace_access(dest, None)?
{
Some(ptr) => ptr,
None => return Ok(()), // zero-sized access
Expand Down