From adb19ff277262ce629e092feabdc5f5f5a2ac408 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Fri, 19 Aug 2016 00:13:15 +0800 Subject: [PATCH] Add AdjustNeverToAny in check_expr --- src/librustc_typeck/check/mod.rs | 130 ++++++++++++++----------------- 1 file changed, 57 insertions(+), 73 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 8406b491737ec..2a12b7055d4ed 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1530,21 +1530,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } #[inline] - pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) -> Ty<'tcx> { + pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) { debug!("write_ty({}, {:?}) in fcx {}", node_id, ty, self.tag()); self.tables.borrow_mut().node_types.insert(node_id, ty); - - // Add adjustments to !-expressions - if ty.is_never() { - if let Some(hir::map::NodeExpr(_)) = self.tcx.map.find(node_id) { - let adj_ty = self.next_diverging_ty_var(); - let adj = adjustment::AdjustNeverToAny(adj_ty); - self.write_adjustment(node_id, adj); - return adj_ty; - } - } - ty } pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) { @@ -1717,16 +1706,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty_substituted } - pub fn write_nil(&self, node_id: ast::NodeId) -> Ty<'tcx> { - self.write_ty(node_id, self.tcx.mk_nil()) + pub fn write_nil(&self, node_id: ast::NodeId) { + self.write_ty(node_id, self.tcx.mk_nil()); } - pub fn write_never(&self, node_id: ast::NodeId) -> Ty<'tcx> { - self.write_ty(node_id, self.tcx.types.never) + pub fn write_never(&self, node_id: ast::NodeId) { + self.write_ty(node_id, self.tcx.types.never); } - pub fn write_error(&self, node_id: ast::NodeId) -> Ty<'tcx> { - self.write_ty(node_id, self.tcx.types.err) + pub fn write_error(&self, node_id: ast::NodeId) { + self.write_ty(node_id, self.tcx.types.err); } pub fn require_type_meets(&self, @@ -3314,20 +3303,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }); let referent_ty = self.check_expr_with_expectation(subexpr, expected_inner); - self.write_ty(id, tcx.mk_box(referent_ty)) + tcx.mk_box(referent_ty) } hir::ExprLit(ref lit) => { - let typ = self.check_lit(&lit, expected); - self.write_ty(id, typ) + self.check_lit(&lit, expected) } hir::ExprBinary(op, ref lhs, ref rhs) => { - let ty = self.check_binop(expr, op, lhs, rhs); - self.write_ty(id, ty) + self.check_binop(expr, op, lhs, rhs) } hir::ExprAssignOp(op, ref lhs, ref rhs) => { - let ty = self.check_binop_assign(expr, op, lhs, rhs); - self.write_ty(id, ty) + self.check_binop_assign(expr, op, lhs, rhs) } hir::ExprUnary(unop, ref oprnd) => { let expected_inner = match unop { @@ -3386,7 +3372,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - self.write_ty(id, oprnd_t) + oprnd_t } hir::ExprAddrOf(mutbl, ref oprnd) => { let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { @@ -3408,7 +3394,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let ty = self.check_expr_with_expectation_and_lvalue_pref(&oprnd, hint, lvalue_pref); let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl }; - let oprnd_t = if tm.ty.references_error() { + if tm.ty.references_error() { tcx.types.err } else { // Note: at this point, we cannot say what the best lifetime @@ -3426,8 +3412,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // as long as it needs to live. let region = self.next_region_var(infer::AddrOfRegion(expr.span)); tcx.mk_ref(region, tm) - }; - self.write_ty(id, oprnd_t) + } } hir::ExprPath(ref opt_qself, ref path) => { let opt_self_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty)); @@ -3446,7 +3431,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.add_wf_bounds(&item_substs.substs, expr); }); - self.write_ty(id, ty) + ty } hir::ExprInlineAsm(_, ref outputs, ref inputs) => { for output in outputs { @@ -3455,10 +3440,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { for input in inputs { self.check_expr(input); } - self.write_nil(id) + tcx.mk_nil() } - hir::ExprBreak(_) => { self.write_never(id) } - hir::ExprAgain(_) => { self.write_never(id) } + hir::ExprBreak(_) => { tcx.types.never } + hir::ExprAgain(_) => { tcx.types.never } hir::ExprRet(ref expr_opt) => { if let Some(ref e) = *expr_opt { self.check_expr_coercable_to_type(&e, self.ret_ty); @@ -3476,7 +3461,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .emit(); } } - self.write_never(id) + tcx.types.never } hir::ExprAssign(ref lhs, ref rhs) => { let lhs_ty = self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue); @@ -3497,55 +3482,49 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized); if lhs_ty.references_error() || rhs_ty.references_error() { - self.write_error(id) + tcx.types.err } else { - self.write_nil(id) + tcx.mk_nil() } } hir::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => { - let if_ty = self.check_then_else(&cond, &then_blk, opt_else_expr.as_ref().map(|e| &**e), - expr.span, expected); - self.write_ty(id, if_ty) + self.check_then_else(&cond, &then_blk, opt_else_expr.as_ref().map(|e| &**e), + expr.span, expected) } hir::ExprWhile(ref cond, ref body, _) => { let cond_ty = self.check_expr_has_type(&cond, tcx.types.bool); self.check_block_no_value(&body); let body_ty = self.node_ty(body.id); if cond_ty.references_error() || body_ty.references_error() { - self.write_error(id) + tcx.types.err } else { - self.write_nil(id) + tcx.mk_nil() } } hir::ExprLoop(ref body, _) => { self.check_block_no_value(&body); if !may_break(tcx, expr.id, &body) { - self.write_never(id) + tcx.types.never } else { - self.write_nil(id) + tcx.mk_nil() } } hir::ExprMatch(ref discrim, ref arms, match_src) => { - let result_ty = self.check_match(expr, &discrim, arms, expected, match_src); - self.write_ty(expr.id, result_ty) + self.check_match(expr, &discrim, arms, expected, match_src) } hir::ExprClosure(capture, ref decl, ref body, _) => { - let ty = self.check_expr_closure(expr, capture, &decl, &body, expected); - self.write_ty(id, ty) + self.check_expr_closure(expr, capture, &decl, &body, expected) } hir::ExprBlock(ref b) => { self.check_block_with_expected(&b, expected); - let ty = self.node_ty(b.id); - self.write_ty(id, ty) + self.node_ty(b.id) } hir::ExprCall(ref callee, ref args) => { - let ret_ty = self.check_call(expr, &callee, &args[..], expected); - self.write_ty(id, ret_ty) + self.check_call(expr, &callee, &args[..], expected) } hir::ExprMethodCall(name, ref tps, ref args) => { - let ret_ty = self.check_method_call(expr, name, &args[..], &tps[..], expected, lvalue_pref); - self.write_ty(id, ret_ty) + self.check_method_call(expr, name, &args[..], &tps[..], expected, lvalue_pref) } hir::ExprCast(ref e, ref t) => { if let hir::TyFixedLengthVec(_, ref count_expr) = t.node { @@ -3561,17 +3540,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Eagerly check for some obvious errors. if t_expr.references_error() || t_cast.references_error() { - self.write_error(id) + tcx.types.err } else { // Defer other checks until we're done type checking. let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) { Ok(cast_check) => { deferred_cast_checks.push(cast_check); - self.write_ty(id, t_cast) + t_cast } Err(ErrorReported) => { - self.write_error(id) + tcx.types.err } } } @@ -3579,7 +3558,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprType(ref e, ref t) => { let typ = self.to_ty(&t); self.check_expr_eq_type(&e, typ); - self.write_ty(id, typ) + typ } hir::ExprVec(ref args) => { let uty = expected.to_option(self).and_then(|uty| { @@ -3611,7 +3590,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - self.write_ty(id, tcx.mk_array(unified, args.len())) + tcx.mk_array(unified, args.len()) } hir::ExprRepeat(ref element, ref count_expr) => { self.check_expr_has_type(&count_expr, tcx.types.usize); @@ -3647,10 +3626,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } if element_ty.references_error() { - self.write_error(id) + tcx.types.err } else { - let t = tcx.mk_array(t, count); - self.write_ty(id, t) + tcx.mk_array(t, count) } } hir::ExprTup(ref elts) => { @@ -3677,29 +3655,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { t }).collect(); if err_field { - self.write_error(id) + tcx.types.err } else { - let typ = tcx.mk_tup(elt_ts); - self.write_ty(id, typ) + tcx.mk_tup(elt_ts) } } hir::ExprStruct(ref path, ref fields, ref base_expr) => { - let ty = self.check_expr_struct(expr, path, fields, base_expr); - self.write_ty(id, ty) + self.check_expr_struct(expr, path, fields, base_expr) } hir::ExprField(ref base, ref field) => { - let ty = self.check_field(expr, lvalue_pref, &base, field); - self.write_ty(id, ty) + self.check_field(expr, lvalue_pref, &base, field) } hir::ExprTupField(ref base, idx) => { - let ty = self.check_tup_field(expr, lvalue_pref, &base, idx); - self.write_ty(id, ty) + self.check_tup_field(expr, lvalue_pref, &base, idx) } hir::ExprIndex(ref base, ref idx) => { let base_t = self.check_expr_with_lvalue_pref(&base, lvalue_pref); let idx_t = self.check_expr(&idx); - let ty = if base_t.references_error() { + if base_t.references_error() { base_t } else if idx_t.references_error() { idx_t @@ -3747,16 +3721,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.tcx().types.err } } - }; - self.write_ty(id, ty) + } } }; + self.write_ty(id, ty); debug!("type of expr({}) {} is...", expr.id, pprust::expr_to_string(expr)); debug!("... {:?}, expected is {:?}", ty, expected); + + // Add adjustments to !-expressions + if ty.is_never() { + if let Some(hir::map::NodeExpr(_)) = self.tcx.map.find(id) { + let adj_ty = self.next_diverging_ty_var(); + let adj = adjustment::AdjustNeverToAny(adj_ty); + self.write_adjustment(id, adj); + return adj_ty; + } + } ty }