Rollup merge of #62465 - matthewjasper:never-type-storage, r=pnkfelix
Sometimes generate storage statements for temporaries with type `!` Closes #62165 cc #42371
This commit is contained in:
commit
5760bc6e98
4 changed files with 61 additions and 29 deletions
|
|
@ -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) = (
|
||||
|
|
|
|||
|
|
@ -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::*;
|
||||
|
||||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ fn main() {
|
|||
// _1 = ();
|
||||
// StorageDead(_2);
|
||||
// StorageDead(_1);
|
||||
// StorageLive(_4);
|
||||
// goto -> bb5;
|
||||
// }
|
||||
// ...
|
||||
|
|
|
|||
14
src/test/ui/borrowck/assign-never-type.rs
Normal file
14
src/test/ui/borrowck/assign-never-type.rs
Normal file
|
|
@ -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,
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue