Skip to content

Commit

Permalink
Add AdjustNeverToAny in check_expr
Browse files Browse the repository at this point in the history
  • Loading branch information
canndrew committed Sep 5, 2016
1 parent 9cd8d7a commit adb19ff
Showing 1 changed file with 57 additions and 73 deletions.
130 changes: 57 additions & 73 deletions src/librustc_typeck/check/mod.rs
Expand Up @@ -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>) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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| {
Expand All @@ -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
Expand All @@ -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));
Expand All @@ -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 {
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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 {
Expand All @@ -3561,25 +3540,25 @@ 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
}
}
}
}
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| {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) => {
Expand All @@ -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
Expand Down Expand Up @@ -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
}

Expand Down

0 comments on commit adb19ff

Please sign in to comment.