diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 059f38f0930d1..93ff5404fa649 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -1229,7 +1229,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // inferred by regionbk let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.id }; - let upvar_borrow = self.typer.upvar_borrow(upvar_id); + let upvar_borrow = self.typer.upvar_borrow(upvar_id).unwrap(); self.delegate.borrow(closure_expr.id, closure_expr.span, diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 5be8d03e74359..0c3438abb2b47 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -111,7 +111,9 @@ use self::VarKind::*; use middle::def::*; use middle::mem_categorization::Typer; -use middle::{pat_util, ty}; +use middle::pat_util; +use middle::ty; +use middle::ty::UnboxedClosureTyper; use lint; use util::nodemap::NodeMap; @@ -1515,16 +1517,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn fn_ret(&self, id: NodeId) -> ty::FnOutput<'tcx> { let fn_ty = ty::node_id_to_type(self.ir.tcx, id); match fn_ty.sty { - ty::ty_unboxed_closure(closure_def_id, _, _) => - self.ir.tcx.unboxed_closures() - .borrow() - .get(&closure_def_id) - .unwrap() - .closure_type - .sig - .0 - .output, - _ => ty::ty_fn_ret(fn_ty) + ty::ty_unboxed_closure(closure_def_id, _, substs) => + self.ir.tcx.unboxed_closure_type(closure_def_id, substs).sig.0.output, + _ => + ty::ty_fn_ret(fn_ty), } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 580b3a93d7397..70942a950e324 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -74,7 +74,7 @@ pub use self::categorization::*; use middle::def; use middle::region; use middle::ty::{mod, Ty}; -use util::nodemap::{DefIdMap, NodeMap}; +use util::nodemap::{NodeMap}; use util::ppaux::{ty_to_string, Repr}; use syntax::ast::{MutImmutable, MutMutable}; @@ -280,7 +280,7 @@ impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {} /// 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> { +pub trait Typer<'tcx> : ty::UnboxedClosureTyper<'tcx> { fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>; fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx>; fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx>; @@ -290,11 +290,9 @@ pub trait Typer<'tcx> { fn adjustments<'a>(&'a self) -> &'a RefCell>>; fn is_method_call(&self, id: ast::NodeId) -> bool; fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option; - fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow; + fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option; fn capture_mode(&self, closure_expr_id: ast::NodeId) -> ast::CaptureClause; - fn unboxed_closures<'a>(&'a self) - -> &'a RefCell>>; } impl MutabilityCategory { @@ -622,8 +620,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { self.cat_upvar(id, span, var_id, fn_node_id, kind, mode, false) } ty::ty_unboxed_closure(closure_id, _, _) => { - let unboxed_closures = self.typer.unboxed_closures().borrow(); - let kind = (*unboxed_closures)[closure_id].kind; + let kind = self.typer.unboxed_closure_kind(closure_id); let mode = self.typer.capture_mode(fn_node_id); self.cat_upvar(id, span, var_id, fn_node_id, kind, mode, true) } @@ -800,7 +797,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } // Look up upvar borrow so we can get its region - let upvar_borrow = self.typer.upvar_borrow(upvar_id); + let upvar_borrow = self.typer.upvar_borrow(upvar_id).unwrap(); let ptr = BorrowedPtr(upvar_borrow.kind, upvar_borrow.region); Rc::new(cmt_ { diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index c85baccd6336d..2dbb15b215ed0 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -110,7 +110,7 @@ impl<'tcx> FulfillmentContext<'tcx> { pub fn normalize_projection_type<'a>(&mut self, infcx: &InferCtxt<'a,'tcx>, param_env: &ty::ParameterEnvironment<'tcx>, - typer: &Typer<'tcx>, + typer: &ty::UnboxedClosureTyper<'tcx>, projection_ty: ty::ProjectionTy<'tcx>, cause: ObligationCause<'tcx>) -> Ty<'tcx> @@ -187,7 +187,7 @@ impl<'tcx> FulfillmentContext<'tcx> { pub fn select_all_or_error<'a>(&mut self, infcx: &InferCtxt<'a,'tcx>, param_env: &ty::ParameterEnvironment<'tcx>, - typer: &Typer<'tcx>) + typer: &ty::UnboxedClosureTyper<'tcx>) -> Result<(),Vec>> { try!(self.select_where_possible(infcx, param_env, typer)); @@ -213,7 +213,7 @@ impl<'tcx> FulfillmentContext<'tcx> { pub fn select_new_obligations<'a>(&mut self, infcx: &InferCtxt<'a,'tcx>, param_env: &ty::ParameterEnvironment<'tcx>, - typer: &Typer<'tcx>) + typer: &ty::UnboxedClosureTyper<'tcx>) -> Result<(),Vec>> { let mut selcx = SelectionContext::new(infcx, param_env, typer); @@ -223,7 +223,7 @@ impl<'tcx> FulfillmentContext<'tcx> { pub fn select_where_possible<'a>(&mut self, infcx: &InferCtxt<'a,'tcx>, param_env: &ty::ParameterEnvironment<'tcx>, - typer: &Typer<'tcx>) + typer: &ty::UnboxedClosureTyper<'tcx>) -> Result<(),Vec>> { let mut selcx = SelectionContext::new(infcx, param_env, typer); diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 28a826b859b4c..c84f31bf6c3bc 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -102,7 +102,7 @@ pub fn poly_project_and_unify_type<'cx,'tcx>( /// Compute result of projecting an associated type and unify it with /// `obligation.predicate.ty` (if we can). -pub fn project_and_unify_type<'cx,'tcx>( +fn project_and_unify_type<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, obligation: &ProjectionObligation<'tcx>) -> Result>>, MismatchedProjectionTypes<'tcx>> @@ -135,9 +135,19 @@ pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>, cause: ObligationCause<'tcx>, value: &T) -> Normalized<'tcx, T> - where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx> { - let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, 0); + normalize_with_depth(selcx, cause, 0, value) +} + +pub fn normalize_with_depth<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>, + cause: ObligationCause<'tcx>, + depth: uint, + value: &T) + -> Normalized<'tcx, T> + where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx> +{ + let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth); let result = normalizer.fold(value); Normalized { value: result, @@ -278,9 +288,10 @@ fn opt_normalize_projection_type<'a,'b,'tcx>( // an impl, where-clause etc) and hence we must // re-normalize it - debug!("normalize_projection_type: projected_ty={} depth={}", + debug!("normalize_projection_type: projected_ty={} depth={} obligations={}", projected_ty.repr(selcx.tcx()), - depth); + depth, + obligations.repr(selcx.tcx())); if ty::type_has_projection(projected_ty) { let tcx = selcx.tcx(); @@ -644,3 +655,20 @@ impl<'tcx> Repr<'tcx> for ProjectionTyCandidate<'tcx> { } } } + +impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Normalized<'tcx, T> { + fn fold_with>(&self, folder: &mut F) -> Normalized<'tcx, T> { + Normalized { + value: self.value.fold_with(folder), + obligations: self.obligations.fold_with(folder), + } + } +} + +impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Normalized<'tcx, T> { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { + format!("Normalized({},{})", + self.value.repr(tcx), + self.obligations.repr(tcx)) + } +} diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index ce5337a58e10c..f9dced088f8c1 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -18,6 +18,7 @@ use self::BuiltinBoundConditions::*; use self::EvaluationResult::*; use super::{DerivedObligationCause}; +use super::{project}; use super::{PredicateObligation, Obligation, TraitObligation, ObligationCause}; use super::{ObligationCauseCode, BuiltinDerivedObligation}; use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch}; @@ -29,7 +30,7 @@ use super::{util}; use middle::fast_reject; use middle::mem_categorization::Typer; -use middle::subst::{Subst, Substs, VecPerParamSpace}; +use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace}; use middle::ty::{mod, AsPredicate, RegionEscape, ToPolyTraitRef, Ty}; use middle::infer; use middle::infer::{InferCtxt, TypeFreshener}; @@ -44,7 +45,7 @@ use util::ppaux::Repr; pub struct SelectionContext<'cx, 'tcx:'cx> { infcx: &'cx InferCtxt<'cx, 'tcx>, param_env: &'cx ty::ParameterEnvironment<'tcx>, - typer: &'cx (Typer<'tcx>+'cx), + closure_typer: &'cx (ty::UnboxedClosureTyper<'tcx>+'cx), /// Freshener used specifically for skolemizing entries on the /// obligation stack. This ensures that all entries on the stack @@ -177,12 +178,12 @@ enum EvaluationResult<'tcx> { impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>, param_env: &'cx ty::ParameterEnvironment<'tcx>, - typer: &'cx Typer<'tcx>) + closure_typer: &'cx ty::UnboxedClosureTyper<'tcx>) -> SelectionContext<'cx, 'tcx> { SelectionContext { infcx: infcx, param_env: param_env, - typer: typer, + closure_typer: closure_typer, freshener: infcx.freshener(), intercrate: false, } @@ -190,12 +191,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>, param_env: &'cx ty::ParameterEnvironment<'tcx>, - typer: &'cx Typer<'tcx>) + closure_typer: &'cx ty::UnboxedClosureTyper<'tcx>) -> SelectionContext<'cx, 'tcx> { SelectionContext { infcx: infcx, param_env: param_env, - typer: typer, + closure_typer: closure_typer, freshener: infcx.freshener(), intercrate: true, } @@ -918,15 +919,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { kind, obligation.repr(self.tcx())); - let closure_kind = match self.typer.unboxed_closures().borrow().get(&closure_def_id) { - Some(closure) => closure.kind, - None => { - self.tcx().sess.span_bug( - obligation.cause.span, - format!("No entry for unboxed closure: {}", - closure_def_id.repr(self.tcx()))[]); - } - }; + let closure_kind = self.closure_typer.unboxed_closure_kind(closure_def_id); debug!("closure_kind = {}", closure_kind); @@ -1398,32 +1391,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Ok(ParameterBuiltin); } - match self.tcx().freevars.borrow().get(&def_id.node) { - None => { - // No upvars. - Ok(If(Vec::new())) + match self.closure_typer.unboxed_closure_upvars(def_id, substs) { + Some(upvars) => { + Ok(If(upvars.iter().map(|c| c.ty).collect())) } - - Some(freevars) => { - let tys: Vec = - freevars - .iter() - .map(|freevar| { - let freevar_def_id = freevar.def.def_id(); - self.typer.node_ty(freevar_def_id.node).subst(self.tcx(), substs) - }) - .collect(); - Ok(If(tys)) + None => { + Ok(AmbiguousBuiltin) } } } ty::ty_struct(def_id, substs) => { let types: Vec = - ty::struct_fields(self.tcx(), def_id, substs) - .iter() - .map(|f| f.mt.ty) - .collect(); + ty::struct_fields(self.tcx(), def_id, substs).iter() + .map(|f| f.mt.ty) + .collect(); nominal(self, bound, def_id, types) } @@ -1798,27 +1780,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { closure_def_id.repr(self.tcx()), substs.repr(self.tcx())); - let closure_type = match self.typer.unboxed_closures().borrow().get(&closure_def_id) { - Some(closure) => closure.closure_type.clone(), - None => { - self.tcx().sess.span_bug( - obligation.cause.span, - format!("No entry for unboxed closure: {}", - closure_def_id.repr(self.tcx()))[]); - } - }; + let closure_type = self.closure_typer.unboxed_closure_type(closure_def_id, substs); + + debug!("confirm_unboxed_closure_candidate: closure_def_id={} closure_type={}", + closure_def_id.repr(self.tcx()), + closure_type.repr(self.tcx())); let closure_sig = &closure_type.sig; let arguments_tuple = closure_sig.0.inputs[0]; - let substs = + let trait_substs = Substs::new_trait( - vec![arguments_tuple.subst(self.tcx(), substs), - closure_sig.0.output.unwrap().subst(self.tcx(), substs)], + vec![arguments_tuple, closure_sig.0.output.unwrap()], vec![], obligation.self_ty()); let trait_ref = ty::Binder(Rc::new(ty::TraitRef { def_id: obligation.predicate.def_id(), - substs: self.tcx().mk_substs(substs), + substs: self.tcx().mk_substs(trait_substs), })); debug!("confirm_unboxed_closure_candidate(closure_def_id={}, trait_ref={})", @@ -2100,7 +2077,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn impl_predicates(&self, + fn impl_predicates(&mut self, cause: ObligationCause<'tcx>, recursion_depth: uint, impl_def_id: ast::DefId, @@ -2111,8 +2088,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { { let impl_generics = ty::lookup_item_type(self.tcx(), impl_def_id).generics; let bounds = impl_generics.to_bounds(self.tcx(), impl_substs); - let bounds = self.infcx().plug_leaks(skol_map, snapshot, &bounds); - util::predicates_for_generics(self.tcx(), cause, recursion_depth, &bounds) + let normalized_bounds = + project::normalize_with_depth(self, cause.clone(), recursion_depth, &bounds); + let normalized_bounds = + self.infcx().plug_leaks(skol_map, snapshot, &normalized_bounds); + let mut impl_obligations = + util::predicates_for_generics(self.tcx(), + cause, + recursion_depth, + &normalized_bounds.value); + for obligation in normalized_bounds.obligations.into_iter() { + impl_obligations.push(TypeSpace, obligation); + } + impl_obligations } fn fn_family_trait_kind(&self, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 8e7470f5084b0..edfbbaae97b9a 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2259,6 +2259,23 @@ impl UnboxedClosureKind { } } +pub trait UnboxedClosureTyper<'tcx> { + fn unboxed_closure_kind(&self, + def_id: ast::DefId) + -> ty::UnboxedClosureKind; + + fn unboxed_closure_type(&self, + def_id: ast::DefId, + substs: &subst::Substs<'tcx>) + -> ty::ClosureTy<'tcx>; + + // Returns `None` if the upvar types cannot yet be definitively determined. + fn unboxed_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>>) @@ -3345,7 +3362,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { ty_unboxed_closure(did, r, substs) => { // FIXME(#14449): `borrowed_contents` below assumes `&mut` // unboxed closure. - let upvars = unboxed_closure_upvars(cx, did, substs); + let upvars = unboxed_closure_upvars(cx, did, substs).unwrap(); TypeContents::union(upvars.as_slice(), |f| tc_ty(cx, f.ty, cache)) | borrowed_contents(*r, MutMutable) @@ -3625,7 +3642,7 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool { } ty_unboxed_closure(did, _, substs) => { - let upvars = unboxed_closure_upvars(cx, did, substs); + let upvars = unboxed_closure_upvars(cx, did, substs).unwrap(); upvars.iter().any(|f| type_requires(cx, seen, r_ty, f.ty)) } @@ -3717,7 +3734,7 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>) find_nonrepresentable(cx, sp, seen, iter) } ty_unboxed_closure(did, _, substs) => { - let upvars = unboxed_closure_upvars(cx, did, substs); + let upvars = unboxed_closure_upvars(cx, did, substs).unwrap(); find_nonrepresentable(cx, sp, seen, upvars.iter().map(|f| f.ty)) } _ => Representable, @@ -5648,7 +5665,7 @@ pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec> { }).collect() } -#[deriving(Copy)] +#[deriving(Copy, Clone)] pub struct UnboxedClosureUpvar<'tcx> { pub def: def::Def, pub span: Span, @@ -5656,38 +5673,67 @@ pub struct UnboxedClosureUpvar<'tcx> { } // Returns a list of `UnboxedClosureUpvar`s for each upvar. -pub fn unboxed_closure_upvars<'tcx>(tcx: &ctxt<'tcx>, closure_id: ast::DefId, substs: &Substs<'tcx>) - -> Vec> { +pub fn unboxed_closure_upvars<'tcx>(typer: &mc::Typer<'tcx>, + closure_id: ast::DefId, + substs: &Substs<'tcx>) + -> Option>> +{ // Presently an unboxed closure type cannot "escape" out of a // function, so we will only encounter ones that originated in the // local crate or were inlined into it along with some function. // This may change if abstract return types of some sort are // implemented. assert!(closure_id.krate == ast::LOCAL_CRATE); + let tcx = typer.tcx(); let capture_mode = tcx.capture_modes.borrow()[closure_id.node].clone(); match tcx.freevars.borrow().get(&closure_id.node) { - None => vec![], + None => Some(vec![]), Some(ref freevars) => { - freevars.iter().map(|freevar| { - let freevar_def_id = freevar.def.def_id(); - let freevar_ty = node_id_to_type(tcx, freevar_def_id.node); - let mut freevar_ty = freevar_ty.subst(tcx, substs); - if capture_mode == ast::CaptureByRef { - let borrow = tcx.upvar_borrow_map.borrow()[ty::UpvarId { - var_id: freevar_def_id.node, - closure_expr_id: closure_id.node - }].clone(); - freevar_ty = mk_rptr(tcx, tcx.mk_region(borrow.region), ty::mt { - ty: freevar_ty, - mutbl: borrow.kind.to_mutbl_lossy() - }); - } - UnboxedClosureUpvar { - def: freevar.def, - span: freevar.span, - ty: freevar_ty - } - }).collect() + freevars.iter() + .map(|freevar| { + let freevar_def_id = freevar.def.def_id(); + let freevar_ty = typer.node_ty(freevar_def_id.node); + let freevar_ty = freevar_ty.subst(tcx, substs); + + match capture_mode { + ast::CaptureByValue => { + Some(UnboxedClosureUpvar { def: freevar.def, + span: freevar.span, + ty: freevar_ty }) + } + + ast::CaptureByRef => { + let upvar_id = ty::UpvarId { + var_id: freevar_def_id.node, + closure_expr_id: closure_id.node + }; + + // FIXME + let freevar_ref_ty = match typer.upvar_borrow(upvar_id) { + Some(borrow) => { + mk_rptr(tcx, + tcx.mk_region(borrow.region), + ty::mt { + ty: freevar_ty, + mutbl: borrow.kind.to_mutbl_lossy(), + }) + } + None => { + // FIXME(#16640) we should really return None here; + // but that requires better inference integration, + // for now gin up something. + freevar_ty + } + }; + Some(UnboxedClosureUpvar { + def: freevar.def, + span: freevar.span, + ty: freevar_ref_ty, + }) + } + } + }) + .collect() } } } @@ -6501,21 +6547,42 @@ impl<'tcx> mc::Typer<'tcx> for ty::ctxt<'tcx> { self.region_maps.temporary_scope(rvalue_id) } - fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow { - self.upvar_borrow_map.borrow()[upvar_id].clone() + fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option { + Some(self.upvar_borrow_map.borrow()[upvar_id].clone()) } fn capture_mode(&self, closure_expr_id: ast::NodeId) -> ast::CaptureClause { self.capture_modes.borrow()[closure_expr_id].clone() } +} - fn unboxed_closures<'a>(&'a self) - -> &'a RefCell>> { - &self.unboxed_closures +impl<'tcx> UnboxedClosureTyper<'tcx> for ty::ctxt<'tcx> { + fn unboxed_closure_kind(&self, + def_id: ast::DefId) + -> ty::UnboxedClosureKind + { + self.unboxed_closures.borrow()[def_id].kind + } + + fn unboxed_closure_type(&self, + def_id: ast::DefId, + substs: &subst::Substs<'tcx>) + -> ty::ClosureTy<'tcx> + { + self.unboxed_closures.borrow()[def_id].closure_type.subst(self, substs) + } + + fn unboxed_closure_upvars(&self, + def_id: ast::DefId, + substs: &Substs<'tcx>) + -> Option>> + { + unboxed_closure_upvars(self, def_id, substs) } } + /// The category of explicit self. #[deriving(Clone, Copy, Eq, PartialEq, Show)] pub enum ExplicitSelfCategory { @@ -7032,12 +7099,30 @@ pub trait HasProjectionTypes { fn has_projection_types(&self) -> bool; } +impl<'tcx,T:HasProjectionTypes> HasProjectionTypes for Vec { + fn has_projection_types(&self) -> bool { + self.iter().any(|p| p.has_projection_types()) + } +} + impl<'tcx,T:HasProjectionTypes> HasProjectionTypes for VecPerParamSpace { fn has_projection_types(&self) -> bool { self.iter().any(|p| p.has_projection_types()) } } +impl<'tcx> HasProjectionTypes for ClosureTy<'tcx> { + fn has_projection_types(&self) -> bool { + self.sig.has_projection_types() + } +} + +impl<'tcx> HasProjectionTypes for UnboxedClosureUpvar<'tcx> { + fn has_projection_types(&self) -> bool { + self.ty.has_projection_types() + } +} + impl<'tcx> HasProjectionTypes for ty::GenericBounds<'tcx> { fn has_projection_types(&self) -> bool { self.predicates.has_projection_types() @@ -7237,3 +7322,23 @@ impl ReferencesError for Region false } } + +impl<'tcx> Repr<'tcx> for ClosureTy<'tcx> { + fn repr(&self, tcx: &ctxt<'tcx>) -> String { + format!("ClosureTy({},{},{},{},{},{})", + self.unsafety, + self.onceness, + self.store, + self.bounds.repr(tcx), + self.sig.repr(tcx), + self.abi) + } +} + +impl<'tcx> Repr<'tcx> for UnboxedClosureUpvar<'tcx> { + fn repr(&self, tcx: &ctxt<'tcx>) -> String { + format!("UnboxedClosureUpvar({},{})", + self.def.repr(tcx), + self.ty.repr(tcx)) + } +} diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 1e7605c0f171c..83d2f6fb0e6d5 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -532,6 +532,16 @@ impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate } } +impl<'tcx> TypeFoldable<'tcx> for ty::UnboxedClosureUpvar<'tcx> { + fn fold_with>(&self, folder: &mut F) -> ty::UnboxedClosureUpvar<'tcx> { + ty::UnboxedClosureUpvar { + def: self.def, + span: self.span, + ty: self.ty.fold_with(folder), + } + } +} + /////////////////////////////////////////////////////////////////////////// // "super" routines: these are the default implementations for TypeFolder. // diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index d01047c53b955..24a3bb42c90f7 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -168,7 +168,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Univariant(mk_struct(cx, ftys[], packed, t), dtor) } ty::ty_unboxed_closure(def_id, _, substs) => { - let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id, substs); + let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id, substs).unwrap(); let upvar_types = upvars.iter().map(|u| u.ty).collect::>(); Univariant(mk_struct(cx, upvar_types[], false, t), false) } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 475443654264f..18155d756807c 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -43,7 +43,7 @@ use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; use middle::subst; use middle::weak_lang_items; use middle::subst::{Subst, Substs}; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, Ty, UnboxedClosureTyper}; use session::config::{mod, NoDebugInfo, FullDebugInfo}; use session::Session; use trans::_match; @@ -257,12 +257,12 @@ fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>, } pub fn self_type_for_unboxed_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - closure_id: ast::DefId, - fn_ty: Ty<'tcx>) - -> Ty<'tcx> { - let unboxed_closures = ccx.tcx().unboxed_closures.borrow(); - let unboxed_closure = &(*unboxed_closures)[closure_id]; - match unboxed_closure.kind { + closure_id: ast::DefId, + fn_ty: Ty<'tcx>) + -> Ty<'tcx> +{ + let unboxed_closure_kind = ccx.tcx().unboxed_closure_kind(closure_id); + match unboxed_closure_kind { ty::FnUnboxedClosureKind => { ty::mk_imm_rptr(ccx.tcx(), ccx.tcx().mk_region(ty::ReStatic), fn_ty) } @@ -291,13 +291,15 @@ pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, (f.sig.0.inputs.clone(), f.sig.0.output, f.abi, Some(Type::i8p(ccx))) } ty::ty_unboxed_closure(closure_did, _, substs) => { - let unboxed_closures = ccx.tcx().unboxed_closures.borrow(); - let unboxed_closure = &(*unboxed_closures)[closure_did]; - let function_type = unboxed_closure.closure_type.clone(); + let typer = common::NormalizingUnboxedClosureTyper::new(ccx.tcx()); + let function_type = typer.unboxed_closure_type(closure_did, substs); let self_type = self_type_for_unboxed_closure(ccx, closure_did, fn_ty); let llenvironment_type = type_of_explicit_arg(ccx, self_type); - (function_type.sig.0.inputs.iter().map(|t| t.subst(ccx.tcx(), substs)).collect(), - function_type.sig.0.output.subst(ccx.tcx(), substs), + debug!("decl_rust_fn: function_type={} self_type={}", + function_type.repr(ccx.tcx()), + self_type.repr(ccx.tcx())); + (function_type.sig.0.inputs, + function_type.sig.0.output, RustCall, Some(llenvironment_type)) } @@ -729,7 +731,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, } ty::ty_unboxed_closure(def_id, _, substs) => { let repr = adt::represent_type(cx.ccx(), t); - let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id, substs); + let upvars = ty::unboxed_closure_upvars(cx.tcx(), 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); @@ -2436,11 +2438,9 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< ty::ty_closure(ref f) => (f.sig.clone(), f.abi, true), ty::ty_bare_fn(_, ref f) => (f.sig.clone(), f.abi, false), ty::ty_unboxed_closure(closure_did, _, substs) => { - let unboxed_closures = ccx.tcx().unboxed_closures.borrow(); - let ref function_type = (*unboxed_closures)[closure_did] - .closure_type; - - (function_type.sig.subst(ccx.tcx(), substs), RustCall, true) + let typer = common::NormalizingUnboxedClosureTyper::new(ccx.tcx()); + let function_type = typer.unboxed_closure_type(closure_did, substs); + (function_type.sig, RustCall, true) } _ => ccx.sess().bug("expected closure or function.") }; diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index 3723ad07a36ec..93a5b54fde3e5 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -22,11 +22,11 @@ use trans::common::*; use trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum}; use trans::debuginfo; use trans::expr; -use trans::monomorphize::MonoId; +use trans::monomorphize::{mod, MonoId}; use trans::type_of::*; use trans::type_::Type; -use middle::ty::{mod, Ty}; -use middle::subst::{Subst, Substs}; +use middle::ty::{mod, Ty, UnboxedClosureTyper}; +use middle::subst::{Substs}; use session::config::FullDebugInfo; use util::ppaux::Repr; use util::ppaux::ty_to_string; @@ -464,7 +464,7 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk, } let function_type = ty::node_id_to_type(bcx.tcx(), closure_id.node); - let function_type = function_type.subst(bcx.tcx(), substs); + let function_type = monomorphize::apply_param_substs(bcx.tcx(), substs, &function_type); // Normalize type so differences in regions and typedefs don't cause // duplicate declarations @@ -511,7 +511,8 @@ pub fn trans_unboxed_closure<'blk, 'tcx>( body: &ast::Block, id: ast::NodeId, dest: expr::Dest) - -> Block<'blk, 'tcx> { + -> Block<'blk, 'tcx> +{ let _icx = push_ctxt("closure::trans_unboxed_closure"); debug!("trans_unboxed_closure()"); @@ -522,9 +523,13 @@ pub fn trans_unboxed_closure<'blk, 'tcx>( closure_id, bcx.fcx.param_substs).unwrap(); - let function_type = (*bcx.tcx().unboxed_closures.borrow())[closure_id] - .closure_type - .clone(); + // Get the type of this closure. Use the current `param_substs` as + // the closure substitutions. This makes sense because the closure + // takes the same set of type arguments as the enclosing fn, and + // this function (`trans_unboxed_closure`) is invoked at the point + // of the closure expression. + let typer = NormalizingUnboxedClosureTyper::new(bcx.tcx()); + let function_type = typer.unboxed_closure_type(closure_id, bcx.fcx.param_substs); let function_type = ty::mk_closure(bcx.tcx(), function_type); let freevars: Vec = diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 7c2585becea8c..aa88224088063 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -39,7 +39,7 @@ use middle::ty::{mod, HasProjectionTypes, Ty}; use middle::ty_fold; use middle::ty_fold::{TypeFolder, TypeFoldable}; use util::ppaux::Repr; -use util::nodemap::{DefIdMap, FnvHashMap, NodeMap}; +use util::nodemap::{FnvHashMap, NodeMap}; use arena::TypedArena; use libc::{c_uint, c_char}; @@ -617,13 +617,8 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { self.tcx().region_maps.temporary_scope(rvalue_id) } - fn unboxed_closures<'a>(&'a self) - -> &'a RefCell>> { - &self.tcx().unboxed_closures - } - - fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow { - self.tcx().upvar_borrow_map.borrow()[upvar_id].clone() + fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option { + Some(self.tcx().upvar_borrow_map.borrow()[upvar_id].clone()) } fn capture_mode(&self, closure_expr_id: ast::NodeId) @@ -632,6 +627,34 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { } } +impl<'blk, 'tcx> ty::UnboxedClosureTyper<'tcx> for BlockS<'blk, 'tcx> { + fn unboxed_closure_kind(&self, + def_id: ast::DefId) + -> ty::UnboxedClosureKind + { + let typer = NormalizingUnboxedClosureTyper::new(self.tcx()); + typer.unboxed_closure_kind(def_id) + } + + fn unboxed_closure_type(&self, + def_id: ast::DefId, + substs: &subst::Substs<'tcx>) + -> ty::ClosureTy<'tcx> + { + let typer = NormalizingUnboxedClosureTyper::new(self.tcx()); + typer.unboxed_closure_type(def_id, substs) + } + + fn unboxed_closure_upvars(&self, + def_id: ast::DefId, + substs: &Substs<'tcx>) + -> Option>> + { + let typer = NormalizingUnboxedClosureTyper::new(self.tcx()); + typer.unboxed_closure_upvars(def_id, substs) + } +} + pub struct Result<'blk, 'tcx: 'blk> { pub bcx: Block<'blk, 'tcx>, pub val: ValueRef @@ -924,7 +947,8 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - let mut selcx = traits::SelectionContext::new(&infcx, ¶m_env, tcx); + let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx); + let mut selcx = traits::SelectionContext::new(&infcx, ¶m_env, &typer); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), trait_ref.to_poly_trait_predicate()); let selection = match selcx.select(&obligation) { @@ -968,6 +992,47 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, vtable } +pub struct NormalizingUnboxedClosureTyper<'a,'tcx:'a> { + tcx: &'a ty::ctxt<'tcx> +} + +impl<'a,'tcx> NormalizingUnboxedClosureTyper<'a,'tcx> { + pub fn new(tcx: &'a ty::ctxt<'tcx>) -> NormalizingUnboxedClosureTyper<'a,'tcx> { + NormalizingUnboxedClosureTyper { tcx: tcx } + } +} + +impl<'a,'tcx> ty::UnboxedClosureTyper<'tcx> for NormalizingUnboxedClosureTyper<'a,'tcx> { + fn unboxed_closure_kind(&self, + def_id: ast::DefId) + -> ty::UnboxedClosureKind + { + self.tcx.unboxed_closure_kind(def_id) + } + + fn unboxed_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.tcx.unboxed_closure_type(def_id, substs); + monomorphize::normalize_associated_type(self.tcx, &closure_ty) + } + + fn unboxed_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 = ty::unboxed_closure_upvars(self.tcx, def_id, substs); + monomorphize::normalize_associated_type(self.tcx, &result) + } +} + pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span, infcx: &infer::InferCtxt<'a,'tcx>, param_env: &ty::ParameterEnvironment<'tcx>, @@ -982,7 +1047,8 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span, // 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, param_env, infcx.tcx) { + let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx); + match fulfill_cx.select_all_or_error(infcx, param_env, &typer) { Ok(()) => { } Err(errors) => { if errors.iter().all(|e| e.is_overflow()) { diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index bce446b741271..c651255226b5a 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -194,13 +194,13 @@ use llvm; use llvm::{ModuleRef, ContextRef, ValueRef}; use llvm::debuginfo::*; use metadata::csearch; -use middle::subst::{mod, Subst, Substs}; +use middle::subst::{mod, Substs}; use trans::{mod, adt, machine, type_of}; use trans::common::*; use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef}; use trans::monomorphize; use trans::type_::Type; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, Ty, UnboxedClosureTyper}; use middle::pat_util; use session::config::{mod, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet}; @@ -470,9 +470,9 @@ impl<'tcx> TypeMap<'tcx> { closure_ty.clone(), &mut unique_type_id); }, - ty::ty_unboxed_closure(ref def_id, _, substs) => { - let closure_ty = cx.tcx().unboxed_closures.borrow() - .get(def_id).unwrap().closure_type.subst(cx.tcx(), substs); + ty::ty_unboxed_closure(def_id, _, substs) => { + let typer = NormalizingUnboxedClosureTyper::new(cx.tcx()); + let closure_ty = typer.unboxed_closure_type(def_id, substs); self.get_unique_type_id_of_closure_type(cx, closure_ty, &mut unique_type_id); @@ -3020,9 +3020,9 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::ty_closure(ref closurety) => { subroutine_type_metadata(cx, unique_type_id, &closurety.sig, usage_site_span) } - ty::ty_unboxed_closure(ref def_id, _, substs) => { - let sig = cx.tcx().unboxed_closures.borrow() - .get(def_id).unwrap().closure_type.sig.subst(cx.tcx(), substs); + ty::ty_unboxed_closure(def_id, _, substs) => { + let typer = NormalizingUnboxedClosureTyper::new(cx.tcx()); + let sig = typer.unboxed_closure_type(def_id, substs).sig; subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span) } ty::ty_struct(def_id, substs) => { diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index 7646aa086eb1c..7c8ba08d98750 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -323,7 +323,8 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T let infcx = infer::new_infer_ctxt(tcx); let param_env = ty::empty_parameter_environment(); - let mut selcx = traits::SelectionContext::new(&infcx, ¶m_env, tcx); + let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx); + let mut selcx = traits::SelectionContext::new(&infcx, ¶m_env, &typer); let cause = traits::ObligationCause::dummy(); let traits::Normalized { value: result, obligations } = traits::normalize(&mut selcx, cause, value); diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs index 98081e28f2fd7..5e9843d0e00bf 100644 --- a/src/librustc_typeck/check/assoc.rs +++ b/src/librustc_typeck/check/assoc.rs @@ -9,7 +9,6 @@ // except according to those terms. use middle::infer::InferCtxt; -use middle::mem_categorization as mc; use middle::traits::{mod, FulfillmentContext, Normalized, MiscObligation, SelectionContext, ObligationCause}; use middle::ty::{mod, HasProjectionTypes}; @@ -20,7 +19,7 @@ use util::ppaux::Repr; pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, param_env: &ty::ParameterEnvironment<'tcx>, - typer: &(mc::Typer<'tcx>+'a), + typer: &(ty::UnboxedClosureTyper<'tcx>+'a), fulfillment_cx: &mut FulfillmentContext<'tcx>, span: Span, body_id: ast::NodeId, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2e3552047b48b..6868c876ff562 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -319,15 +319,37 @@ impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> { fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option { self.tcx().temporary_scope(rvalue_id) } - fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow { - self.inh.upvar_borrow_map.borrow()[upvar_id].clone() + fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option { + self.inh.upvar_borrow_map.borrow().get(&upvar_id).cloned() } fn capture_mode(&self, closure_expr_id: ast::NodeId) -> ast::CaptureClause { self.ccx.tcx.capture_mode(closure_expr_id) } - fn unboxed_closures(&self) -> &RefCell>> { - &self.inh.unboxed_closures +} + +impl<'a, 'tcx> ty::UnboxedClosureTyper<'tcx> for FnCtxt<'a, 'tcx> { + fn unboxed_closure_kind(&self, + def_id: ast::DefId) + -> ty::UnboxedClosureKind + { + self.inh.unboxed_closures.borrow()[def_id].kind + } + + fn unboxed_closure_type(&self, + def_id: ast::DefId, + substs: &subst::Substs<'tcx>) + -> ty::ClosureTy<'tcx> + { + self.inh.unboxed_closures.borrow()[def_id].closure_type.subst(self.tcx(), substs) + } + + fn unboxed_closure_upvars(&self, + def_id: ast::DefId, + substs: &Substs<'tcx>) + -> Option>> + { + ty::unboxed_closure_upvars(self, def_id, substs) } } @@ -352,7 +374,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { } fn normalize_associated_types_in(&self, - typer: &mc::Typer<'tcx>, + typer: &ty::UnboxedClosureTyper<'tcx>, span: Span, body_id: ast::NodeId, value: &T)