Skip to content

Commit acb7050

Browse files
committed
Split critical edges before borrowck.
1 parent d9d6173 commit acb7050

4 files changed

Lines changed: 72 additions & 12 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3795,6 +3795,7 @@ dependencies = [
37953795
"rustc_trait_selection",
37963796
"rustc_traits",
37973797
"smallvec",
3798+
"thin-vec",
37983799
"tracing",
37993800
]
38003801

compiler/rustc_borrowck/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ rustc_span = { path = "../rustc_span" }
2424
rustc_trait_selection = { path = "../rustc_trait_selection" }
2525
rustc_traits = { path = "../rustc_traits" }
2626
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
27+
thin-vec = "0.2.18"
2728
tracing = "0.1"
2829
# tidy-alphabetical-end

compiler/rustc_borrowck/src/renumber.rs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
use rustc_index::IndexSlice;
1+
use rustc_index::{IndexSlice, IndexVec};
22
use rustc_infer::infer::NllRegionVariableOrigin;
33
use rustc_middle::mir::visit::{MutVisitor, TyContext};
4-
use rustc_middle::mir::{Body, ConstOperand, Location, Promoted};
4+
use rustc_middle::mir::*;
55
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, fold_regions};
66
use rustc_span::Symbol;
7+
use thin_vec::ThinVec;
78
use tracing::{debug, instrument};
89

910
use crate::BorrowckInferCtxt;
@@ -21,12 +22,68 @@ pub(crate) fn renumber_mir<'tcx>(
2122
let mut renumberer = RegionRenumberer { infcx };
2223

2324
for body in promoted.iter_mut() {
25+
split_critical_edges(body);
2426
renumberer.visit_body_preserves_cfg(body);
2527
}
2628

29+
split_critical_edges(body);
2730
renumberer.visit_body_preserves_cfg(body);
2831
}
2932

33+
#[instrument(skip(body), level = "debug")]
34+
fn split_critical_edges(body: &mut Body<'_>) {
35+
let predecessors: IndexVec<BasicBlock, _> =
36+
body.basic_blocks.predecessors().iter().map(|preds| preds.len()).collect();
37+
debug!(?predecessors);
38+
39+
let mut new_blocks = vec![];
40+
for bb in predecessors.indices() {
41+
let term = body.basic_blocks[bb].terminator();
42+
if term.successors().count() <= 1 {
43+
continue;
44+
}
45+
if term.successors().all(|s| predecessors[s] <= 1) {
46+
continue;
47+
}
48+
49+
debug!(
50+
"{bb:?} has critical edges: {:?}",
51+
term.successors().map(|s| (s, predecessors[s])).collect::<Vec<_>>(),
52+
);
53+
54+
let original_succ: Vec<_> = term.successors().collect();
55+
new_blocks.push((bb, original_succ));
56+
}
57+
58+
if new_blocks.is_empty() {
59+
return;
60+
}
61+
62+
debug!(?new_blocks);
63+
let basic_blocks = body.basic_blocks.as_mut();
64+
for (bb, successors) in new_blocks.iter_mut() {
65+
let source_info = basic_blocks[*bb].terminator().source_info;
66+
for target in successors.iter_mut() {
67+
if predecessors[*target] <= 1 {
68+
continue;
69+
}
70+
71+
let is_cleanup = basic_blocks[*target].is_cleanup;
72+
let terminator = Terminator {
73+
source_info,
74+
kind: TerminatorKind::Goto { target: *target },
75+
attributes: ThinVec::new(),
76+
};
77+
*target = basic_blocks.push(BasicBlockData::new(Some(terminator), is_cleanup))
78+
}
79+
}
80+
81+
for (bb, new_succ) in new_blocks {
82+
let mut new_succ = new_succ.into_iter();
83+
basic_blocks[bb].terminator_mut().successors_mut(|succ| *succ = new_succ.next().unwrap());
84+
}
85+
}
86+
3087
// The fields are used only for debugging output in `sccs_info`.
3188
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
3289
pub(crate) enum RegionCtxt {

tests/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,31 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time
22
--> $DIR/borrowck-mut-borrow-linear-errors.rs:10:30
33
|
44
LL | 1 => { addr.push(&mut x); }
5-
| ^^^^^^ second mutable borrow occurs here
6-
LL | 2 => { addr.push(&mut x); }
7-
LL | _ => { addr.push(&mut x); }
8-
| ---- ------ first mutable borrow occurs here
5+
| ---- ^^^^^^ second mutable borrow occurs here
96
| |
107
| first borrow later used here
8+
LL | 2 => { addr.push(&mut x); }
9+
LL | _ => { addr.push(&mut x); }
10+
| ------ first mutable borrow occurs here
1111

1212
error[E0499]: cannot borrow `x` as mutable more than once at a time
1313
--> $DIR/borrowck-mut-borrow-linear-errors.rs:11:30
1414
|
15+
LL | 1 => { addr.push(&mut x); }
16+
| ---- first borrow later used here
1517
LL | 2 => { addr.push(&mut x); }
1618
| ^^^^^^ second mutable borrow occurs here
1719
LL | _ => { addr.push(&mut x); }
18-
| ---- ------ first mutable borrow occurs here
19-
| |
20-
| first borrow later used here
20+
| ------ first mutable borrow occurs here
2121

2222
error[E0499]: cannot borrow `x` as mutable more than once at a time
2323
--> $DIR/borrowck-mut-borrow-linear-errors.rs:12:30
2424
|
25+
LL | 1 => { addr.push(&mut x); }
26+
| ---- first borrow used here, in later iteration of loop
27+
LL | 2 => { addr.push(&mut x); }
2528
LL | _ => { addr.push(&mut x); }
26-
| ---- ^^^^^^ `x` was mutably borrowed here in the previous iteration of the loop
27-
| |
28-
| first borrow used here, in later iteration of loop
29+
| ^^^^^^ `x` was mutably borrowed here in the previous iteration of the loop
2930

3031
error: aborting due to 3 previous errors
3132

0 commit comments

Comments
 (0)