Rollup merge of #59560 - matthewjasper:mir-generation-cleanup, r=oli-obk
MIR generation cleanup * Handle the case where the body of a constant is a subtype of the type of the constant (see `mir_static_subtype.rs`). * Move the evaluation of `ExprKind::Use` into `into.rs`, saving an unnecessary copy.
This commit is contained in:
commit
5440cf1cb6
@ -150,10 +150,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
let source = unpack!(block = this.as_operand(block, scope, source));
|
let source = unpack!(block = this.as_operand(block, scope, source));
|
||||||
block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
|
block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
|
||||||
}
|
}
|
||||||
ExprKind::Use { source } => {
|
|
||||||
let source = unpack!(block = this.as_operand(block, scope, source));
|
|
||||||
block.and(Rvalue::Use(source))
|
|
||||||
}
|
|
||||||
ExprKind::Pointer { cast, source } => {
|
ExprKind::Pointer { cast, source } => {
|
||||||
let source = unpack!(block = this.as_operand(block, scope, source));
|
let source = unpack!(block = this.as_operand(block, scope, source));
|
||||||
block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty))
|
block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty))
|
||||||
@ -363,6 +359,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
| ExprKind::Match { .. }
|
| ExprKind::Match { .. }
|
||||||
| ExprKind::If { .. }
|
| ExprKind::If { .. }
|
||||||
| ExprKind::NeverToAny { .. }
|
| ExprKind::NeverToAny { .. }
|
||||||
|
| ExprKind::Use { .. }
|
||||||
| ExprKind::Loop { .. }
|
| ExprKind::Loop { .. }
|
||||||
| ExprKind::LogicalOp { .. }
|
| ExprKind::LogicalOp { .. }
|
||||||
| ExprKind::Call { .. }
|
| ExprKind::Call { .. }
|
||||||
|
@ -48,6 +48,7 @@ impl Category {
|
|||||||
| ExprKind::If { .. }
|
| ExprKind::If { .. }
|
||||||
| ExprKind::Match { .. }
|
| ExprKind::Match { .. }
|
||||||
| ExprKind::NeverToAny { .. }
|
| ExprKind::NeverToAny { .. }
|
||||||
|
| ExprKind::Use { .. }
|
||||||
| ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
|
| ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
|
||||||
|
|
||||||
ExprKind::Array { .. }
|
ExprKind::Array { .. }
|
||||||
@ -58,7 +59,6 @@ impl Category {
|
|||||||
| ExprKind::Binary { .. }
|
| ExprKind::Binary { .. }
|
||||||
| ExprKind::Box { .. }
|
| ExprKind::Box { .. }
|
||||||
| ExprKind::Cast { .. }
|
| ExprKind::Cast { .. }
|
||||||
| ExprKind::Use { .. }
|
|
||||||
| ExprKind::Pointer { .. }
|
| ExprKind::Pointer { .. }
|
||||||
| ExprKind::Repeat { .. }
|
| ExprKind::Repeat { .. }
|
||||||
| ExprKind::Borrow { .. }
|
| ExprKind::Borrow { .. }
|
||||||
|
@ -327,6 +327,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
success.unit()
|
success.unit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ExprKind::Use { source } => {
|
||||||
|
this.into(destination, block, source)
|
||||||
|
}
|
||||||
|
|
||||||
// These cases don't actually need a destination
|
// These cases don't actually need a destination
|
||||||
ExprKind::Assign { .. }
|
ExprKind::Assign { .. }
|
||||||
@ -379,7 +382,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
| ExprKind::Binary { .. }
|
| ExprKind::Binary { .. }
|
||||||
| ExprKind::Box { .. }
|
| ExprKind::Box { .. }
|
||||||
| ExprKind::Cast { .. }
|
| ExprKind::Cast { .. }
|
||||||
| ExprKind::Use { .. }
|
|
||||||
| ExprKind::Pointer { .. }
|
| ExprKind::Pointer { .. }
|
||||||
| ExprKind::Repeat { .. }
|
| ExprKind::Repeat { .. }
|
||||||
| ExprKind::Borrow { .. }
|
| ExprKind::Borrow { .. }
|
||||||
|
@ -147,7 +147,21 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
|
|||||||
build::construct_fn(cx, id, arguments, safety, abi,
|
build::construct_fn(cx, id, arguments, safety, abi,
|
||||||
return_ty, yield_ty, return_ty_span, body)
|
return_ty, yield_ty, return_ty_span, body)
|
||||||
} else {
|
} else {
|
||||||
build::construct_const(cx, body_id, return_ty_span)
|
// Get the revealed type of this const. This is *not* the adjusted
|
||||||
|
// type of its body, which may be a subtype of this type. For
|
||||||
|
// example:
|
||||||
|
//
|
||||||
|
// fn foo(_: &()) {}
|
||||||
|
// static X: fn(&'static ()) = foo;
|
||||||
|
//
|
||||||
|
// The adjusted type of the body of X is `for<'a> fn(&'a ())` which
|
||||||
|
// is not the same as the type of X. We need the type of the return
|
||||||
|
// place to be the type of the constant because NLL typeck will
|
||||||
|
// equate them.
|
||||||
|
|
||||||
|
let return_ty = cx.tables().node_type(id);
|
||||||
|
|
||||||
|
build::construct_const(cx, body_id, return_ty, return_ty_span)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert the Mir to global types.
|
// Convert the Mir to global types.
|
||||||
@ -730,16 +744,25 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
|||||||
fn construct_const<'a, 'gcx, 'tcx>(
|
fn construct_const<'a, 'gcx, 'tcx>(
|
||||||
hir: Cx<'a, 'gcx, 'tcx>,
|
hir: Cx<'a, 'gcx, 'tcx>,
|
||||||
body_id: hir::BodyId,
|
body_id: hir::BodyId,
|
||||||
ty_span: Span,
|
const_ty: Ty<'tcx>,
|
||||||
|
const_ty_span: Span,
|
||||||
) -> Mir<'tcx> {
|
) -> Mir<'tcx> {
|
||||||
let tcx = hir.tcx();
|
let tcx = hir.tcx();
|
||||||
let ast_expr = &tcx.hir().body(body_id).value;
|
|
||||||
let ty = hir.tables().expr_ty_adjusted(ast_expr);
|
|
||||||
let owner_id = tcx.hir().body_owner(body_id);
|
let owner_id = tcx.hir().body_owner(body_id);
|
||||||
let span = tcx.hir().span(owner_id);
|
let span = tcx.hir().span(owner_id);
|
||||||
let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, ty_span, vec![], vec![]);
|
let mut builder = Builder::new(
|
||||||
|
hir,
|
||||||
|
span,
|
||||||
|
0,
|
||||||
|
Safety::Safe,
|
||||||
|
const_ty,
|
||||||
|
const_ty_span,
|
||||||
|
vec![],
|
||||||
|
vec![],
|
||||||
|
);
|
||||||
|
|
||||||
let mut block = START_BLOCK;
|
let mut block = START_BLOCK;
|
||||||
|
let ast_expr = &tcx.hir().body(body_id).value;
|
||||||
let expr = builder.hir.mirror(ast_expr);
|
let expr = builder.hir.mirror(ast_expr);
|
||||||
unpack!(block = builder.into_expr(&Place::RETURN_PLACE, block, expr));
|
unpack!(block = builder.into_expr(&Place::RETURN_PLACE, block, expr));
|
||||||
|
|
||||||
|
@ -259,8 +259,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cast(kind, ref operand, cast_ty) => {
|
Cast(kind, ref operand, _) => {
|
||||||
debug_assert_eq!(self.monomorphize(cast_ty)?, dest.layout.ty);
|
|
||||||
let src = self.eval_operand(operand, None)?;
|
let src = self.eval_operand(operand, None)?;
|
||||||
self.cast(src, kind, dest)?;
|
self.cast(src, kind, dest)?;
|
||||||
}
|
}
|
||||||
|
@ -866,6 +866,8 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
|
|
||||||
fcx.check_expr_coercable_to_type(&body.value, revealed_ty);
|
fcx.check_expr_coercable_to_type(&body.value, revealed_ty);
|
||||||
|
|
||||||
|
fcx.write_ty(id, revealed_ty);
|
||||||
|
|
||||||
fcx
|
fcx
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,6 +42,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
for arg in &body.arguments {
|
for arg in &body.arguments {
|
||||||
wbcx.visit_node_id(arg.pat.span, arg.hir_id);
|
wbcx.visit_node_id(arg.pat.span, arg.hir_id);
|
||||||
}
|
}
|
||||||
|
// Type only exists for constants and statics, not functions.
|
||||||
|
match self.tcx.hir().body_owner_kind(item_id) {
|
||||||
|
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => {
|
||||||
|
let item_hir_id = self.tcx.hir().node_to_hir_id(item_id);
|
||||||
|
wbcx.visit_node_id(body.value.span, item_hir_id);
|
||||||
|
}
|
||||||
|
hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (),
|
||||||
|
}
|
||||||
wbcx.visit_body(body);
|
wbcx.visit_body(body);
|
||||||
wbcx.visit_upvar_capture_map();
|
wbcx.visit_upvar_capture_map();
|
||||||
wbcx.visit_upvar_list_map();
|
wbcx.visit_upvar_list_map();
|
||||||
|
@ -18,25 +18,24 @@ fn main() {
|
|||||||
// START rustc.main.EraseRegions.after.mir
|
// START rustc.main.EraseRegions.after.mir
|
||||||
// bb0: {
|
// bb0: {
|
||||||
// ...
|
// ...
|
||||||
// _6 = &mut _2;
|
// _5 = &mut _2;
|
||||||
// _5 = &mut (*_6);
|
// _4 = &mut (*_5);
|
||||||
// _4 = move _5 as *mut usize (Misc);
|
// _3 = move _4 as *mut usize (Misc);
|
||||||
// _3 = move _4;
|
|
||||||
// ...
|
// ...
|
||||||
// _8 = _3;
|
// _7 = _3;
|
||||||
// _7 = const foo(move _8) -> bb1;
|
// _6 = const foo(move _7) -> bb1;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// bb1: {
|
// bb1: {
|
||||||
// ...
|
// ...
|
||||||
// _9 = _2;
|
// _8 = _2;
|
||||||
// _10 = Len(_1);
|
// _9 = Len(_1);
|
||||||
// _11 = Lt(_9, _10);
|
// _10 = Lt(_8, _9);
|
||||||
// assert(move _11, "index out of bounds: the len is move _10 but the index is _9") -> bb2;
|
// assert(move _10, "index out of bounds: the len is move _9 but the index is _8") -> bb2;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// bb2: {
|
// bb2: {
|
||||||
// _1[_9] = move _7;
|
// _1[_8] = move _6;
|
||||||
// ...
|
// ...
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
@ -75,18 +75,18 @@ fn main() {
|
|||||||
// _10 = move _8;
|
// _10 = move _8;
|
||||||
// Retag(_10);
|
// Retag(_10);
|
||||||
// ...
|
// ...
|
||||||
// _15 = &mut (*_10);
|
// _13 = &mut (*_10);
|
||||||
// Retag(_15);
|
// Retag(_13);
|
||||||
// _14 = move _15 as *mut i32 (Misc);
|
// _12 = move _13 as *mut i32 (Misc);
|
||||||
// Retag([raw] _14);
|
// Retag([raw] _12);
|
||||||
// ...
|
// ...
|
||||||
// _18 = move _19(move _20) -> bb2;
|
// _16 = move _17(move _18) -> bb2;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// bb2: {
|
// bb2: {
|
||||||
// Retag(_18);
|
// Retag(_16);
|
||||||
// ...
|
// ...
|
||||||
// _22 = const Test::foo_shr(move _23, move _25) -> bb3;
|
// _20 = const Test::foo_shr(move _21, move _23) -> bb3;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// bb3: {
|
// bb3: {
|
||||||
|
8
src/test/run-pass/mir/mir_static_subtype.rs
Normal file
8
src/test/run-pass/mir/mir_static_subtype.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Test that subtyping the body of a static doesn't cause an ICE.
|
||||||
|
|
||||||
|
fn foo(_ : &()) {}
|
||||||
|
static X: fn(&'static ()) = foo;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = X;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user