Allow subtyping of the final expression of a constant
Fixes an ICE for the following code: fn foo(_ : &()) {} static X: fn(&'static ()) = foo;
This commit is contained in:
parent
eb37c648d7
commit
ff4d4b277f
4 changed files with 46 additions and 5 deletions
|
@ -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,
|
||||
return_ty, yield_ty, return_ty_span, body)
|
||||
} 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.
|
||||
|
@ -730,16 +744,25 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
|||
fn construct_const<'a, 'gcx, 'tcx>(
|
||||
hir: Cx<'a, 'gcx, 'tcx>,
|
||||
body_id: hir::BodyId,
|
||||
ty_span: Span,
|
||||
const_ty: Ty<'tcx>,
|
||||
const_ty_span: Span,
|
||||
) -> Mir<'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 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 ast_expr = &tcx.hir().body(body_id).value;
|
||||
let expr = builder.hir.mirror(ast_expr);
|
||||
unpack!(block = builder.into_expr(&Place::RETURN_PLACE, block, expr));
|
||||
|
||||
|
|
|
@ -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.write_ty(id, revealed_ty);
|
||||
|
||||
fcx
|
||||
};
|
||||
|
||||
|
|
|
@ -42,6 +42,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
for arg in &body.arguments {
|
||||
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_upvar_capture_map();
|
||||
wbcx.visit_upvar_list_map();
|
||||
|
|
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…
Add table
Add a link
Reference in a new issue