Skip to content

Commit 699b53d

Browse files
[WIP] Attempt to fix borrowck
1 parent d6f43a4 commit 699b53d

File tree

4 files changed

+87
-68
lines changed

4 files changed

+87
-68
lines changed

src/librustc_borrowck/borrowck/mir/dataflow/mod.rs

+9-27
Original file line numberDiff line numberDiff line change
@@ -433,31 +433,12 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
433433
changed: &mut bool,
434434
(bb, bb_data): (mir::Block, &mir::BlockData))
435435
{
436-
match bb_data.terminator().kind {
437-
mir::TerminatorKind::Return |
438-
mir::TerminatorKind::Resume |
439-
mir::TerminatorKind::Unreachable => {}
440-
mir::TerminatorKind::Goto { ref target } |
441-
mir::TerminatorKind::Drop { ref target, location: _, unwind: None } |
442-
mir::TerminatorKind::DropAndReplace {
443-
ref target, value: _, location: _, unwind: None
444-
} => {
445-
self.propagate_bits_into_entry_set_for(in_out, changed, target);
446-
}
447-
mir::TerminatorKind::Drop { ref target, location: _, unwind: Some(ref unwind) } |
448-
mir::TerminatorKind::DropAndReplace {
449-
ref target, value: _, location: _, unwind: Some(ref unwind)
450-
} => {
451-
self.propagate_bits_into_entry_set_for(in_out, changed, target);
452-
self.propagate_bits_into_entry_set_for(in_out, changed, unwind);
453-
}
454-
mir::TerminatorKind::SwitchInt { ref targets, .. } => {
455-
for target in targets {
456-
self.propagate_bits_into_entry_set_for(in_out, changed, target);
457-
}
458-
}
436+
for succ in self.mir.successors_for(bb).iter() {
437+
debug!("successor for {:?}: {:?}", bb, succ);
438+
self.propagate_bits_into_entry_set_for(in_out, changed, succ);
459439
}
460440

441+
let mut seen_call = false;
461442
for stmt in bb_data.statements.iter() {
462443
match stmt.kind {
463444
mir::StatementKind::Assign(..) |
@@ -467,12 +448,13 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
467448
mir::StatementKind::InlineAsm { .. } |
468449
mir::StatementKind::Assert { .. } |
469450
mir::StatementKind::Nop => {},
470-
mir::StatementKind::Call { ref cleanup, ref destination, func: _, args: _ } => {
471-
if let Some(ref unwind) = *cleanup {
472-
self.propagate_bits_into_entry_set_for(in_out, changed, unwind);
473-
}
451+
mir::StatementKind::Call { ref destination, .. } => {
474452
// N.B.: This must be done *last*, after all other
475453
// propagation, as documented in comment above.
454+
// XXX: Do this after all other calls?
455+
debug!("bck: {:?}: looking at call {:?} in {:?}", bb, stmt, bb_data.statements);
456+
assert!(seen_call == false);
457+
seen_call = true;
476458
self.flow_state.operator.propagate_call_return(in_out, bb, destination);
477459
}
478460
}

src/librustc_borrowck/borrowck/mir/elaborate_drops.rs

+15-14
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
548548
allow_initializations = false;
549549
}
550550
_ => {
551-
assert!(!self.patch.is_patched(bb), "kind: {:?}",
552-
data.terminator().kind);
551+
assert!(!self.patch.is_patched(bb), "kind: {:?}, source: {:?}, {:?}; bbdata: {:?}",
552+
data.terminator().kind, data.terminator().source_info,
553+
bb, data);
553554
}
554555
}
555556
}
@@ -558,18 +559,18 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
558559
// so mark the return as initialized *before* the
559560
// call.
560561
// XXX:
561-
//if i < data.statements.len() {
562-
// if let StatementKind::Call {
563-
// destination: ref lv, cleanup: None, ..
564-
// } = data.statements[i].kind {
565-
// let loc = Location { block: bb, statement_index: i };
566-
// let path = self.move_data().rev_lookup.find(lv);
567-
// on_lookup_result_bits(
568-
// self.tcx, self.mir, self.move_data(), path,
569-
// |child| self.set_drop_flag(loc, child, DropFlagState::Present)
570-
// );
571-
// }
572-
//}
562+
if i < data.statements.len() {
563+
if let StatementKind::Call {
564+
destination: ref lv, cleanup: None, ..
565+
} = data.statements[i].kind {
566+
let loc = Location { block: bb, statement_index: i };
567+
let path = self.move_data().rev_lookup.find(lv);
568+
on_lookup_result_bits(
569+
self.tcx, self.mir, self.move_data(), path,
570+
|child| self.set_drop_flag(loc, child, DropFlagState::Present)
571+
);
572+
}
573+
}
573574

574575
let loc = Location { block: bb, statement_index: i };
575576
super::drop_flag_effects_for_location(

src/librustc_mir/transform/add_call_guards.rs

+61-27
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use rustc::ty::TyCtxt;
1212
use rustc::mir::*;
1313
use rustc::mir::transform::{MirPass, MirSource, Pass};
14-
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
14+
use rustc_data_structures::indexed_vec::Idx;
1515

1616
pub struct AddCallGuards;
1717

@@ -42,40 +42,74 @@ impl<'tcx> MirPass<'tcx> for AddCallGuards {
4242
}
4343

4444
pub fn add_call_guards(mir: &mut Mir) {
45-
let pred_count: IndexVec<_, _> =
46-
mir.predecessors().iter().map(|ps| ps.len()).collect();
47-
4845
// We need a place to store the new blocks generated
4946
let mut new_blocks = Vec::new();
5047

5148
let cur_len = mir.basic_blocks().len();
5249

5350
for block in mir.basic_blocks_mut() {
54-
match block.terminator {
55-
Some(Terminator {
56-
kind: TerminatorKind::Call {
57-
destination: Some((_, ref mut destination)),
58-
cleanup: Some(_),
59-
..
60-
}, source_info
61-
}) if pred_count[*destination] > 1 => {
62-
// It's a critical edge, break it
63-
let call_guard = BlockData {
64-
statements: vec![],
65-
is_cleanup: block.is_cleanup,
66-
terminator: Some(Terminator {
67-
source_info: source_info,
68-
kind: TerminatorKind::Goto { target: *destination }
69-
})
70-
};
71-
72-
// Get the index it will be when inserted into the MIR
73-
let idx = cur_len + new_blocks.len();
74-
new_blocks.push(call_guard);
75-
*destination = Block::new(idx);
51+
// Call statement indices, since the last call.
52+
let mut calls = Vec::new();
53+
// Iterate in reverse to allow draining from the end of statements, not the middle
54+
for i in (0..block.statements.len()).rev() {
55+
if let StatementKind::Call { .. } = block.statements[i].kind {
56+
calls.push(i);
7657
}
77-
_ => {}
7858
}
59+
60+
let first_new_block_idx = cur_len + new_blocks.len();
61+
let mut new_blocks_iter = Vec::new();
62+
63+
debug!("original statements = {:#?}", block.statements);
64+
65+
let mut is_first = true;
66+
67+
for &el in calls.iter() {
68+
let after_call = block.statements.split_off(el + 1);
69+
70+
let next_block_idx = first_new_block_idx + new_blocks_iter.len();
71+
let terminator = if is_first {
72+
block.terminator.take().expect("invalid terminator state")
73+
} else {
74+
Terminator {
75+
source_info: after_call[0].source_info,
76+
kind: TerminatorKind::Goto { target: Block::new(next_block_idx - 1) }
77+
}
78+
};
79+
80+
debug!("cg: statements = {:?}", after_call);
81+
let call_guard = BlockData {
82+
statements: after_call,
83+
is_cleanup: block.is_cleanup,
84+
terminator: Some(terminator)
85+
};
86+
87+
new_blocks_iter.push(call_guard);
88+
is_first = false;
89+
}
90+
91+
debug!("after blocks = {:#?}", new_blocks_iter);
92+
93+
for bb_data in &new_blocks_iter {
94+
let c = bb_data.statements.iter().filter(|stmt| {
95+
match stmt.kind {
96+
StatementKind::Call { .. } => true,
97+
_ => false,
98+
}
99+
}).count();
100+
assert!(c <= 1, "{} calls in {:?}", c, bb_data);
101+
}
102+
103+
if !new_blocks_iter.is_empty() {
104+
block.terminator = Some(Terminator {
105+
source_info: new_blocks_iter[0].terminator().source_info,
106+
kind: TerminatorKind::Goto {
107+
target: Block::new(first_new_block_idx + new_blocks_iter.len() - 1)
108+
}
109+
});
110+
}
111+
112+
new_blocks.extend(new_blocks_iter);
79113
}
80114

81115
debug!("Broke {} N edges", new_blocks.len());

src/librustc_mir/util/patch.rs

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ impl<'tcx> MirPatch<'tcx> {
6666
})});
6767
result.resume_block = resume_block;
6868
if let Some(resume_stmt_block) = resume_stmt_block {
69+
debug!("MirPatch: patching resume_stmt_block, statements: {:?}",
70+
mir.basic_blocks()[resume_stmt_block].statements);
6971
result.patch_terminator(resume_stmt_block, TerminatorKind::Goto {
7072
target: resume_block
7173
});

0 commit comments

Comments
 (0)