Skip to content

Commit

Permalink
Rollup merge of rust-lang#62465 - matthewjasper:never-type-storage, r…
Browse files Browse the repository at this point in the history
…=pnkfelix

Sometimes generate storage statements for temporaries with type `!`

Closes rust-lang#62165
cc rust-lang#42371
  • Loading branch information
Centril authored Jul 10, 2019
2 parents a2cbae8 + 163c059 commit 5760bc6
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 29 deletions.
10 changes: 6 additions & 4 deletions src/librustc_mir/build/expr/as_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let (usize_ty, bool_ty) = (this.hir.usize_ty(), this.hir.bool_ty());

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

// bounds check:
let (len, lt) = (
Expand Down
65 changes: 40 additions & 25 deletions src/librustc_mir/build/expr/as_temp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use crate::build::{BlockAnd, BlockAndExtension, Builder};
use crate::build::scope::DropKind;
use crate::hair::*;
use rustc::hir;
use rustc::middle::region;
use rustc::mir::*;

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

if !expr_ty.is_never() {
this.cfg.push(
block,
Statement {
source_info,
kind: StatementKind::StorageLive(temp),
},
);

// In constants, `temp_lifetime` is `None` for temporaries that live for the
// `'static` lifetime. Thus we do not drop these temporaries and simply leak them.
// This is equivalent to what `let x = &foo();` does in functions. The temporary
// is lifted to their surrounding scope. In a function that means the temporary lives
// until just before the function returns. In constants that means it outlives the
// constant's initialization value computation. Anything outliving a constant
// must have the `'static` lifetime and live forever.
// Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything
// within a block will keep the regular drops just like runtime code.
if let Some(temp_lifetime) = temp_lifetime {
this.schedule_drop(
expr_span,
temp_lifetime,
temp,
expr_ty,
DropKind::Storage,
match expr.kind {
// Don't bother with StorageLive and Dead for these temporaries,
// they are never assigned.
ExprKind::Break { .. } |
ExprKind::Continue { .. } |
ExprKind::Return { .. } => (),
ExprKind::Block {
body: hir::Block { expr: None, targeted_by_break: false, .. }
} if expr_ty.is_never() => (),
_ => {
this.cfg.push(
block,
Statement {
source_info,
kind: StatementKind::StorageLive(temp),
},
);

// In constants, `temp_lifetime` is `None` for temporaries that
// live for the `'static` lifetime. Thus we do not drop these
// temporaries and simply leak them.
// This is equivalent to what `let x = &foo();` does in
// functions. The temporary is lifted to their surrounding
// scope. In a function that means the temporary lives until
// just before the function returns. In constants that means it
// outlives the constant's initialization value computation.
// Anything outliving a constant must have the `'static`
// lifetime and live forever.
// Anything with a shorter lifetime (e.g the `&foo()` in
// `bar(&foo())` or anything within a block will keep the
// regular drops just like runtime code.
if let Some(temp_lifetime) = temp_lifetime {
this.schedule_drop(
expr_span,
temp_lifetime,
temp,
expr_ty,
DropKind::Storage,
);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/test/mir-opt/loop_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ fn main() {
// _1 = ();
// StorageDead(_2);
// StorageDead(_1);
// StorageLive(_4);
// goto -> bb5;
// }
// ...
Expand Down
14 changes: 14 additions & 0 deletions src/test/ui/borrowck/assign-never-type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Regression test for issue 62165

// check-pass

#![feature(never_type)]

pub fn main() {
loop {
match None {
None => return,
Some(val) => val,
};
};
}

0 comments on commit 5760bc6

Please sign in to comment.