diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index d2c79e1d820..ad87643e550 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -26,7 +26,6 @@ use metadata::tydecode::{RegionParameter, ClosureSource}; use metadata::tyencode; use middle::cast; use middle::check_const::ConstQualif; -use middle::mem_categorization::Typer; use middle::privacy::{AllPublic, LastMod}; use middle::subst; use middle::subst::VecPerParamSpace; diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 8bbb6ae757f..19b688e5ccf 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -110,14 +110,16 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { } fn with_euv<'b, F, R>(&'b mut self, item_id: Option, f: F) -> R where - F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'tcx, - ty::ParameterEnvironment<'a, 'tcx>>) -> R, + F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'b, 'tcx>) -> R, { let param_env = match item_id { Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id), None => self.tcx.empty_parameter_environment() }; - f(&mut euv::ExprUseVisitor::new(self, ¶m_env)) + + let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env), false); + + f(&mut euv::ExprUseVisitor::new(self, &infcx)) } fn global_expr(&mut self, mode: Mode, expr: &ast::Expr) -> ConstQualif { @@ -283,11 +285,11 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { fn check_static_type(&self, e: &ast::Expr) { let ty = self.tcx.node_id_to_type(e.id); - let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None); - let mut fulfill_cx = traits::FulfillmentContext::new(false); + let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None, false); let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic); + let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut(); fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause); - match fulfill_cx.select_all_or_error(&infcx, &infcx.parameter_environment) { + match fulfill_cx.select_all_or_error(&infcx) { Ok(()) => { }, Err(ref errors) => { traits::report_fulfillment_errors(&infcx, errors); diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index f61884e2136..a303c49bf8d 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -20,7 +20,8 @@ use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Init}; use middle::expr_use_visitor::{JustWrite, LoanCause, MutateMode}; use middle::expr_use_visitor::WriteAndRead; use middle::expr_use_visitor as euv; -use middle::mem_categorization::{cmt, Typer}; +use middle::infer; +use middle::mem_categorization::{cmt}; use middle::pat_util::*; use middle::ty::*; use middle::ty; @@ -1111,7 +1112,12 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, match p.node { ast::PatIdent(ast::BindByValue(_), _, ref sub) => { let pat_ty = tcx.node_id_to_type(p.id); - if cx.param_env.type_moves_by_default(pat_ty, pat.span) { + //FIXME: (@jroesch) this code should be floated up as well + let infcx = infer::new_infer_ctxt(cx.tcx, + &cx.tcx.tables, + Some(cx.param_env.clone()), + false); + if infcx.type_moves_by_default(pat_ty, pat.span) { check_move(p, sub.as_ref().map(|p| &**p)); } } @@ -1139,8 +1145,13 @@ fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>, let mut checker = MutationChecker { cx: cx, }; - let mut visitor = ExprUseVisitor::new(&mut checker, - &checker.cx.param_env); + + let infcx = infer::new_infer_ctxt(cx.tcx, + &cx.tcx.tables, + Some(checker.cx.param_env.clone()), + false); + + let mut visitor = ExprUseVisitor::new(&mut checker, &infcx); visitor.walk_expr(guard); } diff --git a/src/librustc/middle/check_rvalues.rs b/src/librustc/middle/check_rvalues.rs index 1489e946fe2..c9017432473 100644 --- a/src/librustc/middle/check_rvalues.rs +++ b/src/librustc/middle/check_rvalues.rs @@ -12,6 +12,7 @@ // is the public starting point. use middle::expr_use_visitor as euv; +use middle::infer; use middle::mem_categorization as mc; use middle::ty::ParameterEnvironment; use middle::ty; @@ -38,9 +39,14 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for RvalueContext<'a, 'tcx> { s: Span, fn_id: ast::NodeId) { { + // FIXME (@jroesch) change this to be an inference context let param_env = ParameterEnvironment::for_item(self.tcx, fn_id); + let infcx = infer::new_infer_ctxt(self.tcx, + &self.tcx.tables, + Some(param_env.clone()), + false); let mut delegate = RvalueContextDelegate { tcx: self.tcx, param_env: ¶m_env }; - let mut euv = euv::ExprUseVisitor::new(&mut delegate, ¶m_env); + let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx); euv.walk_fn(fd, b); } visit::walk_fn(self, fk, fd, b, s) diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index a6b7d7f832a..7d54b8c284f 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -1031,9 +1031,9 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>, substs: trait_substs }); tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id()); - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None); + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false); - let mut selcx = traits::SelectionContext::new(&infcx, &infcx.parameter_environment); + let mut selcx = traits::SelectionContext::new(&infcx); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), trait_ref.to_poly_trait_predicate()); let selection = match selcx.select(&obligation) { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 25728c50c61..3edf0490214 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -21,8 +21,8 @@ use self::TrackMatchMode::*; use self::OverloadedCallType::*; use middle::{def, region, pat_util}; +use middle::infer; use middle::mem_categorization as mc; -use middle::mem_categorization::Typer; use middle::ty::{self}; use middle::ty::{MethodCall, MethodObject, MethodTraitObject}; use middle::ty::{MethodOrigin, MethodParam, MethodTypeParam}; @@ -291,9 +291,9 @@ impl OverloadedCallType { // supplies types from the tree. After type checking is complete, you // can just use the tcx as the typer. -pub struct ExprUseVisitor<'d,'t,'tcx:'t,TYPER:'t> { - typer: &'t TYPER, - mc: mc::MemCategorizationContext<'t,TYPER>, +pub struct ExprUseVisitor<'d,'t,'a: 't, 'tcx:'a> { + typer: &'t infer::InferCtxt<'a, 'tcx>, + mc: mc::MemCategorizationContext<'t, 'a, 'tcx>, delegate: &'d mut (Delegate<'tcx>+'d), } @@ -319,10 +319,10 @@ enum PassArgs { ByRef, } -impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { +impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> { pub fn new(delegate: &'d mut Delegate<'tcx>, - typer: &'t TYPER) - -> ExprUseVisitor<'d,'t,'tcx,TYPER> { + typer: &'t infer::InferCtxt<'a, 'tcx>) + -> ExprUseVisitor<'d,'t,'a, 'tcx> { ExprUseVisitor { typer: typer, mc: mc::MemCategorizationContext::new(typer), @@ -355,7 +355,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } fn tcx(&self) -> &'t ty::ctxt<'tcx> { - self.typer.tcx() + self.typer.tcx } fn delegate_consume(&mut self, @@ -690,7 +690,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { match local.init { None => { let delegate = &mut self.delegate; - pat_util::pat_bindings(&self.typer.tcx().def_map, &*local.pat, + pat_util::pat_bindings(&self.typer.tcx.def_map, &*local.pat, |_, id, span, _| { delegate.decl_without_init(id, span); }) @@ -1052,7 +1052,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { let delegate = &mut self.delegate; 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(); + let tcx = typer.tcx; debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, @@ -1139,7 +1139,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // the leaves of the pattern tree structure. return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| { let def_map = def_map.borrow(); - let tcx = typer.tcx(); + let tcx = typer.tcx; match pat.node { ast::PatEnum(_, _) | ast::PatQPath(..) | @@ -1278,7 +1278,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } } -fn copy_or_move<'tcx>(typer: &mc::Typer<'tcx>, +fn copy_or_move<'a, 'tcx>(typer: &infer::InferCtxt<'a, 'tcx>, cmt: &mc::cmt<'tcx>, move_reason: MoveReason) -> ConsumeMode diff --git a/src/librustc/middle/implicator.rs b/src/librustc/middle/implicator.rs index d5fa885b16a..3e097578857 100644 --- a/src/librustc/middle/implicator.rs +++ b/src/librustc/middle/implicator.rs @@ -34,7 +34,6 @@ pub enum Implication<'tcx> { struct Implicator<'a, 'tcx: 'a> { infcx: &'a InferCtxt<'a,'tcx>, - closure_typer: &'a (ty::ClosureTyper<'tcx>+'a), body_id: ast::NodeId, stack: Vec<(ty::Region, Option>)>, span: Span, @@ -46,7 +45,6 @@ struct Implicator<'a, 'tcx: 'a> { /// appear in a context with lifetime `outer_region` pub fn implications<'a,'tcx>( infcx: &'a InferCtxt<'a,'tcx>, - closure_typer: &ty::ClosureTyper<'tcx>, body_id: ast::NodeId, ty: Ty<'tcx>, outer_region: ty::Region, @@ -60,8 +58,7 @@ pub fn implications<'a,'tcx>( let mut stack = Vec::new(); stack.push((outer_region, None)); - let mut wf = Implicator { closure_typer: closure_typer, - infcx: infcx, + let mut wf = Implicator { infcx: infcx, body_id: body_id, span: span, stack: stack, @@ -404,7 +401,6 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> { { let value = traits::fully_normalize(self.infcx, - self.closure_typer, traits::ObligationCause::misc(self.span, self.body_id), value); match value { diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index c355e8b82a6..7df37bdae07 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -29,7 +29,8 @@ use middle::region::CodeExtent; use middle::subst; use middle::subst::Substs; use middle::subst::Subst; -use middle::traits; +use middle::traits::{self, FulfillmentContext, Normalized, + SelectionContext, ObligationCause}; use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric}; use middle::ty::{self, Ty, HasTypeFlags}; use middle::ty_fold::{self, TypeFolder, TypeFoldable}; @@ -39,7 +40,7 @@ use std::cell::{RefCell, Ref}; use std::fmt; use syntax::ast; use syntax::codemap; -use syntax::codemap::Span; +use syntax::codemap::{Span, DUMMY_SP}; use util::nodemap::{FnvHashMap, NodeMap}; use self::combine::CombineFields; @@ -87,6 +88,8 @@ pub struct InferCtxt<'a, 'tcx: 'a> { pub parameter_environment: ty::ParameterEnvironment<'a, 'tcx>, + pub fulfillment_cx: RefCell>, + // This is a temporary field used for toggling on normalization in the inference context, // as we move towards the approach described here: // https://internals.rust-lang.org/t/flattening-the-contexts-for-fun-and-profit/2293 @@ -327,9 +330,16 @@ pub fn fixup_err_to_string(f: fixup_err) -> String { } } +/// errors_will_be_reported is required to proxy to the fulfillment context +/// FIXME -- a better option would be to hold back on modifying +/// the global cache until we know that all dependent obligations +/// are also satisfied. In that case, we could actually remove +/// this boolean flag, and we'd also avoid the problem of squelching +/// duplicate errors that occur across fns. pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>, tables: &'a RefCell>, - param_env: Option>) + param_env: Option>, + errors_will_be_reported: bool) -> InferCtxt<'a, 'tcx> { InferCtxt { tcx: tcx, @@ -339,11 +349,20 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>, float_unification_table: RefCell::new(UnificationTable::new()), region_vars: RegionVarBindings::new(tcx), parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()), + fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(errors_will_be_reported)), normalize: false, err_count_on_creation: tcx.sess.err_count() } } +pub fn normalizing_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>, + tables: &'a RefCell>) + -> InferCtxt<'a, 'tcx> { + let mut infcx = new_infer_ctxt(tcx, tables, None, false); + infcx.normalize = true; + infcx +} + /// Computes the least upper-bound of `a` and `b`. If this is not possible, reports an error and /// returns ty::err. pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, @@ -455,123 +474,145 @@ pub struct CombinedSnapshot { region_vars_snapshot: RegionSnapshot, } -impl<'a, 'tcx> mc::Typer<'tcx> for InferCtxt<'a, 'tcx> { - fn node_ty(&self, id: ast::NodeId) -> McResult> { - let ty = self.node_ty(id); - self.resolve_type_vars_or_error(&ty) +pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T + where T : TypeFoldable<'tcx> + HasTypeFlags +{ + debug!("normalize_associated_type(t={:?})", value); + + let value = erase_regions(tcx, value); + + if !value.has_projection_types() { + return value; } - fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult> { - let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id)); - self.resolve_type_vars_or_error(&ty) + let infcx = new_infer_ctxt(tcx, &tcx.tables, None, true); + let mut selcx = traits::SelectionContext::new(&infcx); + let cause = traits::ObligationCause::dummy(); + let traits::Normalized { value: result, obligations } = + traits::normalize(&mut selcx, cause, &value); + + debug!("normalize_associated_type: result={:?} obligations={:?}", + result, + obligations); + + let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut(); + + for obligation in obligations { + fulfill_cx.register_predicate_obligation(&infcx, obligation); } - fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool { - let ty = self.resolve_type_vars_if_possible(&ty); - !traits::type_known_to_meet_builtin_bound(self, self, ty, ty::BoundCopy, span) - } + let result = drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result); - fn node_method_ty(&self, method_call: ty::MethodCall) - -> Option> { - self.tables - .borrow() - .method_map - .get(&method_call) - .map(|method| method.ty) - .map(|ty| self.resolve_type_vars_if_possible(&ty)) - } + result +} - fn node_method_origin(&self, method_call: ty::MethodCall) - -> Option> - { - self.tables - .borrow() - .method_map - .get(&method_call) - .map(|method| method.origin.clone()) - } - - fn adjustments(&self) -> Ref>> { - fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) - -> &'a NodeMap> { - &tables.adjustments +pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span, + infcx: &InferCtxt<'a,'tcx>, + fulfill_cx: &mut traits::FulfillmentContext<'tcx>, + result: &T) + -> T + where T : TypeFoldable<'tcx> +{ + match drain_fulfillment_cx(infcx, fulfill_cx, result) { + Ok(v) => v, + Err(errors) => { + infcx.tcx.sess.span_bug( + span, + &format!("Encountered errors `{:?}` fulfilling during trans", + errors)); } - - Ref::map(self.tables.borrow(), project_adjustments) - } - - fn is_method_call(&self, id: ast::NodeId) -> bool { - self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id)) - } - - fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option { - self.parameter_environment.temporary_scope(rvalue_id) - } - - fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option { - self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned() } } -impl<'a, 'tcx> ty::ClosureTyper<'tcx> for InferCtxt<'a, 'tcx> { - fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> { - &self.parameter_environment - } +/// Finishes processes any obligations that remain in the fulfillment +/// context, and then "freshens" and returns `result`. This is +/// primarily used during normalization and other cases where +/// processing the obligations in `fulfill_cx` may cause type +/// inference variables that appear in `result` to be unified, and +/// hence we need to process those obligations to get the complete +/// picture of the type. +pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, + fulfill_cx: &mut traits::FulfillmentContext<'tcx>, + result: &T) + -> Result>> + where T : TypeFoldable<'tcx> +{ + debug!("drain_fulfillment_cx(result={:?})", + result); - fn closure_kind(&self, - def_id: ast::DefId) - -> Option - { - self.tables.borrow().closure_kinds.get(&def_id).cloned() - } - - fn closure_type(&self, - def_id: ast::DefId, - substs: &subst::Substs<'tcx>) - -> ty::ClosureTy<'tcx> - { - - let closure_ty = self.tables - .borrow() - .closure_tys - .get(&def_id) - .unwrap() - .subst(self.tcx, substs); - - if self.normalize { - // NOTE: this flag is currently *always* set to false, we are slowly folding - // normalization into this trait and will come back to remove this in the near - // future. - - // code from NormalizingClosureTyper: - // the substitutions in `substs` are already monomorphized, - // but we still must normalize associated types - // normalize_associated_type(self.param_env.tcx, &closure_ty) - panic!("see issue 26597: fufillment context refactor must occur") - } else { - closure_ty + // In principle, we only need to do this so long as `result` + // contains unbound type parameters. It could be a slight + // optimization to stop iterating early. + match fulfill_cx.select_all_or_error(infcx) { + Ok(()) => { } + Err(errors) => { + return Err(errors); } } - fn closure_upvars(&self, - def_id: ast::DefId, - substs: &Substs<'tcx>) - -> Option>> - { - let result = ty::ctxt::closure_upvars(self, def_id, substs); + // Use freshen to simultaneously replace all type variables with + // their bindings and replace all regions with 'static. This is + // sort of overkill because we do not expect there to be any + // unbound type variables, hence no `TyFresh` types should ever be + // inserted. + Ok(result.fold_with(&mut infcx.freshener())) +} - if self.normalize { - // NOTE: this flag is currently *always* set to false, we are slowly folding - // normalization into this trait and will come back to remove this in the near - // future. +/// Returns an equivalent value with all free regions removed (note +/// that late-bound regions remain, because they are important for +/// subtyping, but they are anonymized and normalized as well). This +/// is a stronger, caching version of `ty_fold::erase_regions`. +pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T + where T : TypeFoldable<'tcx> +{ + let value1 = value.fold_with(&mut RegionEraser(cx)); + debug!("erase_regions({:?}) = {:?}", + value, value1); + return value1; - // code from NormalizingClosureTyper: - // the substitutions in `substs` are already monomorphized, - // but we still must normalize associated types - // monomorphize::normalize_associated_type(self.param_env.tcx, &result) - panic!("see issue 26597: fufillment context refactor must occur") - } else { - result + struct RegionEraser<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>); + + impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> { + fn tcx(&self) -> &ty::ctxt<'tcx> { self.0 } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + match self.tcx().normalized_cache.borrow().get(&ty).cloned() { + None => {} + Some(u) => return u + } + + let t_norm = ty_fold::super_fold_ty(self, ty); + self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm); + return t_norm; + } + + fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder + where T : TypeFoldable<'tcx> + { + let u = self.tcx().anonymize_late_bound_regions(t); + ty_fold::super_fold_binder(self, &u) + } + + fn fold_region(&mut self, r: ty::Region) -> ty::Region { + // because late-bound regions affect subtyping, we can't + // erase the bound/free distinction, but we can replace + // all free regions with 'static. + // + // Note that we *CAN* replace early-bound regions -- the + // type system never "sees" those, they get substituted + // away. In trans, they will always be erased to 'static + // whenever a substitution occurs. + match r { + ty::ReLateBound(..) => r, + _ => ty::ReStatic + } + } + + fn fold_substs(&mut self, + substs: &subst::Substs<'tcx>) + -> subst::Substs<'tcx> { + subst::Substs { regions: subst::ErasedRegions, + types: substs.types.fold_with(self) } } } } @@ -1017,7 +1058,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .map(|method| resolve_ty(method.ty))) } - pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> { + pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> { match self.tables.borrow().node_types.get(&id) { Some(&t) => t, // FIXME @@ -1263,6 +1304,109 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.equate(true, trace).relate(a, b) }).map(|_| ()) } + + pub fn node_ty(&self, id: ast::NodeId) -> McResult> { + let ty = self.node_type(id); + self.resolve_type_vars_or_error(&ty) + } + + pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult> { + let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id)); + self.resolve_type_vars_or_error(&ty) + } + + pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool { + let ty = self.resolve_type_vars_if_possible(&ty); + !traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span) + // FIXME(@jroesch): should be able to use: + // ty.moves_by_default(&self.parameter_environment, span) + } + + pub fn node_method_ty(&self, method_call: ty::MethodCall) + -> Option> { + self.tables + .borrow() + .method_map + .get(&method_call) + .map(|method| method.ty) + .map(|ty| self.resolve_type_vars_if_possible(&ty)) + } + + pub fn node_method_origin(&self, method_call: ty::MethodCall) + -> Option> + { + self.tables + .borrow() + .method_map + .get(&method_call) + .map(|method| method.origin.clone()) + } + + pub fn adjustments(&self) -> Ref>> { + fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) + -> &'a NodeMap> { + &tables.adjustments + } + + Ref::map(self.tables.borrow(), project_adjustments) + } + + pub fn is_method_call(&self, id: ast::NodeId) -> bool { + self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id)) + } + + pub fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option { + self.tcx.region_maps.temporary_scope(rvalue_id) + } + + pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option { + self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned() + } + + pub fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> { + &self.parameter_environment + } + + pub fn closure_kind(&self, + def_id: ast::DefId) + -> Option + { + self.tables.borrow().closure_kinds.get(&def_id).cloned() + } + + pub fn closure_type(&self, + def_id: ast::DefId, + substs: &subst::Substs<'tcx>) + -> ty::ClosureTy<'tcx> + { + + let closure_ty = self.tables + .borrow() + .closure_tys + .get(&def_id) + .unwrap() + .subst(self.tcx, substs); + + if self.normalize { + normalize_associated_type(&self.tcx, &closure_ty) + } else { + closure_ty + } + } + + pub fn closure_upvars(&self, + def_id: ast::DefId, + substs: &Substs<'tcx>) + -> Option>> + { + let result = ty::ctxt::closure_upvars(self, def_id, substs); + + if self.normalize { + normalize_associated_type(&self.tcx, &result) + } else { + result + } + } } impl<'tcx> TypeTrace<'tcx> { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 7d237a511c4..68001ae1564 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -110,11 +110,9 @@ use self::LiveNodeKind::*; use self::VarKind::*; use middle::def::*; -use middle::mem_categorization::Typer; use middle::pat_util; use middle::region; use middle::ty; -use middle::ty::ClosureTyper; use lint; use util::nodemap::NodeMap; diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 13e127e9126..f506de525ff 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -73,17 +73,16 @@ pub use self::categorization::*; use self::Aliasability::*; use ast_map; +use middle::infer; use middle::check_const; use middle::def; use middle::region; use middle::ty::{self, Ty}; -use util::nodemap::NodeMap; use syntax::ast::{MutImmutable, MutMutable}; use syntax::ast; use syntax::codemap::Span; -use std::cell::Ref; use std::fmt; use std::rc::Rc; @@ -255,46 +254,13 @@ impl ast_node for ast::Pat { fn span(&self) -> Span { self.span } } -pub struct MemCategorizationContext<'t,TYPER:'t> { - typer: &'t TYPER -} - -impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {} -impl<'t,TYPER:'t> Clone for MemCategorizationContext<'t,TYPER> { - fn clone(&self) -> MemCategorizationContext<'t,TYPER> { *self } +#[derive(Copy, Clone)] +pub struct MemCategorizationContext<'t, 'a: 't, 'tcx : 'a> { + pub typer: &'t infer::InferCtxt<'a, 'tcx>, } 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, -/// and so on. -/// -/// This interface is needed because mem-categorization is used from -/// two places: `regionck` and `borrowck`. `regionck` executes before -/// type inference is complete, and hence derives types and so on from -/// intermediate tables. This also implies that type errors can occur, -/// and hence `node_ty()` and friends return a `Result` type -- any -/// error will propagate back up through the mem-categorization -/// routines. -/// -/// In the borrow checker, in contrast, type checking is complete and we -/// know that no errors have occurred, so we simply consult the tcx and we -/// can be sure that only `Ok` results will occur. -pub trait Typer<'tcx> : ty::ClosureTyper<'tcx> { - fn node_ty(&self, id: ast::NodeId) -> McResult>; - fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult>; - fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool; - fn node_method_ty(&self, method_call: ty::MethodCall) -> Option>; - fn node_method_origin(&self, method_call: ty::MethodCall) - -> Option>; - fn adjustments(&self) -> Ref>>; - fn is_method_call(&self, id: ast::NodeId) -> bool; - fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option; - fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option; -} - impl MutabilityCategory { pub fn from_mutbl(m: ast::Mutability) -> MutabilityCategory { let ret = match m { @@ -391,13 +357,13 @@ impl MutabilityCategory { } } -impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { - pub fn new(typer: &'t TYPER) -> MemCategorizationContext<'t,TYPER> { +impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> { + pub fn new(typer: &'t infer::InferCtxt<'a, 'tcx>) -> MemCategorizationContext<'t, 'a, 'tcx> { MemCategorizationContext { typer: typer } } - fn tcx(&self) -> &'t ty::ctxt<'tcx> { - self.typer.tcx() + fn tcx(&self) -> &'a ty::ctxt<'tcx> { + self.typer.tcx } fn expr_ty(&self, expr: &ast::Expr) -> McResult> { @@ -1175,7 +1141,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } 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), + where F: FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &ast::Pat), { self.cat_pattern_(cmt, pat, &mut op) } @@ -1183,7 +1149,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { // 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) -> McResult<()> - where F : FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat), + where F : FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &ast::Pat), { // Here, `cmt` is the categorization for the value being // matched and pat is the pattern it is being matched against. diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index 371b5c309a8..977d0577e48 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -38,8 +38,7 @@ pub fn overlapping_impls(infcx: &InferCtxt, impl1_def_id, impl2_def_id); - let param_env = &infcx.tcx.empty_parameter_environment(); - let selcx = &mut SelectionContext::intercrate(infcx, param_env); + let selcx = &mut SelectionContext::intercrate(infcx); infcx.probe(|_| { overlap(selcx, impl1_def_id, impl2_def_id) || overlap(selcx, impl2_def_id, impl1_def_id) }) diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index dc3ccd417b8..08cb3e57015 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -85,7 +85,7 @@ pub struct FulfillmentContext<'tcx> { // particular node-id). region_obligations: NodeMap>>, - errors_will_be_reported: bool, + pub errors_will_be_reported: bool, } #[derive(Clone)] @@ -132,7 +132,6 @@ impl<'tcx> FulfillmentContext<'tcx> { /// `projection_ty` again. pub fn normalize_projection_type<'a>(&mut self, infcx: &InferCtxt<'a,'tcx>, - typer: &ty::ClosureTyper<'tcx>, projection_ty: ty::ProjectionTy<'tcx>, cause: ObligationCause<'tcx>) -> Ty<'tcx> @@ -144,7 +143,7 @@ impl<'tcx> FulfillmentContext<'tcx> { // FIXME(#20304) -- cache - let mut selcx = SelectionContext::new(infcx, typer); + let mut selcx = SelectionContext::new(infcx); let normalized = project::normalize_projection_type(&mut selcx, projection_ty, cause, 0); for obligation in normalized.obligations { @@ -208,11 +207,10 @@ impl<'tcx> FulfillmentContext<'tcx> { } pub fn select_all_or_error<'a>(&mut self, - infcx: &InferCtxt<'a,'tcx>, - typer: &ty::ClosureTyper<'tcx>) + infcx: &InferCtxt<'a,'tcx>) -> Result<(),Vec>> { - try!(self.select_where_possible(infcx, typer)); + try!(self.select_where_possible(infcx)); // Anything left is ambiguous. let errors: Vec = @@ -233,20 +231,18 @@ impl<'tcx> FulfillmentContext<'tcx> { /// gaining type information. It'd be equally valid to use `select_where_possible` but it /// results in `O(n^2)` performance (#18208). pub fn select_new_obligations<'a>(&mut self, - infcx: &InferCtxt<'a,'tcx>, - typer: &ty::ClosureTyper<'tcx>) + infcx: &InferCtxt<'a,'tcx>) -> Result<(),Vec>> { - let mut selcx = SelectionContext::new(infcx, typer); + let mut selcx = SelectionContext::new(infcx); self.select(&mut selcx, true) } pub fn select_where_possible<'a>(&mut self, - infcx: &InferCtxt<'a,'tcx>, - typer: &ty::ClosureTyper<'tcx>) + infcx: &InferCtxt<'a,'tcx>) -> Result<(),Vec>> { - let mut selcx = SelectionContext::new(infcx, typer); + let mut selcx = SelectionContext::new(infcx); self.select(&mut selcx, false) } diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 9df6ed5d681..5126a549887 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -312,7 +312,6 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, /// conservative towards *no impl*, which is the opposite of the /// `evaluate` methods). pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, - typer: &ty::ClosureTyper<'tcx>, ty: Ty<'tcx>, bound: ty::BuiltinBound, span: Span) @@ -334,7 +333,7 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, // Note: we only assume something is `Copy` if we can // *definitively* show that it implements `Copy`. Otherwise, // assume it is move; linear is always ok. - match fulfill_cx.select_all_or_error(infcx, typer) { + match fulfill_cx.select_all_or_error(infcx) { Ok(()) => { debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} success", ty, @@ -397,8 +396,8 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi let elaborated_env = unnormalized_env.with_caller_bounds(predicates); - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env)); - let predicates = match fully_normalize(&infcx, &infcx.parameter_environment, cause, + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env), false); + let predicates = match fully_normalize(&infcx, cause, &infcx.parameter_environment.caller_bounds) { Ok(predicates) => predicates, Err(errors) => { @@ -429,7 +428,6 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi } pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, - closure_typer: &ty::ClosureTyper<'tcx>, cause: ObligationCause<'tcx>, value: &T) -> Result>> @@ -437,8 +435,22 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, { debug!("normalize_param_env(value={:?})", value); - let mut selcx = &mut SelectionContext::new(infcx, closure_typer); + let mut selcx = &mut SelectionContext::new(infcx); + // FIXME (@jroesch) ISSUE 26721 + // I'm not sure if this is a bug or not, needs further investigation. + // It appears that by reusing the fulfillment_cx here we incur more + // obligations and later trip an asssertion on regionck.rs line 337. + // + // The two possibilities I see is: + // - normalization is not actually fully happening and we + // have a bug else where + // - we are adding a duplicate bound into the list causing + // its size to change. + // + // I think we should probably land this refactor and then come + // back to this is a follow-up patch. let mut fulfill_cx = FulfillmentContext::new(false); + let Normalized { value: normalized_value, obligations } = project::normalize(selcx, cause, value); debug!("normalize_param_env: normalized_value={:?} obligations={:?}", @@ -447,7 +459,8 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, for obligation in obligations { fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation); } - try!(fulfill_cx.select_all_or_error(infcx, closure_typer)); + + try!(fulfill_cx.select_all_or_error(infcx)); let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value); debug!("normalize_param_env: resolved_value={:?}", resolved_value); Ok(resolved_value) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index ae15c8aa8e0..3bc4fd0c0a1 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -55,8 +55,6 @@ use util::nodemap::FnvHashMap; pub struct SelectionContext<'cx, 'tcx:'cx> { infcx: &'cx InferCtxt<'cx, 'tcx>, - closure_typer: &'cx (ty::ClosureTyper<'tcx>+'cx), - /// Freshener used specifically for skolemizing entries on the /// obligation stack. This ensures that all entries on the stack /// at one time will have the same set of skolemized entries, @@ -244,23 +242,19 @@ enum EvaluationResult<'tcx> { } impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { - pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>, - closure_typer: &'cx ty::ClosureTyper<'tcx>) + pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> { SelectionContext { infcx: infcx, - closure_typer: closure_typer, freshener: infcx.freshener(), intercrate: false, } } - pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>, - closure_typer: &'cx ty::ClosureTyper<'tcx>) + pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> { SelectionContext { infcx: infcx, - closure_typer: closure_typer, freshener: infcx.freshener(), intercrate: true, } @@ -275,11 +269,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'cx, 'tcx> { - self.closure_typer.param_env() + self.infcx.param_env() } - pub fn closure_typer(&self) -> &'cx (ty::ClosureTyper<'tcx>+'cx) { - self.closure_typer + pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'tcx> { + self.infcx } /////////////////////////////////////////////////////////////////////////// @@ -1163,7 +1157,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { kind, obligation); - match self.closure_typer.closure_kind(closure_def_id) { + match self.infcx.closure_kind(closure_def_id) { Some(closure_kind) => { debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind); if closure_kind.extends(kind) { @@ -1727,7 +1721,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return ok_if(Vec::new()); } - match self.closure_typer.closure_upvars(def_id, substs) { + match self.infcx.closure_upvars(def_id, substs) { Some(upvars) => ok_if(upvars.iter().map(|c| c.ty).collect()), None => { debug!("assemble_builtin_bound_candidates: no upvar types available yet"); @@ -1865,7 +1859,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::TyClosure(def_id, substs) => { assert_eq!(def_id.krate, ast::LOCAL_CRATE); - match self.closure_typer.closure_upvars(def_id, substs) { + match self.infcx.closure_upvars(def_id, substs) { Some(upvars) => { Some(upvars.iter().map(|c| c.ty).collect()) } @@ -2844,7 +2838,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { substs: &Substs<'tcx>) -> ty::PolyTraitRef<'tcx> { - let closure_type = self.closure_typer.closure_type(closure_def_id, substs); + let closure_type = self.infcx.closure_type(closure_def_id, substs); let ty::Binder((trait_ref, _)) = util::closure_trait_ref_and_return_type(self.tcx(), obligation.predicate.def_id(), diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index fe52fba49c6..b1b0097cbf6 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -52,8 +52,6 @@ use middle::dependency_format; use middle::fast_reject; use middle::free_region::FreeRegionMap; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; -use middle::mem_categorization as mc; -use middle::mem_categorization::Typer; use middle::region; use middle::resolve_lifetime; use middle::infer; @@ -2919,11 +2917,14 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { -> Result<(),CopyImplementationError> { let tcx = self.tcx; + // FIXME: (@jroesch) float this code up + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(self.clone()), false); + let did = match self_type.sty { ty::TyStruct(struct_did, substs) => { let fields = tcx.struct_fields(struct_did, substs); for field in &fields { - if self.type_moves_by_default(field.mt.ty, span) { + if infcx.type_moves_by_default(field.mt.ty, span) { return Err(FieldDoesNotImplementCopy(field.name)) } } @@ -2935,7 +2936,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { for variant_arg_type in &variant.args { let substd_arg_type = variant_arg_type.subst(tcx, substs); - if self.type_moves_by_default(substd_arg_type, span) { + if infcx.type_moves_by_default(substd_arg_type, span) { return Err(VariantDoesNotImplementCopy(variant.name)) } } @@ -3177,35 +3178,6 @@ impl ClosureKind { } } -pub trait ClosureTyper<'tcx> { - fn tcx(&self) -> &ctxt<'tcx> { - self.param_env().tcx - } - - fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx>; - - /// Is this a `Fn`, `FnMut` or `FnOnce` closure? During typeck, - /// returns `None` if the kind of this closure has not yet been - /// inferred. - fn closure_kind(&self, - def_id: ast::DefId) - -> Option; - - /// Returns the argument/return types of this closure. - fn closure_type(&self, - def_id: ast::DefId, - substs: &subst::Substs<'tcx>) - -> ty::ClosureTy<'tcx>; - - /// Returns the set of all upvars and their transformed - /// types. During typeck, maybe return `None` if the upvar types - /// have not yet been inferred. - fn closure_upvars(&self, - def_id: ast::DefId, - substs: &Substs<'tcx>) - -> Option>>; -} - impl<'tcx> CommonTypes<'tcx> { fn new(arena: &'tcx TypedArena>, interner: &mut FnvHashMap, Ty<'tcx>>) @@ -4272,7 +4244,8 @@ impl<'tcx> TyS<'tcx> { TyClosure(did, substs) => { // FIXME(#14449): `borrowed_contents` below assumes `&mut` closure. let param_env = cx.empty_parameter_environment(); - let upvars = param_env.closure_upvars(did, substs).unwrap(); + let infcx = infer::new_infer_ctxt(cx, &cx.tables, Some(param_env), false); + let upvars = infcx.closure_upvars(did, substs).unwrap(); TypeContents::union(&upvars, |f| tc_ty(cx, &f.ty, cache)) } @@ -4400,10 +4373,10 @@ impl<'tcx> TyS<'tcx> { span: Span) -> bool { - let tcx = param_env.tcx(); - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone())); + let tcx = param_env.tcx; + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone()), false); - let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, + let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, self, bound, span); debug!("Ty::impls_bound({:?}, {:?}) = {:?}", @@ -4412,7 +4385,8 @@ impl<'tcx> TyS<'tcx> { is_impld } - fn moves_by_default<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>, + // FIXME (@jroesch): I made this public to use it, not sure if should be private + pub fn moves_by_default<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>, span: Span) -> bool { if self.flags.get().intersects(TypeFlags::MOVENESS_CACHED) { return self.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT); @@ -6112,7 +6086,7 @@ impl<'tcx> ctxt<'tcx> { } // Returns a list of `ClosureUpvar`s for each upvar. - pub fn closure_upvars(typer: &Typer<'tcx>, + pub fn closure_upvars<'a>(typer: &infer::InferCtxt<'a, 'tcx>, closure_id: ast::DefId, substs: &Substs<'tcx>) -> Option>> @@ -6123,7 +6097,7 @@ impl<'tcx> ctxt<'tcx> { // This may change if abstract return types of some sort are // implemented. assert!(closure_id.krate == ast::LOCAL_CRATE); - let tcx = typer.tcx(); + let tcx = typer.tcx; match tcx.freevars.borrow().get(&closure_id.node) { None => Some(vec![]), Some(ref freevars) => { @@ -6711,79 +6685,6 @@ impl<'tcx> ctxt<'tcx> { } } -impl<'a,'tcx> Typer<'tcx> for ParameterEnvironment<'a,'tcx> { - fn node_ty(&self, id: ast::NodeId) -> mc::McResult> { - Ok(self.tcx.node_id_to_type(id)) - } - - fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult> { - Ok(self.tcx.expr_ty_adjusted(expr)) - } - - fn node_method_ty(&self, method_call: ty::MethodCall) -> Option> { - self.tcx.tables.borrow().method_map.get(&method_call).map(|method| method.ty) - } - - fn node_method_origin(&self, method_call: ty::MethodCall) - -> Option> - { - self.tcx.tables.borrow().method_map.get(&method_call).map(|method| method.origin.clone()) - } - - fn adjustments(&self) -> Ref>> { - fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap> { - &tables.adjustments - } - - Ref::map(self.tcx.tables.borrow(), projection) - } - - fn is_method_call(&self, id: ast::NodeId) -> bool { - self.tcx.is_method_call(id) - } - - fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option { - self.tcx.region_maps.temporary_scope(rvalue_id) - } - - fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option { - self.tcx.upvar_capture(upvar_id) - } - - fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool { - ty.moves_by_default(self, span) - } -} - -impl<'a,'tcx> ClosureTyper<'tcx> for ty::ParameterEnvironment<'a,'tcx> { - fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> { - self - } - - fn closure_kind(&self, - def_id: ast::DefId) - -> Option - { - Some(self.tcx.closure_kind(def_id)) - } - - fn closure_type(&self, - def_id: ast::DefId, - substs: &subst::Substs<'tcx>) - -> ty::ClosureTy<'tcx> - { - self.tcx.closure_type(def_id, substs) - } - - fn closure_upvars(&self, - def_id: ast::DefId, - substs: &Substs<'tcx>) - -> Option>> { - ctxt::closure_upvars(self, def_id, substs) - } -} - - /// The category of explicit self. #[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum ExplicitSelfCategory { diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 9d4fb4c994d..7c2318eef9c 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -21,6 +21,7 @@ use self::UseError::*; use borrowck::*; use borrowck::InteriorKind::{InteriorElement, InteriorField}; use rustc::middle::expr_use_visitor as euv; +use rustc::middle::infer; use rustc::middle::mem_categorization as mc; use rustc::middle::region; use rustc::middle::ty; @@ -198,17 +199,18 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, debug!("check_loans(body id={})", body.id); let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); + let infcx = infer::new_infer_ctxt(bccx.tcx, &bccx.tcx.tables, Some(param_env), false); let mut clcx = CheckLoanCtxt { bccx: bccx, dfcx_loans: dfcx_loans, move_data: move_data, all_loans: all_loans, - param_env: ¶m_env, + param_env: &infcx.parameter_environment }; { - let mut euv = euv::ExprUseVisitor::new(&mut clcx, ¶m_env); + let mut euv = euv::ExprUseVisitor::new(&mut clcx, &infcx); euv.walk_fn(decl, body); } } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 44a4a0d2504..432d6289efe 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -19,6 +19,7 @@ use borrowck::*; use borrowck::move_data::MoveData; use rustc::middle::expr_use_visitor as euv; +use rustc::middle::infer; use rustc::middle::mem_categorization as mc; use rustc::middle::region; use rustc::middle::ty; @@ -49,9 +50,9 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, }; let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); - + let infcx = infer::new_infer_ctxt(bccx.tcx, &bccx.tcx.tables, Some(param_env), false); { - let mut euv = euv::ExprUseVisitor::new(&mut glcx, ¶m_env); + let mut euv = euv::ExprUseVisitor::new(&mut glcx, &infcx); euv.walk_fn(decl, body); } @@ -490,8 +491,8 @@ struct StaticInitializerCtxt<'a, 'tcx: 'a> { impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> { fn visit_expr(&mut self, ex: &Expr) { if let ast::ExprAddrOf(mutbl, ref base) = ex.node { - let param_env = self.bccx.tcx.empty_parameter_environment(); - let mc = mc::MemCategorizationContext::new(¶m_env); + let infcx = infer::new_infer_ctxt(self.bccx.tcx, &self.bccx.tcx.tables, None, false); + let mc = mc::MemCategorizationContext::new(&infcx); let base_cmt = mc.cat_expr(&**base).unwrap(); let borrow_kind = ty::BorrowKind::from_mutbl(mutbl); // Check that we don't allow borrows of unsafe static items. diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 4f726044a1b..3a4318527fb 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -30,7 +30,6 @@ use rustc::middle::dataflow::KillFrom; use rustc::middle::expr_use_visitor as euv; use rustc::middle::free_region::FreeRegionMap; use rustc::middle::mem_categorization as mc; -use rustc::middle::mem_categorization::Typer; use rustc::middle::region; use rustc::middle::ty::{self, Ty}; @@ -747,7 +746,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { -> (&'static str, &'static str) { match ty.sty { _ => { - if param_env.type_moves_by_default(ty, span) { + if ty.moves_by_default(param_env, span) { ("non-copyable", "perhaps you meant to use `clone()`?") } else { diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index fb2f6b2b08d..128b0b7baab 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -140,7 +140,7 @@ fn test_env(source_string: &str, lang_items, stability::Index::new(krate), |tcx| { - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None); + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false); body(Env { infcx: &infcx }); let free_regions = FreeRegionMap::new(); infcx.resolve_regions_and_report_errors(&free_regions, ast::CRATE_NODE_ID); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 903ade7cc84..8845bd06a06 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -33,7 +33,6 @@ use metadata::{csearch, decoder}; use middle::def::*; -use middle::mem_categorization::Typer; use middle::subst::Substs; use middle::ty::{self, Ty}; use middle::{def, pat_util, stability}; @@ -1709,7 +1708,9 @@ impl LintPass for MissingCopyImplementations { _ => return, }; let parameter_environment = cx.tcx.empty_parameter_environment(); - if !parameter_environment.type_moves_by_default(ty, item.span) { + // FIXME (@jroesch) should probably inver this so that the parameter env still impls this + // method + if !ty.moves_by_default(¶meter_environment, item.span) { return; } if parameter_environment.can_type_implement_copy(ty, item.span).is_ok() { diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index dc692b0e765..bb7e95cd4ae 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -43,7 +43,6 @@ #![feature(unicode)] #![feature(unicode)] #![feature(vec_push_all)] -#![feature(cell_extras)] #![allow(trivial_casts)] diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 47c2a5e579d..a9617bd17c0 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -195,9 +195,9 @@ use middle::check_match; use middle::const_eval; use middle::def::{self, DefMap}; use middle::expr_use_visitor as euv; +use middle::infer; use middle::lang_items::StrEqFnLangItem; use middle::mem_categorization as mc; -use middle::mem_categorization::Typer; use middle::pat_util::*; use trans::adt; use trans::base::*; @@ -1351,7 +1351,8 @@ fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool reassigned: false }; { - let mut visitor = euv::ExprUseVisitor::new(&mut rc, bcx); + let infcx = infer::new_infer_ctxt(bcx.tcx(), &bcx.tcx().tables, None, false); + let mut visitor = euv::ExprUseVisitor::new(&mut rc, &infcx); visitor.walk_expr(body); } rc.reassigned @@ -1416,7 +1417,7 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat, let trmode; match bm { ast::BindByValue(_) - if !param_env.type_moves_by_default(variable_ty, span) || reassigned => + if !variable_ty.moves_by_default(¶m_env, span) || reassigned => { llmatch = alloca_no_lifetime(bcx, llvariable_ty.ptr_to(), diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 3ce76167e85..eca9891c57c 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -50,7 +50,8 @@ use std::rc::Rc; use llvm::{ValueRef, True, IntEQ, IntNE}; use back::abi::FAT_PTR_ADDR; use middle::subst; -use middle::ty::{self, Ty, ClosureTyper}; +use middle::infer; +use middle::ty::{self, Ty}; use middle::ty::Disr; use syntax::ast; use syntax::attr; @@ -223,8 +224,8 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Univariant(mk_struct(cx, &ftys[..], packed, t), dtor_to_init_u8(dtor)) } ty::TyClosure(def_id, substs) => { - let typer = NormalizingClosureTyper::new(cx.tcx()); - let upvars = typer.closure_upvars(def_id, substs).unwrap(); + let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables); + let upvars = infcx.closure_upvars(def_id, substs).unwrap(); let upvar_types = upvars.iter().map(|u| u.ty).collect::>(); Univariant(mk_struct(cx, &upvar_types[..], false, t), 0) } @@ -443,8 +444,8 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>, // Perhaps one of the upvars of this struct is non-zero // Let's recurse and find out! ty::TyClosure(def_id, substs) => { - let typer = NormalizingClosureTyper::new(tcx); - let upvars = typer.closure_upvars(def_id, substs).unwrap(); + let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables); + let upvars = infcx.closure_upvars(def_id, substs).unwrap(); let upvar_types = upvars.iter().map(|u| u.ty).collect::>(); for (j, &ty) in upvar_types.iter().enumerate() { diff --git a/src/librustc_trans/trans/attributes.rs b/src/librustc_trans/trans/attributes.rs index b432560bc4b..25cde149df1 100644 --- a/src/librustc_trans/trans/attributes.rs +++ b/src/librustc_trans/trans/attributes.rs @@ -11,7 +11,8 @@ use libc::{c_uint, c_ulonglong}; use llvm::{self, ValueRef, AttrHelper}; -use middle::ty::{self, ClosureTyper}; +use middle::ty; +use middle::infer; use session::config::NoDebugInfo; use syntax::abi; use syntax::ast; @@ -145,8 +146,8 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx let (fn_sig, abi, env_ty) = match fn_type.sty { ty::TyBareFn(_, ref f) => (&f.sig, f.abi, None), ty::TyClosure(closure_did, substs) => { - let typer = common::NormalizingClosureTyper::new(ccx.tcx()); - function_type = typer.closure_type(closure_did, substs); + let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables); + function_type = infcx.closure_type(closure_did, substs); let self_type = base::self_type_for_closure(ccx, closure_did, fn_type); (&function_type.sig, abi::RustCall, Some(self_type)) } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 0cd6bbad03a..156d591b909 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -37,10 +37,11 @@ use llvm; use metadata::{csearch, encoder, loader}; use middle::astencode; use middle::cfg; +use middle::infer; use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; use middle::weak_lang_items; use middle::subst::Substs; -use middle::ty::{self, Ty, ClosureTyper, HasTypeFlags}; +use middle::ty::{self, Ty, HasTypeFlags}; use rustc::ast_map; use session::config::{self, NoDebugInfo}; use session::Session; @@ -434,8 +435,8 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, } ty::TyClosure(def_id, substs) => { let repr = adt::represent_type(cx.ccx(), t); - let typer = common::NormalizingClosureTyper::new(cx.tcx()); - let upvars = typer.closure_upvars(def_id, substs).unwrap(); + let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables); + let upvars = infcx.closure_upvars(def_id, substs).unwrap(); for (i, upvar) in upvars.iter().enumerate() { let llupvar = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i); cx = f(cx, llupvar, upvar.ty); diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index b6378062855..5fd0f92400f 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -11,7 +11,7 @@ use arena::TypedArena; use back::link::{self, mangle_internal_name_by_path_and_seq}; use llvm::{ValueRef, get_params}; -use middle::mem_categorization::Typer; +use middle::infer; use trans::adt; use trans::attributes; use trans::base::*; @@ -25,7 +25,7 @@ use trans::declare; use trans::expr; use trans::monomorphize::{self, MonoId}; use trans::type_of::*; -use middle::ty::{self, ClosureTyper}; +use middle::ty; use middle::subst::Substs; use session::config::FullDebugInfo; @@ -214,8 +214,9 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, // takes the same set of type arguments as the enclosing fn, and // this function (`trans_closure`) is invoked at the point // of the closure expression. - let typer = NormalizingClosureTyper::new(tcx); - let function_type = typer.closure_type(closure_id, param_substs); + + let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables); + let function_type = infcx.closure_type(closure_id, param_substs); let freevars: Vec = tcx.with_freevars(id, |fv| fv.iter().cloned().collect()); @@ -358,7 +359,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( ccx.tn().val_to_string(llreffn)); let tcx = ccx.tcx(); - let typer = NormalizingClosureTyper::new(tcx); + let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables); // Find a version of the closure type. Substitute static for the // region since it doesn't really matter. @@ -367,7 +368,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic), closure_ty); // Make a version with the type of by-ref closure. - let ty::ClosureTy { unsafety, abi, mut sig } = typer.closure_type(closure_def_id, substs); + let ty::ClosureTy { unsafety, abi, mut sig } = infcx.closure_type(closure_def_id, substs); sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet let llref_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety, abi: abi, diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 9c2aea1e67a..96564277cdc 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -22,9 +22,6 @@ use middle::cfg; use middle::def; use middle::infer; use middle::lang_items::LangItem; -use middle::mem_categorization as mc; -use middle::mem_categorization::Typer; -use middle::region; use middle::subst::{self, Substs}; use trans::base; use trans::build; @@ -47,7 +44,7 @@ use util::nodemap::{FnvHashMap, NodeMap}; use arena::TypedArena; use libc::{c_uint, c_char}; use std::ffi::CString; -use std::cell::{Cell, RefCell, Ref}; +use std::cell::{Cell, RefCell}; use std::result::Result as StdResult; use std::vec::Vec; use syntax::ast; @@ -153,7 +150,7 @@ fn type_needs_drop_given_env<'a,'tcx>(cx: &ty::ctxt<'tcx>, // normalized version of the type, and therefore will definitely // know whether the type implements Copy (and thus needs no // cleanup/drop/zeroing) ... - let implements_copy = !param_env.type_moves_by_default(ty, DUMMY_SP); + let implements_copy = !ty.moves_by_default(param_env, DUMMY_SP); if implements_copy { return false; } @@ -576,95 +573,6 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { } } -impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { - fn node_ty(&self, id: ast::NodeId) -> mc::McResult> { - Ok(node_id_type(self, id)) - } - - fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult> { - Ok(expr_ty_adjusted(self, expr)) - } - - fn node_method_ty(&self, method_call: ty::MethodCall) -> Option> { - self.tcx() - .tables - .borrow() - .method_map - .get(&method_call) - .map(|method| monomorphize_type(self, method.ty)) - } - - fn node_method_origin(&self, method_call: ty::MethodCall) - -> Option> - { - self.tcx() - .tables - .borrow() - .method_map - .get(&method_call) - .map(|method| method.origin.clone()) - } - - fn adjustments<'a>(&'a self) -> Ref>> { - // FIXME (@jroesch): this is becuase we currently have a HR inference problem - // in the snapshot that causes this code not to work. - fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) -> - &'a NodeMap> { - &tables.adjustments - } - - Ref::map(self.tcx().tables.borrow(), project_adjustments) - } - - fn is_method_call(&self, id: ast::NodeId) -> bool { - self.tcx().tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id)) - } - - fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option { - self.tcx().region_maps.temporary_scope(rvalue_id) - } - - fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option { - Some(self.tcx().tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone()) - } - - fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool { - self.fcx.param_env.type_moves_by_default(ty, span) - } -} - -impl<'blk, 'tcx> ty::ClosureTyper<'tcx> for BlockS<'blk, 'tcx> { - fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx> { - &self.fcx.param_env - } - - fn closure_kind(&self, - def_id: ast::DefId) - -> Option - { - let typer = NormalizingClosureTyper::new(self.tcx()); - typer.closure_kind(def_id) - } - - fn closure_type(&self, - def_id: ast::DefId, - substs: &subst::Substs<'tcx>) - -> ty::ClosureTy<'tcx> - { - let typer = NormalizingClosureTyper::new(self.tcx()); - typer.closure_type(def_id, substs) - } - - fn closure_upvars(&self, - def_id: ast::DefId, - substs: &Substs<'tcx>) - -> Option>> - { - let typer = NormalizingClosureTyper::new(self.tcx()); - typer.closure_upvars(def_id, substs) - } -} - pub struct Result<'blk, 'tcx: 'blk> { pub bcx: Block<'blk, 'tcx>, pub val: ValueRef @@ -957,12 +865,12 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, trait_ref, trait_ref.def_id()); tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id()); - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None); // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - let typer = NormalizingClosureTyper::new(tcx); - let mut selcx = traits::SelectionContext::new(&infcx, &typer); + let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables); + let mut selcx = traits::SelectionContext::new(&infcx); + let obligation = traits::Obligation::new(traits::ObligationCause::misc(span, ast::DUMMY_NODE_ID), trait_ref.to_poly_trait_predicate()); @@ -994,7 +902,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // Currently, we use a fulfillment context to completely resolve // all nested obligations. This is because they can inform the // inference of the impl's type parameters. - let mut fulfill_cx = traits::FulfillmentContext::new(true); + let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut(); let vtable = selection.map(|predicate| { fulfill_cx.register_predicate_obligation(&infcx, predicate); }); @@ -1019,10 +927,9 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, predicates); let tcx = ccx.tcx(); - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None); - let typer = NormalizingClosureTyper::new(tcx); - let mut selcx = traits::SelectionContext::new(&infcx, &typer); - let mut fulfill_cx = traits::FulfillmentContext::new(false); + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true); + let mut selcx = traits::SelectionContext::new(&infcx); + let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut(); let cause = traits::ObligationCause::dummy(); let traits::Normalized { value: predicates, obligations } = traits::normalize(&mut selcx, cause.clone(), &predicates); @@ -1036,57 +943,6 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()).is_ok() } -// NOTE: here is another use of parameter environment without an InferCtxt, -// this is obviously related to the typer interface requiring a parameter env. -// We should pay attention to this when refactoring -// - @jroesch -pub struct NormalizingClosureTyper<'a,'tcx:'a> { - param_env: ty::ParameterEnvironment<'a, 'tcx> -} - -impl<'a,'tcx> NormalizingClosureTyper<'a,'tcx> { - pub fn new(tcx: &'a ty::ctxt<'tcx>) -> NormalizingClosureTyper<'a,'tcx> { - // Parameter environment is used to give details about type parameters, - // but since we are in trans, everything is fully monomorphized. - NormalizingClosureTyper { param_env: tcx.empty_parameter_environment() } - } -} - -impl<'a,'tcx> ty::ClosureTyper<'tcx> for NormalizingClosureTyper<'a,'tcx> { - fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> { - &self.param_env - } - - fn closure_kind(&self, - def_id: ast::DefId) - -> Option - { - self.param_env.closure_kind(def_id) - } - - fn closure_type(&self, - def_id: ast::DefId, - substs: &subst::Substs<'tcx>) - -> ty::ClosureTy<'tcx> - { - // the substitutions in `substs` are already monomorphized, - // but we still must normalize associated types - let closure_ty = self.param_env.tcx.closure_type(def_id, substs); - monomorphize::normalize_associated_type(self.param_env.tcx, &closure_ty) - } - - fn closure_upvars(&self, - def_id: ast::DefId, - substs: &Substs<'tcx>) - -> Option>> - { - // the substitutions in `substs` are already monomorphized, - // but we still must normalize associated types - let result = self.param_env.closure_upvars(def_id, substs); - monomorphize::normalize_associated_type(self.param_env.tcx, &result) - } -} - pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span, infcx: &infer::InferCtxt<'a,'tcx>, fulfill_cx: &mut traits::FulfillmentContext<'tcx>, @@ -1124,8 +980,7 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &infer::InferCtxt<'a,'tcx>, // In principle, we only need to do this so long as `result` // contains unbound type parameters. It could be a slight // optimization to stop iterating early. - let typer = NormalizingClosureTyper::new(infcx.tcx); - match fulfill_cx.select_all_or_error(infcx, &typer) { + match fulfill_cx.select_all_or_error(infcx) { Ok(()) => { } Err(errors) => { return Err(errors); diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index 2c539b67cb6..c0ebffb58af 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -101,7 +101,6 @@ use trans::cleanup::CleanupMethods; use trans::expr; use trans::tvec; use trans::type_of; -use middle::mem_categorization::Typer; use middle::ty::Ty; use std::fmt; @@ -606,8 +605,8 @@ impl<'tcx, K: KindOps + fmt::Debug> Datum<'tcx, K> { * affine values (since they must never be duplicated). */ - assert!(!bcx.tcx().empty_parameter_environment() - .type_moves_by_default(self.ty, DUMMY_SP)); + assert!(!self.ty + .moves_by_default(&bcx.tcx().empty_parameter_environment(), DUMMY_SP)); self.shallow_copy_raw(bcx, dst) } diff --git a/src/librustc_trans/trans/debuginfo/gdb.rs b/src/librustc_trans/trans/debuginfo/gdb.rs index a6f1199d0ff..f7b0f37c9ff 100644 --- a/src/librustc_trans/trans/debuginfo/gdb.rs +++ b/src/librustc_trans/trans/debuginfo/gdb.rs @@ -16,7 +16,6 @@ use llvm::ValueRef; use trans::common::{C_bytes, CrateContext}; use trans::declare; use trans::type_::Type; -use middle::ty::ClosureTyper; use session::config::NoDebugInfo; use std::ffi::CString; diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs index 1fbbf0763aa..45349969a0b 100644 --- a/src/librustc_trans/trans/debuginfo/metadata.rs +++ b/src/librustc_trans/trans/debuginfo/metadata.rs @@ -26,12 +26,13 @@ use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType}; use metadata::csearch; use middle::pat_util; use middle::subst::{self, Substs}; +use middle::infer; use rustc::ast_map; use trans::{type_of, adt, machine, monomorphize}; -use trans::common::{self, CrateContext, FunctionContext, NormalizingClosureTyper, Block}; +use trans::common::{self, CrateContext, FunctionContext, Block}; use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef}; use trans::type_::Type; -use middle::ty::{self, Ty, ClosureTyper}; +use middle::ty::{self, Ty}; use session::config::{self, FullDebugInfo}; use util::nodemap::FnvHashMap; use util::common::path2cstr; @@ -287,8 +288,8 @@ impl<'tcx> TypeMap<'tcx> { } }, ty::TyClosure(def_id, substs) => { - let typer = NormalizingClosureTyper::new(cx.tcx()); - let closure_ty = typer.closure_type(def_id, substs); + let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables); + let closure_ty = infcx.closure_type(def_id, substs); self.get_unique_type_id_of_closure_type(cx, closure_ty, &mut unique_type_id); @@ -796,8 +797,8 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span) } ty::TyClosure(def_id, substs) => { - let typer = NormalizingClosureTyper::new(cx.tcx()); - let sig = typer.closure_type(def_id, substs).sig; + let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables); + let sig = infcx.closure_type(def_id, substs).sig; subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span) } ty::TyStruct(def_id, substs) => { diff --git a/src/librustc_trans/trans/debuginfo/mod.rs b/src/librustc_trans/trans/debuginfo/mod.rs index 7487e8d331b..3d1b384c2d9 100644 --- a/src/librustc_trans/trans/debuginfo/mod.rs +++ b/src/librustc_trans/trans/debuginfo/mod.rs @@ -30,7 +30,7 @@ use rustc::ast_map; use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block}; use trans; use trans::monomorphize; -use middle::ty::{Ty, ClosureTyper}; +use middle::ty::Ty; use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet}; diff --git a/src/librustc_trans/trans/debuginfo/namespace.rs b/src/librustc_trans/trans/debuginfo/namespace.rs index 2e5943a248a..8b33acdee8e 100644 --- a/src/librustc_trans/trans/debuginfo/namespace.rs +++ b/src/librustc_trans/trans/debuginfo/namespace.rs @@ -16,7 +16,6 @@ use llvm; use llvm::debuginfo::DIScope; use rustc::ast_map; use trans::common::CrateContext; -use middle::ty::ClosureTyper; use std::ffi::CString; use std::ptr; diff --git a/src/librustc_trans/trans/debuginfo/type_names.rs b/src/librustc_trans/trans/debuginfo/type_names.rs index 6ea43d7392c..f4116883199 100644 --- a/src/librustc_trans/trans/debuginfo/type_names.rs +++ b/src/librustc_trans/trans/debuginfo/type_names.rs @@ -14,7 +14,7 @@ use super::namespace::crate_root_namespace; use trans::common::CrateContext; use middle::subst::{self, Substs}; -use middle::ty::{self, Ty, ClosureTyper}; +use middle::ty::{self, Ty}; use syntax::ast; use syntax::parse::token; @@ -225,4 +225,3 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, output.push('>'); } } - diff --git a/src/librustc_trans/trans/declare.rs b/src/librustc_trans/trans/declare.rs index 646ca6733c3..b29da9d560f 100644 --- a/src/librustc_trans/trans/declare.rs +++ b/src/librustc_trans/trans/declare.rs @@ -20,11 +20,11 @@ //! * Use define_* family of methods when you might be defining the ValueRef. //! * When in doubt, define. use llvm::{self, ValueRef}; -use middle::ty::{self, ClosureTyper}; +use middle::ty; +use middle::infer; use syntax::abi; use trans::attributes; use trans::base; -use trans::common; use trans::context::CrateContext; use trans::monomorphize; use trans::type_::Type; @@ -117,8 +117,8 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, (&f.sig, f.abi, None) } ty::TyClosure(closure_did, substs) => { - let typer = common::NormalizingClosureTyper::new(ccx.tcx()); - function_type = typer.closure_type(closure_did, substs); + let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables); + function_type = infcx.closure_type(closure_did, substs); let self_type = base::self_type_for_closure(ccx, closure_did, fn_type); let llenvironment_type = type_of::type_of_explicit_arg(ccx, self_type); debug!("declare_rust_fn function_type={:?} self_type={:?}", diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 045cc69bf95..39bb9b25be7 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -56,7 +56,6 @@ use llvm::{self, ValueRef, TypeKind}; use middle::check_const; use middle::def; use middle::lang_items::CoerceUnsizedTraitLangItem; -use middle::mem_categorization::Typer; use middle::subst::{Substs, VecPerParamSpace}; use middle::traits; use trans::{_match, adt, asm, base, callee, closure, consts, controlflow}; diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index e46c3b5fab1..1b01fb6c7f8 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -17,7 +17,6 @@ use middle::subst::{Subst, Substs}; use middle::subst::VecPerParamSpace; use middle::subst; use middle::traits; -use middle::ty::ClosureTyper; use rustc::ast_map; use trans::base::*; use trans::build::*; diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index 67ccf64621a..3ef72e2c4af 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -322,11 +322,8 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T } // FIXME(#20304) -- cache - // NOTE: @jroesch - // Here is of an example where we do not use a param_env but use a typer instead. - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None); - let typer = NormalizingClosureTyper::new(tcx); - let mut selcx = traits::SelectionContext::new(&infcx, &typer); + let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables); + let mut selcx = traits::SelectionContext::new(&infcx); let cause = traits::ObligationCause::dummy(); let traits::Normalized { value: result, obligations } = traits::normalize(&mut selcx, cause, &value); @@ -335,7 +332,8 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T result, obligations); - let mut fulfill_cx = traits::FulfillmentContext::new(true); + let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut(); + for obligation in obligations { fulfill_cx.register_predicate_obligation(&infcx, obligation); } diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs index 4eafbaaf794..c80c48a9692 100644 --- a/src/librustc_typeck/check/assoc.rs +++ b/src/librustc_typeck/check/assoc.rs @@ -11,13 +11,13 @@ use middle::infer::InferCtxt; use middle::traits::{self, FulfillmentContext, Normalized, MiscObligation, SelectionContext, ObligationCause}; -use middle::ty::{self, HasTypeFlags}; +use middle::ty::HasTypeFlags; use middle::ty_fold::TypeFoldable; use syntax::ast; use syntax::codemap::Span; +//FIXME(@jroesch): Ideally we should be able to drop the fulfillment_cx argument. pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, - typer: &(ty::ClosureTyper<'tcx>+'a), fulfillment_cx: &mut FulfillmentContext<'tcx>, span: Span, body_id: ast::NodeId, @@ -26,7 +26,7 @@ pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, where T : TypeFoldable<'tcx> + HasTypeFlags { debug!("normalize_associated_types_in(value={:?})", value); - let mut selcx = SelectionContext::new(infcx, typer); + let mut selcx = SelectionContext::new(infcx); let cause = ObligationCause::new(span, body_id, MiscObligation); let Normalized { value: result, obligations } = traits::normalize(&mut selcx, cause, value); debug!("normalize_associated_types_in: result={:?} predicates={:?}", diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index d29c0494572..f32a4fe43d6 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -27,7 +27,7 @@ use super::write_call; use CrateCtxt; use middle::infer; -use middle::ty::{self, Ty, ClosureTyper}; +use middle::ty::{self, Ty}; use syntax::ast; use syntax::codemap::Span; use syntax::parse::token; diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index b5ee46ece94..6d1e9dfacf2 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -125,7 +125,7 @@ fn deduce_expectations_from_obligations<'a,'tcx>( expected_vid: ty::TyVid) -> (Option>, Option) { - let fulfillment_cx = fcx.inh.fulfillment_cx.borrow(); + let fulfillment_cx = fcx.inh.infcx.fulfillment_cx.borrow(); // Here `expected_ty` is known to be a type inference variable. let expected_sig = diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index b38b6884a98..a0abef74907 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -273,7 +273,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { }; let source = source.adjust_for_autoref(self.tcx(), reborrow); - let mut selcx = traits::SelectionContext::new(self.fcx.infcx(), self.fcx.infcx()); + let mut selcx = traits::SelectionContext::new(self.fcx.infcx()); // Use a FIFO queue for this custom fulfillment procedure. let mut queue = VecDeque::new(); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index f62411e8582..7926394ebb5 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -43,8 +43,8 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, debug!("compare_impl_method: impl_trait_ref (liberated) = {:?}", impl_trait_ref); - let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None); - let mut fulfillment_cx = traits::FulfillmentContext::new(true); + let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true); + let mut fulfillment_cx = infcx.fulfillment_cx.borrow_mut(); let trait_to_impl_substs = &impl_trait_ref.substs; @@ -246,7 +246,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, debug!("compare_impl_method: trait_bounds={:?}", infcx.parameter_environment.caller_bounds); - let mut selcx = traits::SelectionContext::new(&infcx, &infcx.parameter_environment); + let mut selcx = traits::SelectionContext::new(&infcx); for predicate in impl_pred.fns { let traits::Normalized { value: predicate, .. } = @@ -293,7 +293,6 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, impl_sig.subst(tcx, impl_to_skol_substs); let impl_sig = assoc::normalize_associated_types_in(&infcx, - &impl_param_env, &mut fulfillment_cx, impl_m_span, impl_m_body_id, @@ -312,7 +311,6 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, trait_sig.subst(tcx, &trait_to_skol_substs); let trait_sig = assoc::normalize_associated_types_in(&infcx, - &impl_param_env, &mut fulfillment_cx, impl_m_span, impl_m_body_id, @@ -347,7 +345,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, // Check that all obligations are satisfied by the implementation's // version. - match fulfillment_cx.select_all_or_error(&infcx, &infcx.parameter_environment) { + match fulfillment_cx.select_all_or_error(&infcx) { Err(ref errors) => { traits::report_fulfillment_errors(&infcx, errors) } Ok(_) => {} } @@ -419,8 +417,8 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>, debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None); - let mut fulfillment_cx = traits::FulfillmentContext::new(true); + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true); + let mut fulfillment_cx = infcx.fulfillment_cx.borrow_mut(); // The below is for the most part highly similar to the procedure // for methods above. It is simpler in many respects, especially @@ -456,21 +454,21 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>, // There is no "body" here, so just pass dummy id. let impl_ty = assoc::normalize_associated_types_in(&infcx, - &impl_param_env, &mut fulfillment_cx, impl_c_span, 0, &impl_ty); + debug!("compare_const_impl: impl_ty={:?}", impl_ty); let trait_ty = assoc::normalize_associated_types_in(&infcx, - &impl_param_env, &mut fulfillment_cx, impl_c_span, 0, &trait_ty); + debug!("compare_const_impl: trait_ty={:?}", trait_ty); diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 6f0fbfebf46..7d911cf8b03 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -93,7 +93,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( ty: named_type } = tcx.lookup_item_type(self_type_did); - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None); + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false); infcx.commit_if_ok(|snapshot| { let (named_type_to_skolem, skol_map) = diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 9c2d1c4a34d..7a887fac9d4 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -12,7 +12,6 @@ use super::probe; use check::{self, FnCtxt, NoPreference, PreferMutLvalue, callee, demand}; use check::UnresolvedTypeAction; -use middle::mem_categorization::Typer; use middle::subst::{self}; use middle::traits; use middle::ty::{self, Ty}; diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index f312db9c4dc..7ed5c69ad61 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -195,7 +195,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, poly_trait_ref.to_predicate()); // Now we want to know if this can be matched - let mut selcx = traits::SelectionContext::new(fcx.infcx(), fcx.infcx()); + let mut selcx = traits::SelectionContext::new(fcx.infcx()); if !selcx.evaluate_obligation(&obligation) { debug!("--> Cannot match obligation"); return None; // Cannot be matched, no such method resolution is possible. diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 94a2050829d..8eb4716cb2a 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -421,7 +421,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // We can't use normalize_associated_types_in as it will pollute the // fcx's fulfillment context after this probe is over. let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id); - let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx.infcx()); + let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx()); let traits::Normalized { value: xform_self_ty, obligations } = traits::normalize(selcx, cause, &xform_self_ty); debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}", @@ -681,7 +681,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // as it will pollute the fcx's fulfillment context after this probe // is over. let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id); - let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx.infcx()); + let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx()); let traits::Normalized { value: xform_self_ty, obligations } = traits::normalize(selcx, cause, &xform_self_ty); @@ -1076,7 +1076,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { match probe.kind { InherentImplCandidate(impl_def_id, ref substs, ref ref_obligations) | ExtensionImplCandidate(impl_def_id, _, ref substs, _, ref ref_obligations) => { - let selcx = &mut traits::SelectionContext::new(self.infcx(), self.fcx.infcx()); + let selcx = &mut traits::SelectionContext::new(self.infcx()); let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id); // Check whether the impl imposes obligations we have to worry about. diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index b81b672e684..d6a8b3583f8 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -102,7 +102,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let obligation = Obligation::misc(span, fcx.body_id, poly_trait_ref.to_predicate()); - let mut selcx = SelectionContext::new(infcx, fcx.infcx()); + let mut selcx = SelectionContext::new(infcx); if selcx.evaluate_obligation(&obligation) { span_stored_function(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2db1598db4b..b7ebf1abd2d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -158,9 +158,6 @@ pub struct Inherited<'a, 'tcx: 'a> { // one is never copied into the tcx: it is only used by regionck. fn_sig_map: RefCell>>>, - // Tracks trait obligations incurred during this function body. - fulfillment_cx: RefCell>, - // When we process a call like `c()` where `c` is a closure type, // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or // `FnOnce` closure. In that case, we defer full resolution of the @@ -295,28 +292,26 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { -> Inherited<'a, 'tcx> { Inherited { - infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env)), + infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env), true), locals: RefCell::new(NodeMap()), tables: tables, fn_sig_map: RefCell::new(NodeMap()), - fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(true)), deferred_call_resolutions: RefCell::new(DefIdMap()), deferred_cast_checks: RefCell::new(Vec::new()), } } fn normalize_associated_types_in(&self, - typer: &ty::ClosureTyper<'tcx>, span: Span, body_id: ast::NodeId, value: &T) -> T where T : TypeFoldable<'tcx> + HasTypeFlags { - let mut fulfillment_cx = self.fulfillment_cx.borrow_mut(); + let mut fulfillment_cx = self.infcx.fulfillment_cx.borrow_mut(); assoc::normalize_associated_types_in(&self.infcx, - typer, - &mut *fulfillment_cx, span, + &mut fulfillment_cx, + span, body_id, value) } @@ -431,8 +426,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ccx.tcx.liberate_late_bound_regions(region::DestructionScopeData::new(body.id), &fn_sig); let fn_sig = - inh.normalize_associated_types_in(&inh.infcx.parameter_environment, - body.span, + inh.normalize_associated_types_in(body.span, body.id, &fn_sig); @@ -1377,7 +1371,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn normalize_associated_types_in(&self, span: Span, value: &T) -> T where T : TypeFoldable<'tcx> + HasTypeFlags { - self.inh.normalize_associated_types_in(self.infcx(), span, self.body_id, value) + self.inh.normalize_associated_types_in(span, self.body_id, value) } fn normalize_associated_type(&self, @@ -1389,10 +1383,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let cause = traits::ObligationCause::new(span, self.body_id, traits::ObligationCauseCode::MiscObligation); - self.inh.fulfillment_cx + self.inh + .infcx + .fulfillment_cx .borrow_mut() .normalize_projection_type(self.infcx(), - self.infcx(), ty::ProjectionTy { trait_ref: trait_ref, item_name: item_name, @@ -1502,7 +1497,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { -> bool { traits::type_known_to_meet_builtin_bound(self.infcx(), - self.param_env(), ty, ty::BoundSized, span) @@ -1513,7 +1507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { builtin_bound: ty::BuiltinBound, cause: traits::ObligationCause<'tcx>) { - self.inh.fulfillment_cx.borrow_mut() + self.inh.infcx.fulfillment_cx.borrow_mut() .register_builtin_bound(self.infcx(), ty, builtin_bound, cause); } @@ -1522,7 +1516,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { debug!("register_predicate({:?})", obligation); - self.inh.fulfillment_cx + self.inh.infcx.fulfillment_cx .borrow_mut() .register_predicate_obligation(self.infcx(), obligation); } @@ -1648,7 +1642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { region: ty::Region, cause: traits::ObligationCause<'tcx>) { - let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut(); + let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut(); fulfillment_cx.register_region_obligation(ty, region, cause); } @@ -1747,8 +1741,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { assert!(self.inh.deferred_call_resolutions.borrow().is_empty()); self.select_all_obligations_and_apply_defaults(); - let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut(); - match fulfillment_cx.select_all_or_error(self.infcx(), self.infcx()) { + let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut(); + match fulfillment_cx.select_all_or_error(self.infcx()) { Ok(()) => { } Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); } } @@ -1757,9 +1751,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Select as many obligations as we can at present. fn select_obligations_where_possible(&self) { match - self.inh.fulfillment_cx + self.inh.infcx.fulfillment_cx .borrow_mut() - .select_where_possible(self.infcx(), self.infcx()) + .select_where_possible(self.infcx()) { Ok(()) => { } Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); } @@ -1772,9 +1766,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// work. fn select_new_obligations(&self) { match - self.inh.fulfillment_cx + self.inh.infcx.fulfillment_cx .borrow_mut() - .select_new_obligations(self.infcx(), self.infcx()) + .select_new_obligations(self.infcx()) { Ok(()) => { } Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index a8630190738..bb3c9f9fb54 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -86,13 +86,12 @@ use astconv::AstConv; use check::dropck; use check::FnCtxt; use middle::free_region::FreeRegionMap; -use middle::infer::InferCtxt; use middle::implicator; use middle::mem_categorization as mc; use middle::region::CodeExtent; use middle::subst::Substs; use middle::traits; -use middle::ty::{self, ClosureTyper, ReScope, Ty, MethodCall, HasTypeFlags}; +use middle::ty::{self, ReScope, Ty, MethodCall, HasTypeFlags}; use middle::infer::{self, GenericKind}; use middle::pat_util; @@ -318,9 +317,13 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { // Make a copy of the region obligations vec because we'll need // to be able to borrow the fulfillment-cx below when projecting. let region_obligations = - self.fcx.inh.fulfillment_cx.borrow() - .region_obligations(node_id) - .to_vec(); + self.fcx + .inh + .infcx + .fulfillment_cx + .borrow() + .region_obligations(node_id) + .to_vec(); for r_o in ®ion_obligations { debug!("visit_region_obligations: r_o={:?}", @@ -332,7 +335,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { // Processing the region obligations should not cause the list to grow further: assert_eq!(region_obligations.len(), - self.fcx.inh.fulfillment_cx.borrow().region_obligations(node_id).len()); + self.fcx.inh.infcx.fulfillment_cx.borrow().region_obligations(node_id).len()); } /// This method populates the region map's `free_region_map`. It walks over the transformed @@ -356,7 +359,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { debug!("relate_free_regions(t={:?})", ty); let body_scope = CodeExtent::from_node_id(body_id); let body_scope = ty::ReScope(body_scope); - let implications = implicator::implications(self.fcx.infcx(), self.fcx.infcx(), body_id, + let implications = implicator::implications(self.fcx.infcx(), body_id, ty, body_scope, span); // Record any relations between free regions that we observe into the free-region-map. @@ -1097,8 +1100,8 @@ fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[ast::Arg]) { /// Link lifetimes of any ref bindings in `root_pat` to the pointers found in the discriminant, if /// needed. -fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, - mc: mc::MemCategorizationContext>, +fn link_pattern<'t, 'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, + mc: mc::MemCategorizationContext<'t, 'a, 'tcx>, discr_cmt: mc::cmt<'tcx>, root_pat: &ast::Pat) { debug!("link_pattern(discr_cmt={:?}, root_pat={:?})", @@ -1405,7 +1408,7 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, ty, region); - let implications = implicator::implications(rcx.fcx.infcx(), rcx.fcx.infcx(), rcx.body_id, + let implications = implicator::implications(rcx.fcx.infcx(), rcx.body_id, ty, region, origin.span()); for implication in implications { debug!("implication: {:?}", implication); diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index df01b99fd9b..7cf7d73a566 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -268,7 +268,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { let predicates = fcx.tcx().lookup_super_predicates(poly_trait_ref.def_id()); let predicates = predicates.instantiate_supertrait(fcx.tcx(), &poly_trait_ref); let predicates = { - let selcx = &mut traits::SelectionContext::new(fcx.infcx(), fcx.infcx()); + let selcx = &mut traits::SelectionContext::new(fcx.infcx()); traits::normalize(selcx, cause.clone(), &predicates) }; for predicate in predicates.value.predicates { diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index fbabc287342..a1c5ad51dcd 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -448,7 +448,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)", source, target); - let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env)); + let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env), true); let check_mutbl = |mt_a: ty::mt<'tcx>, mt_b: ty::mt<'tcx>, mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| { @@ -531,7 +531,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { } }; - let mut fulfill_cx = traits::FulfillmentContext::new(true); + let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut(); // Register an obligation for `A: Trait`. let cause = traits::ObligationCause::misc(span, impl_did.node); @@ -540,8 +540,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { fulfill_cx.register_predicate_obligation(&infcx, predicate); // Check that all transitive obligations are satisfied. - if let Err(errors) = fulfill_cx.select_all_or_error(&infcx, - &infcx.parameter_environment) { + if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { traits::report_fulfillment_errors(&infcx, &errors); } @@ -632,7 +631,7 @@ fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, pub fn check_coherence(crate_context: &CrateCtxt) { CoherenceChecker { crate_context: crate_context, - inference_context: new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None), + inference_context: new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None, true), inherent_impls: RefCell::new(FnvHashMap()), }.check(crate_context.tcx.map.krate()); unsafety::check(crate_context.tcx); diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 3495714fcc7..42c6bcbfbb9 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -133,7 +133,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { impl1_def_id, impl2_def_id); - let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None); + let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None, false); if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id) { self.report_overlap_error(trait_def_id, impl1_def_id, impl2_def_id); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 7909908079f..c45fbb70002 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2211,7 +2211,7 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>( base_type, base_type_free); - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None); + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false); drop(::require_same_types(tcx, Some(&infcx), false, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 48a64675c70..8c3ef4ae631 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -188,7 +188,7 @@ fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>, { let result = match maybe_infcx { None => { - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None); + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false); infer::mk_eqty(&infcx, t1_is_expected, infer::Misc(span), t1, t2) } Some(infcx) => {