From f7abf47058e73ea4a95031fb80d92f636e5a18f9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 2 Jan 2015 03:51:49 -0500 Subject: [PATCH] Re-introduce `McResult<>` as a way of aborting mem-categorization (and expr-use-visitor) early. Turns out I was wrong to remove this; it causes a lot of pain trying to run EUV etc during typeck without ICEing on erroneous programs. --- src/librustc/middle/expr_use_visitor.rs | 79 +++++----- src/librustc/middle/mem_categorization.rs | 167 +++++++++++----------- src/librustc/middle/ty.rs | 5 +- src/librustc_typeck/check/mod.rs | 23 ++- src/librustc_typeck/check/regionck.rs | 31 ++-- 5 files changed, 175 insertions(+), 130 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index d36c85342ce..06815266266 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -300,6 +300,20 @@ pub struct ExprUseVisitor<'d,'t,'tcx:'t,TYPER:'t> { mc: mc::MemCategorizationContext<'t,TYPER>, delegate: &'d mut (Delegate<'tcx>+'d), param_env: &'t ParameterEnvironment<'tcx>, +// If the TYPER results in an error, it's because the type check +// failed (or will fail, when the error is uncovered and reported +// during writeback). In this case, we just ignore this part of the +// code. +// +// Note that this macro appears similar to try!(), but, unlike try!(), +// it does not propagate the error. +macro_rules! return_if_err { + ($inp: expr) => ( + match $inp { + Ok(v) => v, + Err(()) => return + } + ) } /// Whether the elements of an overloaded operation are passed by value or by reference @@ -332,7 +346,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { decl: &ast::FnDecl, body: &ast::Block) { for arg in decl.inputs.iter() { - let arg_ty = self.typer.node_ty(arg.pat.id); + let arg_ty = return_if_err!(self.typer.node_ty(arg.pat.id)); let fn_body_scope = region::CodeExtent::from_node_id(body.id); let arg_cmt = self.mc.cat_rvalue( @@ -369,7 +383,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { pub fn consume_expr(&mut self, expr: &ast::Expr) { debug!("consume_expr(expr={})", expr.repr(self.tcx())); - let cmt = self.mc.cat_expr(expr); + let cmt = return_if_err!(self.mc.cat_expr(expr)); self.delegate_consume(expr.id, expr.span, cmt); self.walk_expr(expr); } @@ -378,7 +392,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { assignment_expr: &ast::Expr, expr: &ast::Expr, mode: MutateMode) { - let cmt = self.mc.cat_expr(expr); + let cmt = return_if_err!(self.mc.cat_expr(expr)); self.delegate.mutate(assignment_expr.id, assignment_expr.span, cmt, mode); self.walk_expr(expr); } @@ -391,7 +405,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { debug!("borrow_expr(expr={}, r={}, bk={})", expr.repr(self.tcx()), r.repr(self.tcx()), bk.repr(self.tcx())); - let cmt = self.mc.cat_expr(expr); + let cmt = return_if_err!(self.mc.cat_expr(expr)); self.delegate.borrow(expr.id, expr.span, cmt, r, bk, cause); // Note: Unlike consume, we can ignore ExprParen. cat_expr @@ -491,7 +505,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } ast::ExprMatch(ref discr, ref arms, _) => { - let discr_cmt = self.mc.cat_expr(&**discr); + let discr_cmt = return_if_err!(self.mc.cat_expr(&**discr)); self.borrow_expr(&**discr, ty::ReEmpty, ty::ImmBorrow, MatchDiscriminant); // treatment of the discriminant is handled while walking the arms. @@ -509,7 +523,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { ast::ExprAddrOf(m, ref base) => { // &base // make sure that the thing we are pointing out stays valid // for the lifetime `scope_r` of the resulting ptr: - let expr_ty = ty::expr_ty(self.tcx(), expr); + let expr_ty = return_if_err!(self.typer.node_ty(expr.id)); let r = ty::ty_region(self.tcx(), expr.span, expr_ty); let bk = ty::BorrowKind::from_mutbl(m); self.borrow_expr(&**base, r, bk, AddrOf); @@ -550,7 +564,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // Fetch the type of the value that the iteration yields to // produce the pattern's categorized mutable type. - let pattern_type = self.typer.node_ty(pat.id); + let pattern_type = return_if_err!(self.typer.node_ty(pat.id)); let blk_scope = region::CodeExtent::from_node_id(blk.id); let pat_cmt = self.mc.cat_rvalue(pat.id, pat.span, @@ -638,7 +652,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } fn walk_callee(&mut self, call: &ast::Expr, callee: &ast::Expr) { - let callee_ty = self.typer.expr_ty_adjusted(callee); + let callee_ty = return_if_err!(self.typer.expr_ty_adjusted(callee)); debug!("walk_callee: callee={} callee_ty={}", callee.repr(self.tcx()), callee_ty.repr(self.tcx())); let call_scope = region::CodeExtent::from_node_id(call.id); @@ -735,7 +749,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // "assigns", which is handled by // `walk_pat`: self.walk_expr(&**expr); - let init_cmt = self.mc.cat_expr(&**expr); + let init_cmt = return_if_err!(self.mc.cat_expr(&**expr)); self.walk_irrefutable_pat(init_cmt, &*local.pat); } } @@ -769,7 +783,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { None => { return; } }; - let with_cmt = self.mc.cat_expr(&*with_expr); + let with_cmt = return_if_err!(self.mc.cat_expr(&*with_expr)); // Select just those fields of the `with` // expression that will actually be used @@ -824,7 +838,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // rvalue. debug!("walk_adjustment(AutoAddEnv|AdjustReifyFnPointer)"); let cmt_unadjusted = - self.mc.cat_expr_unadjusted(expr); + return_if_err!(self.mc.cat_expr_unadjusted(expr)); self.delegate_consume(expr.id, expr.span, cmt_unadjusted); } ty::AdjustDerefRef(ty::AutoDerefRef { @@ -858,7 +872,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { match self.typer.node_method_ty(deref_id) { None => {} Some(method_ty) => { - let cmt = self.mc.cat_expr_autoderefd(expr, i); + let cmt = return_if_err!(self.mc.cat_expr_autoderefd(expr, i)); let self_ty = ty::ty_fn_args(method_ty)[0]; let (m, r) = match self_ty.sty { ty::ty_rptr(r, ref m) => (m.mutbl, r), @@ -888,14 +902,15 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { assert!(n == 1, format!("Expected exactly 1 deref with Uniq \ AutoRefs, found: {}", n)); let cmt_unadjusted = - self.mc.cat_expr_unadjusted(expr); + return_if_err!(self.mc.cat_expr_unadjusted(expr)); self.delegate_consume(expr.id, expr.span, cmt_unadjusted); return; } _ => {} } - let cmt_derefd = self.mc.cat_expr_autoderefd(expr, n); + let cmt_derefd = return_if_err!( + self.mc.cat_expr_autoderefd(expr, n)); debug!("walk_adjustment: cmt_derefd={}", cmt_derefd.repr(self.tcx())); @@ -988,7 +1003,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { mode: &mut TrackMatchMode) { debug!("determine_pat_move_mode cmt_discr={} pat={}", cmt_discr.repr(self.tcx()), pat.repr(self.tcx())); - self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| { + return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| { let tcx = self.typer.tcx(); let def_map = &self.typer.tcx().def_map; if pat_util::pat_is_binding(def_map, pat) { @@ -1011,7 +1026,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } } } - }); + })); } /// The core driver for walking a pattern; `match_mode` must be @@ -1028,8 +1043,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { let typer = self.typer; let def_map = &self.typer.tcx().def_map; let delegate = &mut self.delegate; - let param_env = self.param_env; - mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| { + return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| { if pat_util::pat_is_binding(def_map, pat) { let tcx = typer.tcx(); @@ -1039,7 +1053,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { match_mode); // pat_ty: the type of the binding being produced. - let pat_ty = typer.node_ty(pat.id); + let pat_ty = return_if_err!(typer.node_ty(pat.id)); // Each match binding is effectively an assignment to the // binding being produced. @@ -1080,7 +1094,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // matched. let (slice_cmt, slice_mutbl, slice_r) = - mc.cat_slice_pattern(cmt_pat, &**slice_pat); + return_if_err!(mc.cat_slice_pattern(cmt_pat, &**slice_pat)); // Note: We declare here that the borrow // occurs upon entering the `[...]` @@ -1110,13 +1124,13 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { _ => { } } } - }); + })); // Do a second pass over the pattern, calling `matched_pat` on // the interior nodes (enum variants and structs), as opposed // to the above loop's visit of than the bindings that form // the leaves of the pattern tree structure. - mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| { + return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| { let def_map = def_map.borrow(); let tcx = typer.tcx(); @@ -1197,7 +1211,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // cases either. } } - }); + })); } fn walk_captures(&mut self, closure_expr: &ast::Expr) { @@ -1221,9 +1235,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { freevars: &[ty::Freevar]) { for freevar in freevars.iter() { let id_var = freevar.def.def_id().node; - let cmt_var = self.cat_captured_var(closure_expr.id, - closure_expr.span, - freevar.def); + let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, + closure_expr.span, + freevar.def)); // Lookup the kind of borrow the callee requires, as // inferred by regionbk @@ -1244,11 +1258,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { closure_expr: &ast::Expr, freevars: &[ty::Freevar]) { for freevar in freevars.iter() { - let cmt_var = self.cat_captured_var(closure_expr.id, - closure_expr.span, - freevar.def); - let mode = copy_or_move(self.tcx(), cmt_var.ty, - self.param_env, CaptureMove); + let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, + closure_expr.span, + freevar.def)); + let mode = copy_or_move(self.typer, &cmt_var, CaptureMove); self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode); } } @@ -1257,11 +1270,11 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { closure_id: ast::NodeId, closure_span: Span, upvar_def: def::Def) - -> mc::cmt<'tcx> { + -> mc::McResult> { // Create the cmt for the variable being borrowed, from the // caller's perspective let var_id = upvar_def.def_id().node; - let var_ty = self.typer.node_ty(var_id); + let var_ty = try!(self.typer.node_ty(var_id)); self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def) } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 70942a950e3..dbe005ea63d 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -75,7 +75,7 @@ use middle::def; use middle::region; use middle::ty::{mod, Ty}; use util::nodemap::{NodeMap}; -use util::ppaux::{ty_to_string, Repr}; +use util::ppaux::{Repr}; use syntax::ast::{MutImmutable, MutMutable}; use syntax::ast; @@ -264,6 +264,8 @@ pub struct MemCategorizationContext<'t,TYPER:'t> { impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {} +pub type McResult = Result; + /// The `Typer` trait provides the interface for the mem-categorization /// module to the results of the type check. It can be used to query /// the type assigned to an expression node, to inquire after adjustments, @@ -282,8 +284,10 @@ impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {} /// can be sure that only `Ok` results will occur. pub trait Typer<'tcx> : ty::UnboxedClosureTyper<'tcx> { fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>; - fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx>; - fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx>; + fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx>; + fn node_ty(&self, id: ast::NodeId) -> McResult>; + fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult>; + fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool; fn node_method_ty(&self, method_call: ty::MethodCall) -> Option>; fn node_method_origin(&self, method_call: ty::MethodCall) -> Option>; @@ -382,22 +386,22 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { self.typer.tcx() } - fn expr_ty(&self, expr: &ast::Expr) -> Ty<'tcx> { + fn expr_ty(&self, expr: &ast::Expr) -> McResult> { self.typer.node_ty(expr.id) } - fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> { - let unadjusted_ty = self.expr_ty(expr); - ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty, - self.typer.adjustments().borrow().get(&expr.id), - |method_call| self.typer.node_method_ty(method_call)) + fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult> { + let unadjusted_ty = try!(self.expr_ty(expr)); + Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty, + self.typer.adjustments().borrow().get(&expr.id), + |method_call| self.typer.node_method_ty(method_call))) } - fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> { + fn node_ty(&self, id: ast::NodeId) -> McResult> { self.typer.node_ty(id) } - fn pat_ty(&self, pat: &ast::Pat) -> Ty<'tcx> { + fn pat_ty(&self, pat: &ast::Pat) -> McResult> { let tcx = self.typer.tcx(); let base_ty = self.typer.node_ty(pat.id); // FIXME (Issue #18207): This code detects whether we are @@ -420,7 +424,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { ret_ty } - pub fn cat_expr(&self, expr: &ast::Expr) -> cmt<'tcx> { + pub fn cat_expr(&self, expr: &ast::Expr) -> McResult> { match self.typer.adjustments().borrow().get(&expr.id) { None => { // No adjustments. @@ -434,8 +438,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { expr.repr(self.tcx())); // Convert a bare fn to a closure by adding NULL env. // Result is an rvalue. - let expr_ty = self.expr_ty_adjusted(expr); - self.cat_rvalue_node(expr.id(), expr.span(), expr_ty) + let expr_ty = try!(self.expr_ty_adjusted(expr)); + Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)) } ty::AdjustDerefRef( @@ -445,8 +449,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { expr.repr(self.tcx())); // Equivalent to &*expr or something similar. // Result is an rvalue. - let expr_ty = self.expr_ty_adjusted(expr); - self.cat_rvalue_node(expr.id(), expr.span(), expr_ty) + let expr_ty = try!(self.expr_ty_adjusted(expr)); + Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)) } ty::AdjustDerefRef( @@ -463,46 +467,46 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { pub fn cat_expr_autoderefd(&self, expr: &ast::Expr, autoderefs: uint) - -> cmt<'tcx> { - let mut cmt = self.cat_expr_unadjusted(expr); + -> McResult> { + let mut cmt = try!(self.cat_expr_unadjusted(expr)); debug!("cat_expr_autoderefd: autoderefs={}, cmt={}", autoderefs, cmt.repr(self.tcx())); for deref in range(1u, autoderefs + 1) { - cmt = self.cat_deref(expr, cmt, deref, false); + cmt = try!(self.cat_deref(expr, cmt, deref, false)); } - return cmt; + return Ok(cmt); } - pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> cmt<'tcx> { + pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult> { debug!("cat_expr: id={} expr={}", expr.id, expr.repr(self.tcx())); - let expr_ty = self.expr_ty(expr); + let expr_ty = try!(self.expr_ty(expr)); match expr.node { ast::ExprUnary(ast::UnDeref, ref e_base) => { - let base_cmt = self.cat_expr(&**e_base); + let base_cmt = try!(self.cat_expr(&**e_base)); self.cat_deref(expr, base_cmt, 0, false) } ast::ExprField(ref base, f_name) => { - let base_cmt = self.cat_expr(&**base); + let base_cmt = try!(self.cat_expr(&**base)); debug!("cat_expr(cat_field): id={} expr={} base={}", expr.id, expr.repr(self.tcx()), base_cmt.repr(self.tcx())); - self.cat_field(expr, base_cmt, f_name.node.name, expr_ty) + Ok(self.cat_field(expr, base_cmt, f_name.node.name, expr_ty)) } ast::ExprTupField(ref base, idx) => { - let base_cmt = self.cat_expr(&**base); - self.cat_tup_field(expr, base_cmt, idx.node, expr_ty) + let base_cmt = try!(self.cat_expr(&**base)); + Ok(self.cat_tup_field(expr, base_cmt, idx.node, expr_ty)) } ast::ExprIndex(ref base, ref idx) => { match idx.node { ast::ExprRange(..) => { // Slicing syntax special case (KILLME). - self.cat_rvalue_node(expr.id(), expr.span(), expr_ty) + Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)) } _ => { let method_call = ty::MethodCall::expr(expr.id()); @@ -517,7 +521,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { ret_ty), 1, true) } None => { - self.cat_index(expr, self.cat_expr(&**base)) + self.cat_index(expr, try!(self.cat_expr(&**base))) } } } @@ -545,7 +549,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { ast::ExprAgain(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprInlineAsm(..) | ast::ExprBox(..) | ast::ExprForLoop(..) => { - self.cat_rvalue_node(expr.id(), expr.span(), expr_ty) + Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)) } ast::ExprIfLet(..) => { @@ -562,43 +566,43 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { span: Span, expr_ty: Ty<'tcx>, def: def::Def) - -> cmt<'tcx> { + -> McResult> { debug!("cat_def: id={} expr={} def={}", id, expr_ty.repr(self.tcx()), def); match def { def::DefStruct(..) | def::DefVariant(..) | def::DefFn(..) | def::DefStaticMethod(..) | def::DefConst(..) => { - self.cat_rvalue_node(id, span, expr_ty) + Ok(self.cat_rvalue_node(id, span, expr_ty)) } def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) | def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) | def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) | def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> { - Rc::new(cmt_ { + Ok(Rc::new(cmt_ { id:id, span:span, cat:cat_static_item, mutbl: McImmutable, ty:expr_ty, note: NoteNone - }) + })) } def::DefStatic(_, mutbl) => { - Rc::new(cmt_ { + Ok(Rc::new(cmt_ { id:id, span:span, cat:cat_static_item, mutbl: if mutbl { McDeclared } else { McImmutable}, ty:expr_ty, note: NoteNone - }) + })) } def::DefUpvar(var_id, fn_node_id, _) => { - let ty = self.node_ty(fn_node_id); + let ty = try!(self.node_ty(fn_node_id)); match ty.sty { ty::ty_closure(ref closure_ty) => { // Translate old closure type info into unboxed @@ -635,14 +639,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } def::DefLocal(vid) => { - Rc::new(cmt_ { + Ok(Rc::new(cmt_ { id: id, span: span, cat: cat_local(vid), mutbl: MutabilityCategory::from_local(self.tcx(), vid), ty: expr_ty, note: NoteNone - }) + })) } } } @@ -657,7 +661,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { kind: ty::UnboxedClosureKind, mode: ast::CaptureClause, is_unboxed: bool) - -> cmt<'tcx> { + -> McResult> { // An upvar can have up to 3 components. The base is a // `cat_upvar`. Next, we add a deref through the implicit // environment pointer with an anonymous free region 'env and @@ -679,7 +683,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { // FnOnce | copied | upvar -> &'up bk // old stack | N/A | upvar -> &'env mut -> &'up bk // old proc/once | copied | N/A - let var_ty = self.node_ty(var_id); + let var_ty = try!(self.node_ty(var_id)); let upvar_id = ty::UpvarId { var_id: var_id, closure_expr_id: fn_node_id }; @@ -727,7 +731,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { }); // First, switch by capture mode - match mode { + Ok(match mode { ast::CaptureByValue => { let mut base = cmt_ { id: id, @@ -809,7 +813,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { note: NoteUpvarRef(upvar_id) }) } - } + }) } pub fn cat_rvalue_node(&self, @@ -882,7 +886,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { base_cmt: cmt<'tcx>, deref_cnt: uint, implicit: bool) - -> cmt<'tcx> { + -> McResult> { let adjustment = match self.typer.adjustments().borrow().get(&node.id()) { Some(adj) if ty::adjust_is_object(adj) => ty::AutoObject, _ if deref_cnt != 0 => ty::AutoDeref(deref_cnt), @@ -896,7 +900,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { let method_ty = self.typer.node_method_ty(method_call); debug!("cat_deref: method_call={} method_ty={}", - method_call, method_ty.map(|ty| ty.repr(self.tcx()))); + method_call, method_ty.map(|ty| ty.repr(self.tcx()))); let base_cmt = match method_ty { Some(method_ty) => { @@ -922,8 +926,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { deref_cnt: uint, deref_ty: Ty<'tcx>, implicit: bool) - -> cmt<'tcx> { - let (m, cat) = match deref_kind(self.tcx(), base_cmt.ty) { + -> McResult> + { + let (m, cat) = match try!(deref_kind(base_cmt.ty)) { deref_ptr(ptr) => { let ptr = if implicit { match ptr { @@ -943,20 +948,20 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { (base_cmt.mutbl.inherit(), cat_interior(base_cmt, interior)) } }; - Rc::new(cmt_ { + Ok(Rc::new(cmt_ { id: node.id(), span: node.span(), cat: cat, mutbl: m, ty: deref_ty, note: NoteNone - }) + })) } pub fn cat_index(&self, elt: &N, mut base_cmt: cmt<'tcx>) - -> cmt<'tcx> { + -> McResult> { //! Creates a cmt for an indexing operation (`[]`). //! //! One subtle aspect of indexing that may not be @@ -1021,15 +1026,16 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { fn deref_vec(&self, elt: &N, base_cmt: cmt<'tcx>) - -> cmt<'tcx> { - match deref_kind(self.tcx(), base_cmt.ty) { + -> McResult> + { + match try!(deref_kind(base_cmt.ty)) { deref_ptr(ptr) => { // for unique ptrs, we inherit mutability from the // owning reference. let m = MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr); // the deref is explicit in the resulting cmt - Rc::new(cmt_ { + Ok(Rc::new(cmt_ { id:elt.id(), span:elt.span(), cat:cat_deref(base_cmt.clone(), 0, ptr), @@ -1039,11 +1045,11 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { None => self.tcx().sess.bug("Found non-derefable type") }, note: NoteNone - }) + })) } deref_interior(_) => { - base_cmt + Ok(base_cmt) } } } @@ -1058,13 +1064,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { pub fn cat_slice_pattern(&self, vec_cmt: cmt<'tcx>, slice_pat: &ast::Pat) - -> (cmt<'tcx>, ast::Mutability, ty::Region) { - let slice_ty = self.node_ty(slice_pat.id); + -> McResult<(cmt<'tcx>, ast::Mutability, ty::Region)> { + let slice_ty = try!(self.node_ty(slice_pat.id)); let (slice_mutbl, slice_r) = vec_slice_info(self.tcx(), slice_pat, slice_ty); - let cmt_slice = self.cat_index(slice_pat, self.deref_vec(slice_pat, vec_cmt)); - return (cmt_slice, slice_mutbl, slice_r); + let cmt_slice = try!(self.cat_index(slice_pat, try!(self.deref_vec(slice_pat, vec_cmt)))); + return Ok((cmt_slice, slice_mutbl, slice_r)); /// In a pattern like [a, b, ..c], normally `c` has slice type, but if you have [a, b, /// ..ref c], then the type of `ref c` will be `&&[]`, so to extract the slice details we @@ -1119,15 +1125,16 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { }) } - pub fn cat_pattern(&self, cmt: cmt<'tcx>, pat: &ast::Pat, mut op: F) where - F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat), + pub fn cat_pattern(&self, cmt: cmt<'tcx>, pat: &ast::Pat, mut op: F) -> McResult<()> + where F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat), { self.cat_pattern_(cmt, pat, &mut op) } // FIXME(#19596) This is a workaround, but there should be a better way to do this - fn cat_pattern_(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F) where - F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat), + fn cat_pattern_(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F) + -> McResult<()> + where F : FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat), { // Here, `cmt` is the categorization for the value being // matched and pat is the pattern it is being matched against. @@ -1208,29 +1215,29 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { Some(&def::DefVariant(..)) => { // variant(x, y, z) for (i, subpat) in subpats.iter().enumerate() { - let subpat_ty = self.pat_ty(&**subpat); // see (*2) + let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2) let subcmt = self.cat_imm_interior( pat, cmt.clone(), subpat_ty, InteriorField(PositionalField(i))); - self.cat_pattern_(subcmt, &**subpat, op); + try!(self.cat_pattern_(subcmt, &**subpat, op)); } } Some(&def::DefStruct(..)) => { for (i, subpat) in subpats.iter().enumerate() { - let subpat_ty = self.pat_ty(&**subpat); // see (*2) + let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2) let cmt_field = self.cat_imm_interior( pat, cmt.clone(), subpat_ty, InteriorField(PositionalField(i))); - self.cat_pattern_(cmt_field, &**subpat, op); + try!(self.cat_pattern_(cmt_field, &**subpat, op)); } } Some(&def::DefConst(..)) => { for subpat in subpats.iter() { - self.cat_pattern_(cmt.clone(), &**subpat, op); + try!(self.cat_pattern_(cmt.clone(), &**subpat, op)); } } _ => { @@ -1242,7 +1249,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } ast::PatIdent(_, _, Some(ref subpat)) => { - self.cat_pattern_(cmt, &**subpat, op); + try!(self.cat_pattern_(cmt, &**subpat, op)); } ast::PatIdent(_, _, None) => { @@ -1252,42 +1259,42 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { ast::PatStruct(_, ref field_pats, _) => { // {f1: p1, ..., fN: pN} for fp in field_pats.iter() { - let field_ty = self.pat_ty(&*fp.node.pat); // see (*2) + let field_ty = try!(self.pat_ty(&*fp.node.pat)); // see (*2) let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.ident.name, field_ty); - self.cat_pattern_(cmt_field, &*fp.node.pat, op); + try!(self.cat_pattern_(cmt_field, &*fp.node.pat, op)); } } ast::PatTup(ref subpats) => { // (p1, ..., pN) for (i, subpat) in subpats.iter().enumerate() { - let subpat_ty = self.pat_ty(&**subpat); // see (*2) + let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2) let subcmt = self.cat_imm_interior( pat, cmt.clone(), subpat_ty, InteriorField(PositionalField(i))); - self.cat_pattern_(subcmt, &**subpat, op); + try!(self.cat_pattern_(subcmt, &**subpat, op)); } } ast::PatBox(ref subpat) | ast::PatRegion(ref subpat) => { // @p1, ~p1, ref p1 - let subcmt = self.cat_deref(pat, cmt, 0, false); - self.cat_pattern_(subcmt, &**subpat, op); + let subcmt = try!(self.cat_deref(pat, cmt, 0, false)); + try!(self.cat_pattern_(subcmt, &**subpat, op)); } ast::PatVec(ref before, ref slice, ref after) => { - let elt_cmt = self.cat_index(pat, self.deref_vec(pat, cmt)); + let elt_cmt = try!(self.cat_index(pat, try!(self.deref_vec(pat, cmt)))); for before_pat in before.iter() { - self.cat_pattern_(elt_cmt.clone(), &**before_pat, op); + try!(self.cat_pattern_(elt_cmt.clone(), &**before_pat, op)); } for slice_pat in slice.iter() { - let slice_ty = self.pat_ty(&**slice_pat); + let slice_ty = try!(self.pat_ty(&**slice_pat)); let slice_cmt = self.cat_rvalue_node(pat.id(), pat.span(), slice_ty); - self.cat_pattern_(slice_cmt, &**slice_pat, op); + try!(self.cat_pattern_(slice_cmt, &**slice_pat, op)); } for after_pat in after.iter() { - self.cat_pattern_(elt_cmt.clone(), &**after_pat, op); + try!(self.cat_pattern_(elt_cmt.clone(), &**after_pat, op)); } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 999bc23c270..079972eff67 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -5708,7 +5708,10 @@ pub fn unboxed_closure_upvars<'tcx>(typer: &mc::Typer<'tcx>, freevars.iter() .map(|freevar| { let freevar_def_id = freevar.def.def_id(); - let freevar_ty = typer.node_ty(freevar_def_id.node); + let freevar_ty = match typer.node_ty(freevar_def_id.node) { + Ok(t) => { t } + Err(()) => { return None; } + }; let freevar_ty = freevar_ty.subst(tcx, substs); match capture_mode { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 19ec85dc61e..189798a1390 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -289,12 +289,17 @@ impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> { self.ccx.tcx } fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> { + fn node_ty(&self, id: ast::NodeId) -> McResult> { let ty = self.node_ty(id); - self.infcx().resolve_type_vars_if_possible(&ty) + self.resolve_type_vars_or_error(&ty) } - fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> { - let ty = self.expr_ty_adjusted(expr); - self.infcx().resolve_type_vars_if_possible(&ty) + fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult> { + let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id)); + self.resolve_type_vars_or_error(&ty) + } + fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool { + let ty = self.infcx().resolve_type_vars_if_possible(&ty); + traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span) } fn node_method_ty(&self, method_call: ty::MethodCall) -> Option> { @@ -1671,6 +1676,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.ccx.tcx.sess.err_count() - self.err_count_on_creation } + /// Resolves all type variables in `t` and then, if any were left + /// unresolved, substitutes an error type. This is used after the + /// main checking when doing a second pass before writeback. The + /// justification is that writeback will produce an error for + /// these unconstrained type variables. + fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult> { + let t = self.infcx().resolve_type_vars_if_possible(t); + if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) } + } + pub fn tag(&self) -> String { format!("{}", self as *const FnCtxt) } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index d01b79068aa..0631b0edb4f 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -140,6 +140,10 @@ use std::collections::hash_map::Entry::{Vacant, Occupied}; use self::RepeatingScope::Repeating; use self::SubjectNode::Subject; +// a variation on try that just returns unit +macro_rules! ignore_err { + ($e:expr) => (match $e { Ok(e) => e, Err(_) => return () }) +} /////////////////////////////////////////////////////////////////////////// // PUBLIC ENTRY POINTS @@ -1027,7 +1031,7 @@ fn constrain_callee(rcx: &mut Rcx, // While we're here, link the closure's region with a unique // immutable borrow (gathered later in borrowck) let mc = mc::MemCategorizationContext::new(rcx.fcx); - let expr_cmt = mc.cat_expr(callee_expr); + let expr_cmt = ignore_err!(mc.cat_expr(callee_expr)); link_region(rcx, callee_expr.span, call_region, ty::UniqueImmBorrow, expr_cmt); r @@ -1136,7 +1140,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, }; { let mc = mc::MemCategorizationContext::new(rcx.fcx); - let self_cmt = mc.cat_expr_autoderefd(deref_expr, i); + let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i)); link_region(rcx, deref_expr.span, *r, ty::BorrowKind::from_mutbl(m), self_cmt); } @@ -1232,7 +1236,7 @@ fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr, let cmt = { let mc = mc::MemCategorizationContext::new(rcx.fcx); - mc.cat_expr(base) + ignore_err!(mc.cat_expr(base)) }; link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt); } @@ -1247,7 +1251,7 @@ fn link_local(rcx: &Rcx, local: &ast::Local) { Some(ref expr) => &**expr, }; let mc = mc::MemCategorizationContext::new(rcx.fcx); - let discr_cmt = mc.cat_expr(init_expr); + let discr_cmt = ignore_err!(mc.cat_expr(init_expr)); link_pattern(rcx, mc, discr_cmt, &*local.pat); } @@ -1257,7 +1261,7 @@ fn link_local(rcx: &Rcx, local: &ast::Local) { fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) { debug!("regionck::for_match()"); let mc = mc::MemCategorizationContext::new(rcx.fcx); - let discr_cmt = mc.cat_expr(discr); + let discr_cmt = ignore_err!(mc.cat_expr(discr)); debug!("discr_cmt={}", discr_cmt.repr(rcx.tcx())); for arm in arms.iter() { for root_pat in arm.pats.iter() { @@ -1303,11 +1307,14 @@ fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, // `[_, ..slice, _]` pattern ast::PatVec(_, Some(ref slice_pat), _) => { - let (slice_cmt, slice_mutbl, slice_r) = - mc.cat_slice_pattern(sub_cmt, &**slice_pat); - link_region(rcx, sub_pat.span, slice_r, - ty::BorrowKind::from_mutbl(slice_mutbl), - slice_cmt); + match mc.cat_slice_pattern(sub_cmt, &**slice_pat) { + Ok((slice_cmt, slice_mutbl, slice_r)) => { + link_region(rcx, sub_pat.span, slice_r, + ty::BorrowKind::from_mutbl(slice_mutbl), + slice_cmt); + } + Err(()) => {} + } } _ => {} } @@ -1323,7 +1330,7 @@ fn link_autoref(rcx: &Rcx, debug!("link_autoref(autoref={})", autoref); let mc = mc::MemCategorizationContext::new(rcx.fcx); - let expr_cmt = mc.cat_expr_autoderefd(expr, autoderefs); + let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs)); debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx())); match *autoref { @@ -1345,7 +1352,7 @@ fn link_by_ref(rcx: &Rcx, debug!("link_by_ref(expr={}, callee_scope={})", expr.repr(tcx), callee_scope); let mc = mc::MemCategorizationContext::new(rcx.fcx); - let expr_cmt = mc.cat_expr(expr); + let expr_cmt = ignore_err!(mc.cat_expr(expr)); let borrow_region = ty::ReScope(callee_scope); link_region(rcx, expr.span, borrow_region, ty::ImmBorrow, expr_cmt); }