diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 3e2d26aa518..b3e5f13de2c 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -393,27 +393,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { fresh_tables: env.fresh_tables().map(RefCell::new), } } - - /// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck - /// for MemCategorizationContext/ExprUseVisitor. - /// If any inference functionality is used, ICEs will occur. - pub fn borrowck_fake_infer_ctxt(self) -> InferCtxt<'a, 'gcx, 'gcx> { - InferCtxt { - tcx: self, - tables: InferTables::Missing, - type_variables: RefCell::new(type_variable::TypeVariableTable::new()), - int_unification_table: RefCell::new(UnificationTable::new()), - float_unification_table: RefCell::new(UnificationTable::new()), - region_vars: RegionVarBindings::new(self), - selection_cache: traits::SelectionCache::new(), - evaluation_cache: traits::EvaluationCache::new(), - projection_cache: RefCell::new(traits::ProjectionCache::new()), - reported_trait_errors: RefCell::new(FxHashSet()), - tainted_by_errors_flag: Cell::new(false), - err_count_on_creation: self.sess.err_count(), - in_snapshot: Cell::new(false), - } - } } impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index b24b2a616b0..58e77f40d98 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -261,16 +261,32 @@ macro_rules! return_if_err { ) } -impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { +impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> { pub fn new(delegate: &'a mut (Delegate<'tcx>+'a), - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, region_maps: &'a RegionMaps, tables: &'a ty::TypeckTables<'tcx>) -> Self { ExprUseVisitor { - mc: mc::MemCategorizationContext::new(infcx, region_maps, tables), + mc: mc::MemCategorizationContext::new(tcx, region_maps, tables), + delegate, + param_env, + } + } +} + +impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { + pub fn with_infer(delegate: &'a mut (Delegate<'tcx>+'a), + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + region_maps: &'a RegionMaps, + tables: &'a ty::TypeckTables<'tcx>) + -> Self + { + ExprUseVisitor { + mc: mc::MemCategorizationContext::with_infer(infcx, region_maps, tables), delegate, param_env, } @@ -296,7 +312,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { - self.mc.infcx.tcx + self.mc.tcx } fn delegate_consume(&mut self, @@ -306,7 +322,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("delegate_consume(consume_id={}, cmt={:?})", consume_id, cmt); - let mode = copy_or_move(self.mc.infcx, self.param_env, &cmt, DirectRefMove); + let mode = copy_or_move(&self.mc, self.param_env, &cmt, DirectRefMove); self.delegate.consume(consume_id, consume_span, cmt, mode); } @@ -784,7 +800,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { PatKind::Binding(hir::BindByRef(..), ..) => mode.lub(BorrowingMatch), PatKind::Binding(hir::BindByValue(..), ..) => { - match copy_or_move(self.mc.infcx, self.param_env, &cmt_pat, PatBindingMove) { + match copy_or_move(&self.mc, self.param_env, &cmt_pat, PatBindingMove) { Copy => mode.lub(CopyingMatch), Move(..) => mode.lub(MovingMatch), } @@ -801,7 +817,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat); let tcx = self.tcx(); - let infcx = self.mc.infcx; let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self; return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { if let PatKind::Binding(bmode, def_id, ..) = pat.node { @@ -826,7 +841,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } } hir::BindByValue(..) => { - let mode = copy_or_move(infcx, param_env, &cmt_pat, PatBindingMove); + let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove); debug!("walk_pat binding consuming pat"); delegate.consume_pat(pat, cmt_pat, mode); } @@ -885,7 +900,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { freevar.def)); match upvar_capture { ty::UpvarCapture::ByValue => { - let mode = copy_or_move(self.mc.infcx, + let mode = copy_or_move(&self.mc, self.param_env, &cmt_var, CaptureMove); @@ -917,13 +932,13 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } } -fn copy_or_move<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, +fn copy_or_move<'a, 'gcx, 'tcx>(mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, cmt: &mc::cmt<'tcx>, move_reason: MoveReason) -> ConsumeMode { - if infcx.type_moves_by_default(param_env, cmt.ty, cmt.span) { + if mc.type_moves_by_default(param_env, cmt.ty, cmt.span) { Move(move_reason) } else { Copy diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 66de8bc5803..259079cf160 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -282,9 +282,10 @@ impl ast_node for hir::Pat { #[derive(Clone)] pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + pub tcx: TyCtxt<'a, 'gcx, 'tcx>, pub region_maps: &'a RegionMaps, pub tables: &'a ty::TypeckTables<'tcx>, + infcx: Option<&'a InferCtxt<'a, 'gcx, 'tcx>>, } pub type McResult = Result; @@ -385,27 +386,51 @@ impl MutabilityCategory { } } -impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { - /// Context should be the `DefId` we use to fetch region-maps. - pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, +impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, region_maps: &'a RegionMaps, tables: &'a ty::TypeckTables<'tcx>) - -> MemCategorizationContext<'a, 'gcx, 'tcx> { - MemCategorizationContext { infcx, region_maps, tables } + -> MemCategorizationContext<'a, 'tcx, 'tcx> { + MemCategorizationContext { tcx, region_maps, tables, infcx: None } + } +} + +impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { + pub fn with_infer(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + region_maps: &'a RegionMaps, + tables: &'a ty::TypeckTables<'tcx>) + -> MemCategorizationContext<'a, 'gcx, 'tcx> { + MemCategorizationContext { + tcx: infcx.tcx, + region_maps, + tables, + infcx: Some(infcx), + } } - fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { - self.infcx.tcx + pub fn type_moves_by_default(&self, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + span: Span) + -> bool { + self.infcx.map(|infcx| infcx.type_moves_by_default(param_env, ty, span)) + .or_else(|| { + self.tcx.lift_to_global(&(param_env, ty)).map(|(param_env, ty)| { + ty.moves_by_default(self.tcx.global_tcx(), param_env, span) + }) + }) + .unwrap_or(true) } fn resolve_type_vars_if_possible(&self, value: &T) -> T where T: TypeFoldable<'tcx> { - self.infcx.resolve_type_vars_if_possible(value) + self.infcx.map(|infcx| infcx.resolve_type_vars_if_possible(value)) + .unwrap_or_else(|| value.clone()) } fn is_tainted_by_errors(&self) -> bool { - self.infcx.is_tainted_by_errors() + self.infcx.map_or(false, |infcx| infcx.is_tainted_by_errors()) } fn resolve_type_vars_or_error(&self, @@ -426,7 +451,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { None if self.is_tainted_by_errors() => Err(()), None => { bug!("no type for node {}: {} in mem_categorization", - id, self.tcx().hir.node_to_string(id)); + id, self.tcx.hir.node_to_string(id)); } } } @@ -506,7 +531,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { adjustment::Adjust::Deref(overloaded) => { // Equivalent to *expr or something similar. let base = if let Some(deref) = overloaded { - let ref_ty = self.tcx().mk_ref(deref.region, ty::TypeAndMut { + let ref_ty = self.tcx.mk_ref(deref.region, ty::TypeAndMut { ty: target, mutbl: deref.mutbl, }); @@ -624,17 +649,17 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } Def::Upvar(def_id, _, fn_node_id) => { - let var_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); + let var_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); self.cat_upvar(id, span, var_id, fn_node_id) } Def::Local(def_id) => { - let vid = self.tcx().hir.as_local_node_id(def_id).unwrap(); + let vid = self.tcx.hir.as_local_node_id(def_id).unwrap(); Ok(Rc::new(cmt_ { id: id, span: span, cat: Categorization::Local(vid), - mutbl: MutabilityCategory::from_local(self.tcx(), vid), + mutbl: MutabilityCategory::from_local(self.tcx, vid), ty: expr_ty, note: NoteNone })) @@ -686,7 +711,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let var_ty = self.node_ty(var_id)?; // Mutability of original variable itself - let var_mutbl = MutabilityCategory::from_local(self.tcx(), var_id); + let var_mutbl = MutabilityCategory::from_local(self.tcx, var_id); // Construct the upvar. This represents access to the field // from the environment (perhaps we should eventually desugar @@ -753,11 +778,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { -> cmt_<'tcx> { // Region of environment pointer - let env_region = self.tcx().mk_region(ty::ReFree(ty::FreeRegion { + let env_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { // The environment of a closure is guaranteed to // outlive any bindings introduced in the body of the // closure itself. - scope: self.tcx().hir.local_def_id(upvar_id.closure_expr_id), + scope: self.tcx.hir.local_def_id(upvar_id.closure_expr_id), bound_region: ty::BrEnv })); @@ -774,7 +799,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // one. let cmt_result = cmt_ { mutbl: McImmutable, - ty: self.tcx().types.err, + ty: self.tcx.types.err, ..cmt_result }; @@ -806,7 +831,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { pub fn temporary_scope(&self, id: ast::NodeId) -> ty::Region<'tcx> { let scope = self.region_maps.temporary_scope(id); - self.tcx().mk_region(match scope { + self.tcx.mk_region(match scope { Some(scope) => ty::ReScope(scope), None => ty::ReStatic }) @@ -817,20 +842,20 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { span: Span, expr_ty: Ty<'tcx>) -> cmt<'tcx> { - let promotable = self.tcx().rvalue_promotable_to_static.borrow().get(&id).cloned() + let promotable = self.tcx.rvalue_promotable_to_static.borrow().get(&id).cloned() .unwrap_or(false); // When the corresponding feature isn't toggled, only promote `[T; 0]`. let promotable = match expr_ty.sty { ty::TyArray(_, 0) => true, - _ => promotable && self.tcx().sess.features.borrow().rvalue_static_promotion, + _ => promotable && self.tcx.sess.features.borrow().rvalue_static_promotion, }; // Compute maximum lifetime of this rvalue. This is 'static if // we can promote to a constant, otherwise equal to enclosing temp // lifetime. let re = if promotable { - self.tcx().types.re_static + self.tcx.types.re_static } else { self.temporary_scope(id) }; @@ -911,7 +936,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { span_bug!(expr.span, "cat_overloaded_lvalue: base is not a reference") } }; - let ref_ty = self.tcx().mk_ref(region, ty::TypeAndMut { + let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { ty: lvalue_ty, mutbl, }); @@ -1098,8 +1123,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { Def::Variant(variant_did) | Def::VariantCtor(variant_did, ..) => { // univariant enums do not need downcasts - let enum_did = self.tcx().parent_def_id(variant_did).unwrap(); - if !self.tcx().adt_def(enum_did).is_univariant() { + let enum_did = self.tcx.parent_def_id(variant_did).unwrap(); + if !self.tcx.adt_def(enum_did).is_univariant() { self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did) } else { cmt @@ -1116,8 +1141,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let def = self.tables.qpath_def(qpath, pat.id); let expected_len = match def { Def::VariantCtor(def_id, CtorKind::Fn) => { - let enum_def = self.tcx().parent_def_id(def_id).unwrap(); - self.tcx().adt_def(enum_def).variant_with_id(def_id).fields.len() + let enum_def = self.tcx.parent_def_id(def_id).unwrap(); + self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len() } Def::StructCtor(_, CtorKind::Fn) => { match self.pat_ty(&pat)?.sty { diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index a47ec35d265..ae2be28c198 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -200,8 +200,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, all_loans: all_loans, param_env, }; - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(); - euv::ExprUseVisitor::new(&mut clcx, &infcx, param_env, &bccx.region_maps, bccx.tables) + euv::ExprUseVisitor::new(&mut clcx, bccx.tcx, param_env, &bccx.region_maps, bccx.tables) .consume_body(body); } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index ae68fb651f6..7dcb6ce76a4 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -49,8 +49,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, }; let body = glcx.bccx.tcx.hir.body(body); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(); - euv::ExprUseVisitor::new(&mut glcx, &infcx, param_env, &bccx.region_maps, bccx.tables) + euv::ExprUseVisitor::new(&mut glcx, bccx.tcx, param_env, &bccx.region_maps, bccx.tables) .consume_body(body); glcx.report_potential_errors(); diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 17cb60792c6..fcdabf89e3c 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -493,20 +493,18 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, /// /// FIXME: this should be done by borrowck. fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) { - cx.tcx.infer_ctxt(()).enter(|infcx| { - let mut checker = MutationChecker { - cx: cx, - }; - ExprUseVisitor::new(&mut checker, &infcx, cx.param_env, cx.region_maps, cx.tables) - .walk_expr(guard); - }); + let mut checker = MutationChecker { + cx: cx, + }; + ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_maps, cx.tables) + .walk_expr(guard); } -struct MutationChecker<'a, 'gcx: 'a> { - cx: &'a MatchVisitor<'a, 'gcx>, +struct MutationChecker<'a, 'tcx: 'a> { + cx: &'a MatchVisitor<'a, 'tcx>, } -impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> { +impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> { fn matched_pat(&mut self, _: &Pat, _: cmt, _: euv::MatchMode) {} fn consume(&mut self, _: ast::NodeId, _: Span, _: cmt, _: ConsumeMode) {} fn consume_pat(&mut self, _: &Pat, _: cmt, _: ConsumeMode) {} diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index f7889385688..e539cc1ae8b 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -51,7 +51,6 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use std::collections::hash_map::Entry; use std::cmp::Ordering; -use std::mem; struct CheckCrateVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -138,14 +137,14 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { self.check_const_eval(&body.value); } - let outer_penv = self.tcx.infer_ctxt(()).enter(|infcx| { - let param_env = self.tcx.param_env(item_def_id); - let outer_penv = mem::replace(&mut self.param_env, param_env); - let region_maps = &self.tcx.region_maps(item_def_id); - euv::ExprUseVisitor::new(self, &infcx, param_env, region_maps, self.tables) - .consume_body(body); - outer_penv - }); + let outer_penv = self.param_env; + self.param_env = self.tcx.param_env(item_def_id); + + let tcx = self.tcx; + let param_env = self.param_env; + let region_maps = self.tcx.region_maps(item_def_id); + euv::ExprUseVisitor::new(self, tcx, param_env, ®ion_maps, self.tables) + .consume_body(body); self.visit_body(body); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 616de1fc412..952321c946b 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -828,9 +828,9 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { fn with_mc(&self, f: F) -> R where F: for<'b> FnOnce(mc::MemCategorizationContext<'b, 'gcx, 'tcx>) -> R { - f(mc::MemCategorizationContext::new(&self.infcx, - &self.region_maps, - &self.tables.borrow())) + f(mc::MemCategorizationContext::with_infer(&self.infcx, + &self.region_maps, + &self.tables.borrow())) } /// Invoked on any adjustments that occur. Checks that if this is a region pointer being diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 400ca59e143..59ca896b347 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -142,11 +142,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { adjust_closure_kinds: NodeMap(), adjust_upvar_captures: ty::UpvarCaptureMap::default(), }; - euv::ExprUseVisitor::new(&mut delegate, - &self.infcx, - self.param_env, - region_maps, - &self.tables.borrow()) + euv::ExprUseVisitor::with_infer(&mut delegate, + &self.infcx, + self.param_env, + region_maps, + &self.tables.borrow()) .consume_body(body); // Write the adjusted values back into the main tables.