Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3bcda48

Browse files
committedFeb 9, 2018
Auto merge of #47802 - bobtwinkles:loop_false_edge, r=nikomatsakis
[NLL] Add false edges out of infinite loops Resolves #46036 by adding a `cleanup` member to the `FalseEdges` terminator kind. There's also a small doc fix to one of the other comments in `into.rs` which I can pull out in to another PR if desired =) This PR should pass CI but the test suite has been relatively unstable on my system so I'm not 100% sure. r? @nikomatsakis
2 parents 02537fb + 85dfa9d commit 3bcda48

File tree

29 files changed

+261
-74
lines changed

29 files changed

+261
-74
lines changed
 

‎src/librustc/ich/impls_mir.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ for mir::TerminatorKind<'gcx> {
219219
target.hash_stable(hcx, hasher);
220220
}
221221
}
222+
mir::TerminatorKind::FalseUnwind { ref real_target, ref unwind } => {
223+
real_target.hash_stable(hcx, hasher);
224+
unwind.hash_stable(hcx, hasher);
225+
}
222226
}
223227
}
224228
}

‎src/librustc/mir/mod.rs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -816,9 +816,28 @@ pub enum TerminatorKind<'tcx> {
816816
/// Indicates the end of the dropping of a generator
817817
GeneratorDrop,
818818

819+
/// A block where control flow only ever takes one real path, but borrowck
820+
/// needs to be more conservative.
819821
FalseEdges {
822+
/// The target normal control flow will take
820823
real_target: BasicBlock,
821-
imaginary_targets: Vec<BasicBlock>
824+
/// The list of blocks control flow could conceptually take, but won't
825+
/// in practice
826+
imaginary_targets: Vec<BasicBlock>,
827+
},
828+
/// A terminator for blocks that only take one path in reality, but where we
829+
/// reserve the right to unwind in borrowck, even if it won't happen in practice.
830+
/// This can arise in infinite loops with no function calls for example.
831+
FalseUnwind {
832+
/// The target normal control flow will take
833+
real_target: BasicBlock,
834+
/// The imaginary cleanup block link. This particular path will never be taken
835+
/// in practice, but in order to avoid fragility we want to always
836+
/// consider it in borrowck. We don't want to accept programs which
837+
/// pass borrowck only when panic=abort or some assertions are disabled
838+
/// due to release vs. debug mode builds. This needs to be an Option because
839+
/// of the remove_noop_landing_pads and no_landing_pads passes
840+
unwind: Option<BasicBlock>,
822841
},
823842
}
824843

@@ -878,6 +897,8 @@ impl<'tcx> TerminatorKind<'tcx> {
878897
s.extend_from_slice(imaginary_targets);
879898
s.into_cow()
880899
}
900+
FalseUnwind { real_target: t, unwind: Some(u) } => vec![t, u].into_cow(),
901+
FalseUnwind { real_target: ref t, unwind: None } => slice::from_ref(t).into_cow(),
881902
}
882903
}
883904

@@ -910,6 +931,8 @@ impl<'tcx> TerminatorKind<'tcx> {
910931
s.extend(imaginary_targets.iter_mut());
911932
s
912933
}
934+
FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => vec![t, u],
935+
FalseUnwind { ref mut real_target, unwind: None } => vec![real_target],
913936
}
914937
}
915938

@@ -929,7 +952,8 @@ impl<'tcx> TerminatorKind<'tcx> {
929952
TerminatorKind::Call { cleanup: ref mut unwind, .. } |
930953
TerminatorKind::Assert { cleanup: ref mut unwind, .. } |
931954
TerminatorKind::DropAndReplace { ref mut unwind, .. } |
932-
TerminatorKind::Drop { ref mut unwind, .. } => {
955+
TerminatorKind::Drop { ref mut unwind, .. } |
956+
TerminatorKind::FalseUnwind { ref mut unwind, .. } => {
933957
Some(unwind)
934958
}
935959
}
@@ -1058,7 +1082,8 @@ impl<'tcx> TerminatorKind<'tcx> {
10581082

10591083
write!(fmt, ")")
10601084
},
1061-
FalseEdges { .. } => write!(fmt, "falseEdges")
1085+
FalseEdges { .. } => write!(fmt, "falseEdges"),
1086+
FalseUnwind { .. } => write!(fmt, "falseUnwind"),
10621087
}
10631088
}
10641089

@@ -1100,6 +1125,8 @@ impl<'tcx> TerminatorKind<'tcx> {
11001125
l.resize(imaginary_targets.len() + 1, "imaginary".into());
11011126
l
11021127
}
1128+
FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
1129+
FalseUnwind { unwind: None, .. } => vec!["real".into()],
11031130
}
11041131
}
11051132
}
@@ -2202,7 +2229,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
22022229
Return => Return,
22032230
Unreachable => Unreachable,
22042231
FalseEdges { real_target, ref imaginary_targets } =>
2205-
FalseEdges { real_target, imaginary_targets: imaginary_targets.clone() }
2232+
FalseEdges { real_target, imaginary_targets: imaginary_targets.clone() },
2233+
FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
22062234
};
22072235
Terminator {
22082236
source_info: self.source_info,
@@ -2244,7 +2272,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
22442272
Return |
22452273
GeneratorDrop |
22462274
Unreachable |
2247-
FalseEdges { .. } => false
2275+
FalseEdges { .. } |
2276+
FalseUnwind { .. } => false
22482277
}
22492278
}
22502279
}

‎src/librustc/mir/visit.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,15 +495,21 @@ macro_rules! make_mir_visitor {
495495
self.visit_operand(value, source_location);
496496
self.visit_branch(block, resume);
497497
drop.map(|t| self.visit_branch(block, t));
498-
499498
}
500499

501-
TerminatorKind::FalseEdges { real_target, ref imaginary_targets } => {
500+
TerminatorKind::FalseEdges { real_target, ref imaginary_targets} => {
502501
self.visit_branch(block, real_target);
503502
for target in imaginary_targets {
504503
self.visit_branch(block, *target);
505504
}
506505
}
506+
507+
TerminatorKind::FalseUnwind { real_target, unwind } => {
508+
self.visit_branch(block, real_target);
509+
if let Some(unwind) = unwind {
510+
self.visit_branch(block, unwind);
511+
}
512+
}
507513
}
508514
}
509515

‎src/librustc_mir/borrow_check/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,8 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
575575
TerminatorKind::Goto { target: _ }
576576
| TerminatorKind::Abort
577577
| TerminatorKind::Unreachable
578-
| TerminatorKind::FalseEdges { .. } => {
578+
| TerminatorKind::FalseEdges { real_target: _, imaginary_targets: _ }
579+
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {
579580
// no data used, thus irrelevant to borrowck
580581
}
581582
}

‎src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
796796
| TerminatorKind::GeneratorDrop
797797
| TerminatorKind::Unreachable
798798
| TerminatorKind::Drop { .. }
799-
| TerminatorKind::FalseEdges { .. } => {
799+
| TerminatorKind::FalseEdges { .. }
800+
| TerminatorKind::FalseUnwind { .. } => {
800801
// no checks needed for these
801802
}
802803

@@ -1152,6 +1153,18 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
11521153
self.assert_iscleanup(mir, block_data, *target, is_cleanup);
11531154
}
11541155
}
1156+
TerminatorKind::FalseUnwind {
1157+
real_target,
1158+
unwind
1159+
} => {
1160+
self.assert_iscleanup(mir, block_data, real_target, is_cleanup);
1161+
if let Some(unwind) = unwind {
1162+
if is_cleanup {
1163+
span_mirbug!(self, block_data, "cleanup in cleanup block via false unwind");
1164+
}
1165+
self.assert_iscleanup(mir, block_data, unwind, true);
1166+
}
1167+
}
11551168
}
11561169
}
11571170

‎src/librustc_mir/build/expr/into.rs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
104104
// Or:
105105
//
106106
// [block: If(lhs)] -false-> [else_block: If(rhs)] -true-> [true_block]
107-
// | | (false)
108-
// +----------true------------+-------------------> [false_block]
107+
// | (true) | (false)
108+
// [true_block] [false_block]
109109

110110
let (true_block, false_block, mut else_block, join_block) =
111111
(this.cfg.start_new_block(), this.cfg.start_new_block(),
@@ -147,20 +147,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
147147
join_block.unit()
148148
}
149149
ExprKind::Loop { condition: opt_cond_expr, body } => {
150-
// [block] --> [loop_block] ~~> [loop_block_end] -1-> [exit_block]
151-
// ^ |
152-
// | 0
153-
// | |
154-
// | v
155-
// [body_block_end] <~~~ [body_block]
150+
// [block] --> [loop_block] -/eval. cond./-> [loop_block_end] -1-> [exit_block]
151+
// ^ |
152+
// | 0
153+
// | |
154+
// | v
155+
// [body_block_end] <-/eval. body/-- [body_block]
156156
//
157157
// If `opt_cond_expr` is `None`, then the graph is somewhat simplified:
158158
//
159-
// [block] --> [loop_block / body_block ] ~~> [body_block_end] [exit_block]
160-
// ^ |
161-
// | |
162-
// +--------------------------+
163-
//
159+
// [block]
160+
// |
161+
// [loop_block] -> [body_block] -/eval. body/-> [body_block_end]
162+
// | ^ |
163+
// false link | |
164+
// | +-----------------------------------------+
165+
// +-> [diverge_cleanup]
166+
// The false link is required to make sure borrowck considers unwinds through the
167+
// body, even when the exact code in the body cannot unwind
164168

165169
let loop_block = this.cfg.start_new_block();
166170
let exit_block = this.cfg.start_new_block();
@@ -188,7 +192,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
188192
// always `()` anyway
189193
this.cfg.push_assign_unit(exit_block, source_info, destination);
190194
} else {
191-
body_block = loop_block;
195+
body_block = this.cfg.start_new_block();
196+
let diverge_cleanup = this.diverge_cleanup();
197+
this.cfg.terminate(loop_block, source_info,
198+
TerminatorKind::FalseUnwind {
199+
real_target: body_block,
200+
unwind: Some(diverge_cleanup)
201+
})
192202
}
193203

194204
// The “return” value of the loop body must always be an unit. We therefore

‎src/librustc_mir/build/matches/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
728728
TerminatorKind::FalseEdges {
729729
real_target: block,
730730
imaginary_targets:
731-
vec![candidate.next_candidate_pre_binding_block]});
731+
vec![candidate.next_candidate_pre_binding_block],
732+
});
732733

733734
self.bind_matched_candidate(block, candidate.bindings);
734735

@@ -749,7 +750,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
749750
TerminatorKind::FalseEdges {
750751
real_target: otherwise,
751752
imaginary_targets:
752-
vec![candidate.next_candidate_pre_binding_block] });
753+
vec![candidate.next_candidate_pre_binding_block],
754+
});
753755
Some(otherwise)
754756
} else {
755757
self.cfg.terminate(block, candidate_source_info,

‎src/librustc_mir/dataflow/impls/borrows.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
517517
mir::TerminatorKind::Yield {..} |
518518
mir::TerminatorKind::Goto {..} |
519519
mir::TerminatorKind::FalseEdges {..} |
520+
mir::TerminatorKind::FalseUnwind {..} |
520521
mir::TerminatorKind::Unreachable => {}
521522
}
522523
}

‎src/librustc_mir/dataflow/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,14 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
864864
self.propagate_bits_into_entry_set_for(in_out, changed, target);
865865
}
866866
}
867+
mir::TerminatorKind::FalseUnwind { ref real_target, unwind } => {
868+
self.propagate_bits_into_entry_set_for(in_out, changed, real_target);
869+
if let Some(ref unwind) = unwind {
870+
if !self.dead_unwinds.contains(&bb) {
871+
self.propagate_bits_into_entry_set_for(in_out, changed, unwind);
872+
}
873+
}
874+
}
867875
}
868876
}
869877

‎src/librustc_mir/dataflow/move_paths/builder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
346346
TerminatorKind::Abort |
347347
TerminatorKind::GeneratorDrop |
348348
TerminatorKind::FalseEdges { .. } |
349+
TerminatorKind::FalseUnwind { .. } |
349350
TerminatorKind::Unreachable => { }
350351

351352
TerminatorKind::Return => {

‎src/librustc_mir/interpret/terminator/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
165165
Resume => unimplemented!(),
166166
Abort => unimplemented!(),
167167
FalseEdges { .. } => bug!("should have been eliminated by `simplify_branches` mir pass"),
168+
FalseUnwind { .. } => bug!("should have been eliminated by `simplify_branches` mir pass"),
168169
Unreachable => return err!(Unreachable),
169170
}
170171

‎src/librustc_mir/monomorphize/collector.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
636636
mir::TerminatorKind::Assert { .. } => {}
637637
mir::TerminatorKind::GeneratorDrop |
638638
mir::TerminatorKind::Yield { .. } |
639-
mir::TerminatorKind::FalseEdges { .. } => bug!(),
639+
mir::TerminatorKind::FalseEdges { .. } |
640+
mir::TerminatorKind::FalseUnwind { .. } => bug!(),
640641
}
641642

642643
self.super_terminator_kind(block, kind, location);

‎src/librustc_mir/transform/check_unsafety.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
7676
TerminatorKind::Abort |
7777
TerminatorKind::Return |
7878
TerminatorKind::Unreachable |
79-
TerminatorKind::FalseEdges { .. } => {
79+
TerminatorKind::FalseEdges { .. } |
80+
TerminatorKind::FalseUnwind { .. } => {
8081
// safe (at least as emitted during MIR construction)
8182
}
8283

‎src/librustc_mir/transform/inline.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,9 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
813813
*target = self.update_target(*target);
814814
}
815815
}
816+
TerminatorKind::FalseUnwind { real_target: _ , unwind: _ } =>
817+
// see the ordering of passes in the optimized_mir query.
818+
bug!("False unwinds should have been removed before inlining")
816819
}
817820
}
818821

‎src/librustc_mir/transform/qualify_consts.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,8 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
329329
TerminatorKind::GeneratorDrop |
330330
TerminatorKind::Yield { .. } |
331331
TerminatorKind::Unreachable |
332-
TerminatorKind::FalseEdges { .. } => None,
332+
TerminatorKind::FalseEdges { .. } |
333+
TerminatorKind::FalseUnwind { .. } => None,
333334

334335
TerminatorKind::Return => {
335336
// Check for unused values. This usually means

‎src/librustc_mir/transform/remove_noop_landing_pads.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ impl RemoveNoopLandingPads {
7575
TerminatorKind::Goto { .. } |
7676
TerminatorKind::Resume |
7777
TerminatorKind::SwitchInt { .. } |
78-
TerminatorKind::FalseEdges { .. } => {
78+
TerminatorKind::FalseEdges { .. } |
79+
TerminatorKind::FalseUnwind { .. } => {
7980
terminator.successors().iter().all(|succ| {
8081
nop_landing_pads.contains(succ.index())
8182
})

‎src/librustc_mir/transform/simplify_branches.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ impl MirPass for SimplifyBranches {
6464
TerminatorKind::FalseEdges { real_target, .. } => {
6565
TerminatorKind::Goto { target: real_target }
6666
},
67+
TerminatorKind::FalseUnwind { real_target, .. } => {
68+
TerminatorKind::Goto { target: real_target }
69+
},
6770
_ => continue
6871
};
6972
}

‎src/librustc_passes/mir_stats.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
123123
TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop",
124124
TerminatorKind::Yield { .. } => "TerminatorKind::Yield",
125125
TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges",
126+
TerminatorKind::FalseUnwind { .. } => "TerminatorKind::FalseUnwind",
126127
}, kind);
127128
self.super_terminator_kind(block, kind, location);
128129
}

‎src/librustc_trans/mir/analyze.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec<mir::BasicBlock
242242
TerminatorKind::Unreachable |
243243
TerminatorKind::SwitchInt { .. } |
244244
TerminatorKind::Yield { .. } |
245-
TerminatorKind::FalseEdges { .. } => {
245+
TerminatorKind::FalseEdges { .. } |
246+
TerminatorKind::FalseUnwind { .. } => {
246247
/* nothing to do */
247248
}
248249
TerminatorKind::Call { cleanup: unwind, .. } |

‎src/librustc_trans/mir/block.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,8 +608,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
608608
cleanup);
609609
}
610610
mir::TerminatorKind::GeneratorDrop |
611-
mir::TerminatorKind::Yield { .. } |
612-
mir::TerminatorKind::FalseEdges { .. } => bug!("generator ops in trans"),
611+
mir::TerminatorKind::Yield { .. } => bug!("generator ops in trans"),
612+
mir::TerminatorKind::FalseEdges { .. } |
613+
mir::TerminatorKind::FalseUnwind { .. } => bug!("borrowck false edges in trans"),
613614
}
614615
}
615616

‎src/test/compile-fail/issue-46036.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Issue 46036: [NLL] false edges on infinite loops
12+
// Infinite loops should create false edges to the cleanup block.
13+
#![feature(nll)]
14+
15+
struct Foo { x: &'static u32 }
16+
17+
fn foo() {
18+
let a = 3;
19+
let foo = Foo { x: &a }; //~ ERROR E0597
20+
loop { }
21+
}
22+
23+
fn main() { }

‎src/test/incremental/hashes/loop_expressions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ pub fn change_continue_label() {
179179
}
180180

181181
#[cfg(not(cfail1))]
182-
#[rustc_clean(cfg="cfail2", except="HirBody, TypeckTables")]
182+
#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, TypeckTables")]
183183
#[rustc_clean(cfg="cfail3")]
184184
pub fn change_continue_label() {
185185
let mut _x = 0;

‎src/test/mir-opt/end_region_2.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,29 @@ fn main() {
4040
// goto -> bb1;
4141
// }
4242
// bb1: {
43+
// falseUnwind -> [real: bb2, cleanup: bb3];
44+
// }
45+
// bb2: {
4346
// StorageLive(_2);
4447
// _2 = const true;
4548
// StorageLive(_3);
4649
// _3 = &'23_1rs _2;
4750
// StorageLive(_5);
4851
// _5 = _2;
49-
// switchInt(move _5) -> [0u8: bb3, otherwise: bb2];
52+
// switchInt(move _5) -> [0u8: bb5, otherwise: bb4];
5053
// }
51-
// bb2: {
54+
// bb3: {
55+
// ...
56+
// }
57+
// bb4: {
5258
// _0 = ();
5359
// StorageDead(_5);
5460
// EndRegion('23_1rs);
5561
// StorageDead(_3);
5662
// StorageDead(_2);
5763
// return;
5864
// }
59-
// bb3: {
65+
// bb5: {
6066
// _4 = ();
6167
// StorageDead(_5);
6268
// StorageLive(_7);

‎src/test/mir-opt/end_region_3.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,28 @@ fn main() {
4343
// goto -> bb1;
4444
// }
4545
// bb1: {
46+
// falseUnwind -> [real: bb2, cleanup: bb3];
47+
// }
48+
// bb2: {
4649
// _1 = const true;
4750
// StorageLive(_3);
4851
// _3 = &'26_1rs _1;
4952
// StorageLive(_5);
5053
// _5 = _1;
51-
// switchInt(move _5) -> [0u8: bb3, otherwise: bb2];
54+
// switchInt(move _5) -> [0u8: bb5, otherwise: bb4];
5255
// }
53-
// bb2: {
56+
// bb3: {
57+
// ...
58+
// }
59+
// bb4: {
5460
// _0 = ();
5561
// StorageDead(_5);
5662
// EndRegion('26_1rs);
5763
// StorageDead(_3);
5864
// StorageDead(_1);
5965
// return;
6066
// }
61-
// bb3: {
67+
// bb5: {
6268
// _4 = ();
6369
// StorageDead(_5);
6470
// StorageLive(_7);

‎src/test/mir-opt/end_region_9.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,24 @@ fn main() {
5757
// _1 = const false;
5858
// StorageLive(_2);
5959
// _2 = const 3i32;
60-
// StorageLive(_4);
61-
// goto -> bb1;
60+
// falseUnwind -> [real: bb2, cleanup: bb1];
6261
// }
63-
//
6462
// bb1: {
63+
// ...
64+
// }
65+
// bb2: {
66+
// StorageLive(_4);
67+
// goto -> bb3;
68+
// }
69+
// bb3: {
70+
// falseUnwind -> [real: bb4, cleanup: bb1];
71+
// }
72+
// bb4: {
6573
// StorageLive(_7);
6674
// _7 = _1;
67-
// switchInt(move _7) -> [0u8: bb3, otherwise: bb2];
75+
// switchInt(move _7) -> [0u8: bb6, otherwise: bb5];
6876
// }
69-
// bb2: {
77+
// bb5: {
7078
// _0 = ();
7179
// StorageDead(_7);
7280
// EndRegion('33_0rs);
@@ -75,13 +83,13 @@ fn main() {
7583
// StorageDead(_1);
7684
// return;
7785
// }
78-
// bb3: {
86+
// bb6: {
7987
// _4 = &'33_0rs _2;
8088
// _6 = ();
8189
// StorageDead(_7);
8290
// _1 = const true;
8391
// _3 = ();
84-
// goto -> bb1;
92+
// goto -> bb3;
8593
// }
8694
// }
8795
// END rustc.main.SimplifyCfg-qualify-consts.after.mir

‎src/test/mir-opt/end_region_cyclic.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,19 @@ fn query() -> bool { true }
6767
// goto -> bb1;
6868
// }
6969
// bb1: {
70+
// falseUnwind -> [real: bb2, cleanup: bb3];
71+
// }
72+
// bb2: {
7073
// StorageLive(_2);
7174
// StorageLive(_3);
7275
// StorageLive(_4);
7376
// _4 = std::option::Option<&'35_0rs S<'35_0rs>>::None;
74-
// _3 = const <std::cell::Cell<T>>::new(move _4) -> [return: bb3, unwind: bb2];
77+
// _3 = const <std::cell::Cell<T>>::new(move _4) -> [return: bb4, unwind: bb3];
7578
// }
76-
// bb2: {
79+
// bb3: {
7780
// resume;
7881
// }
79-
// bb3: {
82+
// bb4: {
8083
// StorageDead(_4);
8184
// _2 = S<'35_0rs> { r: move _3 };
8285
// StorageDead(_3);
@@ -89,27 +92,27 @@ fn query() -> bool { true }
8992
// _8 = &'35_0rs (*_9);
9093
// _7 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _8,);
9194
// StorageDead(_8);
92-
// _5 = const <std::cell::Cell<T>>::set(move _6, move _7) -> [return: bb4, unwind: bb2];
95+
// _5 = const <std::cell::Cell<T>>::set(move _6, move _7) -> [return: bb5, unwind: bb3];
9396
// }
94-
// bb4: {
97+
// bb5: {
9598
// EndRegion('16s);
9699
// StorageDead(_7);
97100
// StorageDead(_6);
98101
// StorageDead(_9);
99102
// StorageLive(_11);
100-
// _11 = const query() -> [return: bb5, unwind: bb2];
101-
// }
102-
// bb5: {
103-
// switchInt(move _11) -> [0u8: bb7, otherwise: bb6];
103+
// _11 = const query() -> [return: bb6, unwind: bb3];
104104
// }
105105
// bb6: {
106+
// switchInt(move _11) -> [0u8: bb8, otherwise: bb7];
107+
// }
108+
// bb7: {
106109
// _0 = ();
107110
// StorageDead(_11);
108111
// EndRegion('35_0rs);
109112
// StorageDead(_2);
110113
// return;
111114
// }
112-
// bb7: {
115+
// bb8: {
113116
// _10 = ();
114117
// StorageDead(_11);
115118
// StorageLive(_14);
@@ -121,9 +124,9 @@ fn query() -> bool { true }
121124
// _16 = &'35_0rs (*_17);
122125
// _15 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _16,);
123126
// StorageDead(_16);
124-
// _13 = const <std::cell::Cell<T>>::set(move _14, move _15) -> [return: bb8, unwind: bb2];
127+
// _13 = const <std::cell::Cell<T>>::set(move _14, move _15) -> [return: bb9, unwind: bb3];
125128
// }
126-
// bb8: {
129+
// bb9: {
127130
// EndRegion('33s);
128131
// StorageDead(_15);
129132
// StorageDead(_14);

‎src/test/mir-opt/issue-38669.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,30 @@ fn main() {
2525
// bb0: {
2626
// StorageLive(_1);
2727
// _1 = const false;
28-
// goto -> bb1;
28+
// goto -> bb2;
2929
// }
30-
//
3130
// bb1: {
31+
// resume;
32+
// }
33+
// bb2: {
34+
// falseUnwind -> [real: bb3, cleanup: bb1];
35+
// }
36+
// bb3: {
3237
// StorageLive(_4);
3338
// _4 = _1;
34-
// switchInt(move _4) -> [0u8: bb3, otherwise: bb2];
39+
// switchInt(move _4) -> [0u8: bb5, otherwise: bb4];
3540
// }
36-
//
37-
// bb2: {
41+
// bb4: {
3842
// _0 = ();
3943
// StorageDead(_4);
4044
// StorageDead(_1);
4145
// return;
4246
// }
43-
//
44-
// bb3: {
47+
// bb5: {
4548
// _3 = ();
4649
// StorageDead(_4);
4750
// _1 = const true;
4851
// _2 = ();
49-
// goto -> bb1;
52+
// goto -> bb2;
5053
// }
5154
// END rustc.main.SimplifyCfg-initial.after.mir

‎src/test/mir-opt/loop_test.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z identify_regions -Z emit-end-regions
12+
13+
// Tests to make sure we correctly generate falseUnwind edges in loops
14+
15+
fn main() {
16+
// Exit early at runtime. Since only care about the generated MIR
17+
// and not the runtime behavior (which is exercised by other tests)
18+
// we just bail early. Without this the test just loops infinitely.
19+
if true {
20+
return;
21+
}
22+
loop {
23+
let x = 1;
24+
continue;
25+
}
26+
}
27+
28+
// END RUST SOURCE
29+
// START rustc.main.SimplifyCfg-qualify-consts.after.mir
30+
// ...
31+
// bb1: { // The cleanup block
32+
// resume;
33+
// }
34+
// ...
35+
// bb3: { // Entry into the loop
36+
// _1 = ();
37+
// goto -> bb4;
38+
// }
39+
// bb4: { // The loop_block
40+
// falseUnwind -> [real: bb5, cleanup: bb1];
41+
// }
42+
// bb5: { // The loop body (body_block)
43+
// StorageLive(_5);
44+
// _5 = const 1i32;
45+
// StorageDead(_5);
46+
// goto -> bb4;
47+
// }
48+
// ...
49+
// END rustc.main.SimplifyCfg-qualify-consts.after.mir

‎src/test/mir-opt/nll/liveness-drop-intra-block.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@ fn main() {
2525

2626
// END RUST SOURCE
2727
// START rustc.main.nll.0.mir
28-
// | Live variables on entry to bb2: []
29-
// bb2: {
30-
// | Live variables on entry to bb2[0]: []
28+
// | Live variables on entry to bb3: []
29+
// bb3: {
30+
// | Live variables on entry to bb3[0]: []
3131
// _1 = const 55usize;
32-
// | Live variables on entry to bb2[1]: [_1]
32+
// | Live variables on entry to bb3[1]: [_1]
3333
// StorageLive(_3);
34-
// | Live variables on entry to bb2[2]: [_1]
34+
// | Live variables on entry to bb3[2]: [_1]
3535
// StorageLive(_4);
36-
// | Live variables on entry to bb2[3]: [_1]
36+
// | Live variables on entry to bb3[3]: [_1]
3737
// _4 = _1;
38-
// | Live variables on entry to bb2[4]: [_4]
39-
// _3 = const use_x(move _4) -> [return: bb3, unwind: bb1];
38+
// | Live variables on entry to bb3[4]: [_4]
39+
// _3 = const use_x(move _4) -> [return: bb4, unwind: bb1];
4040
// }
4141
// END rustc.main.nll.0.mir

0 commit comments

Comments
 (0)
Please sign in to comment.