Skip to content

Commit 5760bc6

Browse files
authored
Rollup merge of rust-lang#62465 - matthewjasper:never-type-storage, r=pnkfelix
Sometimes generate storage statements for temporaries with type `!` Closes rust-lang#62165 cc rust-lang#42371
2 parents a2cbae8 + 163c059 commit 5760bc6

File tree

4 files changed

+61
-29
lines changed

4 files changed

+61
-29
lines changed

src/librustc_mir/build/expr/as_place.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
7373
let (usize_ty, bool_ty) = (this.hir.usize_ty(), this.hir.bool_ty());
7474

7575
let slice = unpack!(block = this.as_place(block, lhs));
76-
// region_scope=None so place indexes live forever. They are scalars so they
77-
// do not need storage annotations, and they are often copied between
78-
// places.
7976
// Making this a *fresh* temporary also means we do not have to worry about
8077
// the index changing later: Nothing will ever change this temporary.
8178
// The "retagging" transformation (for Stacked Borrows) relies on this.
82-
let idx = unpack!(block = this.as_temp(block, None, index, Mutability::Mut));
79+
let idx = unpack!(block = this.as_temp(
80+
block,
81+
expr.temp_lifetime,
82+
index,
83+
Mutability::Not,
84+
));
8385

8486
// bounds check:
8587
let (len, lt) = (

src/librustc_mir/build/expr/as_temp.rs

+40-25
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use crate::build::{BlockAnd, BlockAndExtension, Builder};
44
use crate::build::scope::DropKind;
55
use crate::hair::*;
6+
use rustc::hir;
67
use rustc::middle::region;
78
use rustc::mir::*;
89

@@ -66,32 +67,46 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
6667
};
6768
let temp_place = &Place::from(temp);
6869

69-
if !expr_ty.is_never() {
70-
this.cfg.push(
71-
block,
72-
Statement {
73-
source_info,
74-
kind: StatementKind::StorageLive(temp),
75-
},
76-
);
77-
78-
// In constants, `temp_lifetime` is `None` for temporaries that live for the
79-
// `'static` lifetime. Thus we do not drop these temporaries and simply leak them.
80-
// This is equivalent to what `let x = &foo();` does in functions. The temporary
81-
// is lifted to their surrounding scope. In a function that means the temporary lives
82-
// until just before the function returns. In constants that means it outlives the
83-
// constant's initialization value computation. Anything outliving a constant
84-
// must have the `'static` lifetime and live forever.
85-
// Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything
86-
// within a block will keep the regular drops just like runtime code.
87-
if let Some(temp_lifetime) = temp_lifetime {
88-
this.schedule_drop(
89-
expr_span,
90-
temp_lifetime,
91-
temp,
92-
expr_ty,
93-
DropKind::Storage,
70+
match expr.kind {
71+
// Don't bother with StorageLive and Dead for these temporaries,
72+
// they are never assigned.
73+
ExprKind::Break { .. } |
74+
ExprKind::Continue { .. } |
75+
ExprKind::Return { .. } => (),
76+
ExprKind::Block {
77+
body: hir::Block { expr: None, targeted_by_break: false, .. }
78+
} if expr_ty.is_never() => (),
79+
_ => {
80+
this.cfg.push(
81+
block,
82+
Statement {
83+
source_info,
84+
kind: StatementKind::StorageLive(temp),
85+
},
9486
);
87+
88+
// In constants, `temp_lifetime` is `None` for temporaries that
89+
// live for the `'static` lifetime. Thus we do not drop these
90+
// temporaries and simply leak them.
91+
// This is equivalent to what `let x = &foo();` does in
92+
// functions. The temporary is lifted to their surrounding
93+
// scope. In a function that means the temporary lives until
94+
// just before the function returns. In constants that means it
95+
// outlives the constant's initialization value computation.
96+
// Anything outliving a constant must have the `'static`
97+
// lifetime and live forever.
98+
// Anything with a shorter lifetime (e.g the `&foo()` in
99+
// `bar(&foo())` or anything within a block will keep the
100+
// regular drops just like runtime code.
101+
if let Some(temp_lifetime) = temp_lifetime {
102+
this.schedule_drop(
103+
expr_span,
104+
temp_lifetime,
105+
temp,
106+
expr_ty,
107+
DropKind::Storage,
108+
);
109+
}
95110
}
96111
}
97112

src/test/mir-opt/loop_test.rs

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ fn main() {
2626
// _1 = ();
2727
// StorageDead(_2);
2828
// StorageDead(_1);
29+
// StorageLive(_4);
2930
// goto -> bb5;
3031
// }
3132
// ...
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Regression test for issue 62165
2+
3+
// check-pass
4+
5+
#![feature(never_type)]
6+
7+
pub fn main() {
8+
loop {
9+
match None {
10+
None => return,
11+
Some(val) => val,
12+
};
13+
};
14+
}

0 commit comments

Comments
 (0)