Skip to content

Commit 4574152

Browse files
committed
Handle more cases with conditionally initialized/dropped values
1 parent 298ca2f commit 4574152

File tree

2 files changed

+89
-3
lines changed

2 files changed

+89
-3
lines changed

compiler/rustc_typeck/src/check/generator_interior.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,8 @@ impl<'tcx> Visitor<'tcx> for DropRangeVisitor<'tcx> {
871871
self.visit_expr(if_true);
872872
true_ranges = self.swap_drop_ranges(true_ranges);
873873

874-
false_ranges = self.swap_drop_ranges(false_ranges);
874+
false_ranges =
875+
self.swap_drop_ranges(trim_drop_ranges(&false_ranges, self.expr_count));
875876
self.visit_expr(if_false);
876877
false_ranges = self.swap_drop_ranges(false_ranges);
877878

@@ -908,6 +909,31 @@ impl<'tcx> Visitor<'tcx> for DropRangeVisitor<'tcx> {
908909
let body_drop_ranges = self.swap_drop_ranges(old_drop_ranges);
909910
self.merge_drop_ranges_at(body_drop_ranges, join_point);
910911
}
912+
ExprKind::Match(scrutinee, arms, ..) => {
913+
self.visit_expr(scrutinee);
914+
915+
let forked_ranges = self.fork_drop_ranges();
916+
let arm_drops = arms
917+
.iter()
918+
.map(|Arm { hir_id, pat, body, guard, .. }| {
919+
debug!("match arm {:?} starts at {}", hir_id, self.expr_count);
920+
let old_ranges = self
921+
.swap_drop_ranges(trim_drop_ranges(&forked_ranges, self.expr_count));
922+
self.visit_pat(pat);
923+
match guard {
924+
Some(Guard::If(expr)) => self.visit_expr(expr),
925+
Some(Guard::IfLet(pat, expr)) => {
926+
self.visit_pat(pat);
927+
self.visit_expr(expr);
928+
}
929+
None => (),
930+
}
931+
self.visit_expr(body);
932+
self.swap_drop_ranges(old_ranges)
933+
})
934+
.collect::<Vec<_>>();
935+
arm_drops.into_iter().for_each(|drops| self.merge_drop_ranges(drops));
936+
}
911937
_ => intravisit::walk_expr(self, expr),
912938
}
913939

@@ -926,6 +952,10 @@ impl<'tcx> Visitor<'tcx> for DropRangeVisitor<'tcx> {
926952
}
927953
}
928954

955+
fn trim_drop_ranges(drop_ranges: &HirIdMap<DropRange>, trim_from: usize) -> HirIdMap<DropRange> {
956+
drop_ranges.iter().map(|(k, v)| (*k, v.trimmed(trim_from))).collect()
957+
}
958+
929959
#[derive(Clone, Debug, PartialEq, Eq)]
930960
enum Event {
931961
Drop(usize),
@@ -1058,4 +1088,20 @@ impl DropRange {
10581088
}],
10591089
}
10601090
}
1091+
1092+
fn trimmed(&self, trim_from: usize) -> Self {
1093+
let start = if self.is_dropped_at(trim_from) {
1094+
Event::Drop(trim_from)
1095+
} else {
1096+
Event::Reinit(trim_from)
1097+
};
1098+
1099+
Self {
1100+
events: [start]
1101+
.iter()
1102+
.chain(self.events.iter().skip_while(|event| event.location() <= trim_from))
1103+
.cloned()
1104+
.collect(),
1105+
}
1106+
}
10611107
}

src/test/ui/generator/drop-control-flow.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55
// included in the generator type.
66

77
#![feature(generators, negative_impls)]
8-
98
#![allow(unused_assignments, dead_code)]
109

1110
struct Ptr;
1211
impl<'a> Drop for Ptr {
1312
fn drop(&mut self) {}
1413
}
1514

16-
struct NonSend {}
15+
struct NonSend;
1716
impl !Send for NonSend {}
1817

1918
fn assert_send<T: Send>(_: T) {}
@@ -51,6 +50,29 @@ fn if_let(arg: Option<i32>) {
5150
};
5251
}
5352

53+
fn init_in_if(arg: bool) {
54+
assert_send(|| {
55+
let mut x = NonSend;
56+
drop(x);
57+
if arg {
58+
x = NonSend;
59+
} else {
60+
yield;
61+
}
62+
})
63+
}
64+
65+
fn init_in_match_arm(arg: Option<i32>) {
66+
assert_send(|| {
67+
let mut x = NonSend;
68+
drop(x);
69+
match arg {
70+
Some(_) => x = NonSend,
71+
None => yield,
72+
}
73+
})
74+
}
75+
5476
fn reinit() {
5577
let _ = || {
5678
let mut arr = [Ptr];
@@ -73,9 +95,27 @@ fn loop_uninit() {
7395
};
7496
}
7597

98+
fn nested_loop() {
99+
let _ = || {
100+
let mut arr = [Ptr];
101+
let mut count = 0;
102+
drop(arr);
103+
while count < 3 {
104+
for _ in 0..3 {
105+
yield;
106+
}
107+
arr = [Ptr];
108+
count += 1;
109+
}
110+
};
111+
}
112+
76113
fn main() {
77114
one_armed_if(true);
78115
if_let(Some(41));
116+
init_in_if(true);
117+
init_in_match_arm(Some(41));
79118
reinit();
80119
loop_uninit();
120+
nested_loop();
81121
}

0 commit comments

Comments
 (0)