提交 ff4d4b27 编写于 作者: M Matthew Jasper

Allow subtyping of the final expression of a constant

Fixes an ICE for the following code:

fn foo(_ : &()) {}
static X: fn(&'static ()) = foo;
上级 eb37c648
......@@ -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 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type
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();
......
// Test that subtyping the body of a static doesn't cause an ICE.
fn foo(_ : &()) {}
static X: fn(&'static ()) = foo;
fn main() {
let _ = X;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册