Address code review comments
1. Add test case for partial drops 2. Simplify code in `propagate_to_fixpoint` and remove most clones 3. Clean up PostOrderIndex creation
This commit is contained in:
parent
006f547162
commit
30e1b1e92e
2 changed files with 44 additions and 23 deletions
|
@ -34,13 +34,13 @@ use crate::expr_use_visitor;
|
||||||
/// record the parent expression, which is the point where the drop actually takes place.
|
/// record the parent expression, which is the point where the drop actually takes place.
|
||||||
pub struct ExprUseDelegate<'tcx> {
|
pub struct ExprUseDelegate<'tcx> {
|
||||||
hir: Map<'tcx>,
|
hir: Map<'tcx>,
|
||||||
/// Records the point at which an expression or local variable is dropped.
|
/// Records the variables/expressions that are dropped by a given expression.
|
||||||
///
|
///
|
||||||
/// The key is the hir-id of the expression, and the value is a set or hir-ids for variables
|
/// The key is the hir-id of the expression, and the value is a set or hir-ids for variables
|
||||||
/// or values that are consumed by that expression.
|
/// or values that are consumed by that expression.
|
||||||
///
|
///
|
||||||
/// Note that this set excludes "partial drops" -- for example, a statement like `drop(x.y)` is
|
/// Note that this set excludes "partial drops" -- for example, a statement like `drop(x.y)` is
|
||||||
/// not considered a drop of `x`.
|
/// not considered a drop of `x`, although it would be a drop of `x.y`.
|
||||||
consumed_places: HirIdMap<HirIdSet>,
|
consumed_places: HirIdMap<HirIdSet>,
|
||||||
/// A set of hir-ids of values or variables that are borrowed at some point within the body.
|
/// A set of hir-ids of values or variables that are borrowed at some point within the body.
|
||||||
borrowed_places: HirIdSet,
|
borrowed_places: HirIdSet,
|
||||||
|
@ -437,29 +437,29 @@ impl DropRanges {
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
for id in self.nodes.indices() {
|
for id in self.nodes.indices() {
|
||||||
let old_state = self.nodes[id].drop_state.clone();
|
let old_state = self.nodes[id].drop_state.clone();
|
||||||
if preds[id].len() != 0 {
|
let mut new_state = if id.index() == 0 {
|
||||||
self.nodes[id].drop_state = self.nodes[preds[id][0]].drop_state.clone();
|
BitSet::new_empty(self.num_values())
|
||||||
for pred in &preds[id][1..] {
|
|
||||||
let state = self.nodes[*pred].drop_state.clone();
|
|
||||||
self.nodes[id].drop_state.intersect(&state);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.nodes[id].drop_state = if id.index() == 0 {
|
// If we are not the start node and we have no predecessors, treat
|
||||||
BitSet::new_empty(self.num_values())
|
// everything as dropped because there's no way to get here anyway.
|
||||||
} else {
|
BitSet::new_filled(self.num_values())
|
||||||
// If we are not the start node and we have no predecessors, treat
|
|
||||||
// everything as dropped because there's no way to get here anyway.
|
|
||||||
BitSet::new_filled(self.num_values())
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
for drop in &self.nodes[id].drops.clone() {
|
|
||||||
self.nodes[id].drop_state.insert(*drop);
|
for pred in &preds[id] {
|
||||||
}
|
let state = &self.nodes[*pred].drop_state;
|
||||||
for reinit in &self.nodes[id].reinits.clone() {
|
new_state.intersect(state);
|
||||||
self.nodes[id].drop_state.remove(*reinit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
changed |= old_state != self.nodes[id].drop_state;
|
for drop in &self.nodes[id].drops {
|
||||||
|
new_state.insert(*drop);
|
||||||
|
}
|
||||||
|
|
||||||
|
for reinit in &self.nodes[id].reinits {
|
||||||
|
new_state.remove(*reinit);
|
||||||
|
}
|
||||||
|
|
||||||
|
changed |= old_state != new_state;
|
||||||
|
self.nodes[id].drop_state = new_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
changed
|
changed
|
||||||
|
@ -476,7 +476,7 @@ impl DropRanges {
|
||||||
let mut preds = IndexVec::from_fn_n(|_| vec![], self.nodes.len());
|
let mut preds = IndexVec::from_fn_n(|_| vec![], self.nodes.len());
|
||||||
for (id, node) in self.nodes.iter_enumerated() {
|
for (id, node) in self.nodes.iter_enumerated() {
|
||||||
if node.successors.len() == 0 && id.index() != self.nodes.len() - 1 {
|
if node.successors.len() == 0 && id.index() != self.nodes.len() - 1 {
|
||||||
preds[<_>::from(id.index() + 1)].push(id);
|
preds[id + 1].push(id);
|
||||||
} else {
|
} else {
|
||||||
for succ in &node.successors {
|
for succ in &node.successors {
|
||||||
preds[*succ].push(id);
|
preds[*succ].push(id);
|
||||||
|
@ -501,7 +501,7 @@ impl<'a> dot::GraphWalk<'a> for DropRanges {
|
||||||
.iter_enumerated()
|
.iter_enumerated()
|
||||||
.flat_map(|(i, node)| {
|
.flat_map(|(i, node)| {
|
||||||
if node.successors.len() == 0 {
|
if node.successors.len() == 0 {
|
||||||
vec![(i, PostOrderId::from_usize(i.index() + 1))]
|
vec![(i, i + 1)]
|
||||||
} else {
|
} else {
|
||||||
node.successors.iter().map(move |&s| (i, s)).collect()
|
node.successors.iter().map(move |&s| (i, s)).collect()
|
||||||
}
|
}
|
||||||
|
|
21
src/test/ui/generator/partial-drop.rs
Normal file
21
src/test/ui/generator/partial-drop.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(negative_impls, generators)]
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
impl !Send for Foo {}
|
||||||
|
|
||||||
|
struct Bar {
|
||||||
|
foo: Foo,
|
||||||
|
x: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_send(|| {
|
||||||
|
let guard = Bar { foo: Foo, x: 42 };
|
||||||
|
drop(guard.foo);
|
||||||
|
yield;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_send<T: Send>(_: T) {}
|
Loading…
Add table
Add a link
Reference in a new issue