-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Drop Tracking: Implement fake_read
callback
#96923
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
Changes from 4 commits
125326e
5ba2e09
36c4c1e
6d6be5f
bf21a81
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,38 +77,8 @@ impl<'tcx> ExprUseDelegate<'tcx> { | |
} | ||
self.places.consumed.get_mut(&consumer).map(|places| places.insert(target)); | ||
} | ||
} | ||
|
||
impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> { | ||
fn consume( | ||
&mut self, | ||
place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>, | ||
diag_expr_id: HirId, | ||
) { | ||
let parent = match self.tcx.hir().find_parent_node(place_with_id.hir_id) { | ||
Some(parent) => parent, | ||
None => place_with_id.hir_id, | ||
}; | ||
debug!( | ||
"consume {:?}; diag_expr_id={:?}, using parent {:?}", | ||
place_with_id, diag_expr_id, parent | ||
); | ||
place_with_id | ||
.try_into() | ||
.map_or((), |tracked_value| self.mark_consumed(parent, tracked_value)); | ||
} | ||
|
||
fn borrow( | ||
&mut self, | ||
place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>, | ||
diag_expr_id: HirId, | ||
bk: rustc_middle::ty::BorrowKind, | ||
) { | ||
debug!( | ||
"borrow: place_with_id = {place_with_id:?}, diag_expr_id={diag_expr_id:?}, \ | ||
borrow_kind={bk:?}" | ||
); | ||
|
||
fn borrow_place(&mut self, place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>) { | ||
self.places | ||
.borrowed | ||
.insert(TrackedValue::from_place_with_projections_allowed(place_with_id)); | ||
|
@@ -158,6 +128,40 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> { | |
self.places.borrowed_temporaries.insert(place_with_id.hir_id); | ||
} | ||
} | ||
} | ||
|
||
impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> { | ||
fn consume( | ||
&mut self, | ||
place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>, | ||
diag_expr_id: HirId, | ||
) { | ||
let parent = match self.tcx.hir().find_parent_node(place_with_id.hir_id) { | ||
Some(parent) => parent, | ||
None => place_with_id.hir_id, | ||
}; | ||
debug!( | ||
"consume {:?}; diag_expr_id={:?}, using parent {:?}", | ||
place_with_id, diag_expr_id, parent | ||
); | ||
place_with_id | ||
.try_into() | ||
.map_or((), |tracked_value| self.mark_consumed(parent, tracked_value)); | ||
} | ||
|
||
fn borrow( | ||
&mut self, | ||
place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>, | ||
diag_expr_id: HirId, | ||
bk: rustc_middle::ty::BorrowKind, | ||
) { | ||
debug!( | ||
"borrow: place_with_id = {place_with_id:?}, diag_expr_id={diag_expr_id:?}, \ | ||
borrow_kind={bk:?}" | ||
); | ||
|
||
self.borrow_place(place_with_id); | ||
} | ||
|
||
fn copy( | ||
&mut self, | ||
|
@@ -199,9 +203,16 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> { | |
|
||
fn fake_read( | ||
&mut self, | ||
_place: expr_use_visitor::Place<'tcx>, | ||
_cause: rustc_middle::mir::FakeReadCause, | ||
_diag_expr_id: HirId, | ||
place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>, | ||
cause: rustc_middle::mir::FakeReadCause, | ||
diag_expr_id: HirId, | ||
) { | ||
debug!( | ||
"fake_read place_with_id={place_with_id:?}; cause={cause:?}; diag_expr_id={diag_expr_id:?}" | ||
); | ||
|
||
// fake reads happen in places like the scrutinee of a match expression, so we can treat | ||
// these as a borrow. | ||
self.borrow_place(place_with_id); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm, I'm surprised this would borrow the place and not just "read" it. I guess I have to take a look at where this is invoked. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think a borrow is actually ok, just like with copy -- i.e., we are kind of "transiently borrowing" this to read its value -- the only thing is that we don't necessarily want to consider it a borrowed temporary -- but I am don't see it does any harm if we do so (we might over-approximate a bit). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like your updated comment, and thanks for the review! We don't really have a concept of read here, we just have borrows, so I think treating a read as a borrow makes sense. You borrow it so that you can read from it. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// run-pass | ||
// compile-flags: -Zdrop-tracking | ||
|
||
// Based on addassign-yield.rs, but with drop tracking enabled. Originally we did not implement | ||
// the fake_read callback on ExprUseVisitor which caused this case to break. | ||
|
||
#![feature(generators)] | ||
|
||
fn foo() { | ||
let _y = static || { | ||
let x = &mut 0; | ||
*{ | ||
yield; | ||
x | ||
} += match String::new() { | ||
_ => 0, | ||
}; | ||
}; | ||
|
||
// Please don't ever actually write something like this | ||
let _z = static || { | ||
let x = &mut 0; | ||
*{ | ||
let inner = &mut 1; | ||
*{ | ||
yield (); | ||
inner | ||
} += match String::new() { | ||
_ => 1, | ||
}; | ||
yield; | ||
x | ||
} += match String::new() { | ||
_ => 2, | ||
}; | ||
}; | ||
} | ||
|
||
fn main() { | ||
foo() | ||
} |
Uh oh!
There was an error while loading. Please reload this page.