diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index baecfb7eb22c5..b33839f33e820 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -555,11 +555,9 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w 'k' => { assert_eq!(next(st), '['); let did = parse_def_(st, ClosureSource, conv); - let region = parse_region_(st, conv); let substs = parse_substs_(st, conv); assert_eq!(next(st), ']'); - return ty::mk_closure(st.tcx, did, - st.tcx.mk_region(region), st.tcx.mk_substs(substs)); + return ty::mk_closure(st.tcx, did, st.tcx.mk_substs(substs)); } 'P' => { assert_eq!(next(st), '['); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 76a365259aa57..ebb4153e32bce 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -139,9 +139,8 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t enc_substs(w, cx, substs); mywrite!(w, "]"); } - ty::ty_closure(def, region, substs) => { + ty::ty_closure(def, substs) => { mywrite!(w, "k[{}|", (cx.ds)(def)); - enc_region(w, cx, *region); enc_substs(w, cx, substs); mywrite!(w, "]"); } diff --git a/src/librustc/middle/fast_reject.rs b/src/librustc/middle/fast_reject.rs index 7584a2e44cc7c..063845c6c3425 100644 --- a/src/librustc/middle/fast_reject.rs +++ b/src/librustc/middle/fast_reject.rs @@ -74,7 +74,7 @@ pub fn simplify_type(tcx: &ty::ctxt, let def_id = tcx.lang_items.owned_box().unwrap(); Some(StructSimplifiedType(def_id)) } - ty::ty_closure(def_id, _, _) => { + ty::ty_closure(def_id, _) => { Some(ClosureSimplifiedType(def_id)) } ty::ty_tup(ref tys) => { diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index b782a655d89ff..be94a73df37ba 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -503,15 +503,14 @@ pub fn super_tys<'tcx, C>(this: &C, Ok(ty::mk_struct(tcx, a_id, tcx.mk_substs(substs))) } - (&ty::ty_closure(a_id, a_region, a_substs), - &ty::ty_closure(b_id, b_region, b_substs)) + (&ty::ty_closure(a_id, a_substs), + &ty::ty_closure(b_id, b_substs)) if a_id == b_id => { // All ty_closure types with the same id represent // the (anonymous) type of the same closure expression. So // all of their regions should be equated. - let region = try!(this.equate().regions(*a_region, *b_region)); let substs = try!(this.substs_variances(None, a_substs, b_substs)); - Ok(ty::mk_closure(tcx, a_id, tcx.mk_region(region), tcx.mk_substs(substs))) + Ok(ty::mk_closure(tcx, a_id, tcx.mk_substs(substs))) } (&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 5cb034667cc64..224a568c77f02 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1496,7 +1496,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn fn_ret(&self, id: NodeId) -> ty::PolyFnOutput<'tcx> { let fn_ty = ty::node_id_to_type(self.ir.tcx, id); match fn_ty.sty { - ty::ty_closure(closure_def_id, _, substs) => + ty::ty_closure(closure_def_id, substs) => self.ir.tcx.closure_type(closure_def_id, substs).sig.output(), _ => ty::ty_fn_ret(fn_ty), diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index c4446b87855ca..1f02f13a4a178 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -607,7 +607,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { def::DefUpvar(var_id, fn_node_id) => { let ty = try!(self.node_ty(fn_node_id)); match ty.sty { - ty::ty_closure(closure_id, _, _) => { + ty::ty_closure(closure_id, _) => { match self.typer.closure_kind(closure_id) { Some(kind) => { self.cat_upvar(id, span, var_id, fn_node_id, kind) diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 7db1138ac72f6..b4db3aba7867d 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -320,8 +320,10 @@ impl InnermostEnclosingExpr { #[derive(Debug, Copy)] pub struct Context { + /// the scope that contains any new variables declared var_parent: InnermostDeclaringBlock, + /// region parent of expressions etc parent: InnermostEnclosingExpr, } diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 7d4febb38e678..b9a863f4fe46f 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -154,7 +154,7 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext debug!("consider_unification_despite_ambiguity: self_ty.sty={:?}", self_ty.sty); match self_ty.sty { - ty::ty_closure(closure_def_id, _, substs) => { + ty::ty_closure(closure_def_id, substs) => { let closure_typer = selcx.closure_typer(); let closure_type = closure_typer.closure_type(closure_def_id, substs); let ty::Binder((_, ret_type)) = diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index d8c62780a781f..470315c78f81d 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -293,7 +293,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // lifetimes can appear inside the self-type. let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); let (closure_def_id, substs) = match self_ty.sty { - ty::ty_closure(id, _, ref substs) => (id, substs.clone()), + ty::ty_closure(id, ref substs) => (id, substs.clone()), _ => { return; } }; assert!(!substs.has_escaping_regions()); @@ -1054,7 +1054,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); let (closure_def_id, substs) = match self_ty.sty { - ty::ty_closure(id, _, ref substs) => (id, substs.clone()), + ty::ty_closure(id, ref substs) => (id, substs.clone()), ty::ty_infer(ty::TyVar(_)) => { debug!("assemble_unboxed_closure_candidates: ambiguous self-type"); candidates.ambiguous = true; @@ -1533,7 +1533,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet ty::ty_tup(ref tys) => Ok(If(tys.clone())), - ty::ty_closure(def_id, _, substs) => { + ty::ty_closure(def_id, substs) => { // FIXME -- This case is tricky. In the case of by-ref // closures particularly, we need the results of // inference to decide how to reflect the type of each @@ -1687,7 +1687,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Some(tys.clone()) } - ty::ty_closure(def_id, _, substs) => { + ty::ty_closure(def_id, substs) => { assert_eq!(def_id.krate, ast::LOCAL_CRATE); match self.closure_typer.closure_upvars(def_id, substs) { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 635ec09d3394c..aaba840825e69 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1367,7 +1367,7 @@ pub enum sty<'tcx> { ty_trait(Box>), ty_struct(DefId, &'tcx Substs<'tcx>), - ty_closure(DefId, &'tcx Region, &'tcx Substs<'tcx>), + ty_closure(DefId, &'tcx Substs<'tcx>), ty_tup(Vec>), @@ -2658,8 +2658,7 @@ impl FlagComputation { } } - &ty_closure(_, region, substs) => { - self.add_region(*region); + &ty_closure(_, substs) => { self.add_substs(substs); } @@ -2927,10 +2926,9 @@ pub fn mk_struct<'tcx>(cx: &ctxt<'tcx>, struct_id: ast::DefId, mk_t(cx, ty_struct(struct_id, substs)) } -pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, closure_id: ast::DefId, - region: &'tcx Region, substs: &'tcx Substs<'tcx>) +pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, closure_id: ast::DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { - mk_t(cx, ty_closure(closure_id, region, substs)) + mk_t(cx, ty_closure(closure_id, substs)) } pub fn mk_var<'tcx>(cx: &ctxt<'tcx>, v: TyVid) -> Ty<'tcx> { @@ -3513,13 +3511,11 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { apply_lang_items(cx, did, res) } - ty_closure(did, r, substs) => { + ty_closure(did, substs) => { // FIXME(#14449): `borrowed_contents` below assumes `&mut` closure. let param_env = ty::empty_parameter_environment(cx); let upvars = closure_upvars(¶m_env, did, substs).unwrap(); - TypeContents::union(&upvars, - |f| tc_ty(cx, &f.ty, cache)) - | borrowed_contents(*r, MutMutable) + TypeContents::union(&upvars, |f| tc_ty(cx, &f.ty, cache)) } ty_tup(ref tys) => { @@ -5175,7 +5171,7 @@ pub fn ty_to_def_id(ty: Ty) -> Option { Some(tt.principal_def_id()), ty_struct(id, _) | ty_enum(id, _) | - ty_closure(id, _, _) => + ty_closure(id, _) => Some(id), _ => None @@ -6301,10 +6297,9 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) - } ty_infer(_) => unreachable!(), ty_err => byte!(21), - ty_closure(d, r, _) => { + ty_closure(d, _) => { byte!(22); did(state, d); - region(state, *r); } ty_projection(ref data) => { byte!(23); @@ -6618,8 +6613,7 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec, ty_struct(_, substs) => { accum_substs(accumulator, substs); } - ty_closure(_, region, substs) => { - accumulator.push(*region); + ty_closure(_, substs) => { accum_substs(accumulator, substs); } ty_bool | diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 4bf47c3a75f80..1b904aacc3012 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -650,10 +650,9 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, let substs = substs.fold_with(this); ty::ty_struct(did, this.tcx().mk_substs(substs)) } - ty::ty_closure(did, ref region, ref substs) => { - let r = region.fold_with(this); + ty::ty_closure(did, ref substs) => { let s = substs.fold_with(this); - ty::ty_closure(did, this.tcx().mk_region(r), this.tcx().mk_substs(s)) + ty::ty_closure(did, this.tcx().mk_substs(s)) } ty::ty_projection(ref data) => { ty::ty_projection(data.fold_with(this)) diff --git a/src/librustc/middle/ty_walk.rs b/src/librustc/middle/ty_walk.rs index 3336e7ee8bf71..5b5eac451783a 100644 --- a/src/librustc/middle/ty_walk.rs +++ b/src/librustc/middle/ty_walk.rs @@ -45,7 +45,7 @@ impl<'tcx> TypeWalker<'tcx> { } ty::ty_enum(_, ref substs) | ty::ty_struct(_, ref substs) | - ty::ty_closure(_, _, ref substs) => { + ty::ty_closure(_, ref substs) => { self.push_reversed(substs.types.as_slice()); } ty::ty_tup(ref ts) => { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 15b3c6d9d0602..0eeb746022c0d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -406,7 +406,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { data.item_name.user_string(cx)) } ty_str => "str".to_string(), - ty_closure(ref did, _, substs) => { + ty_closure(ref did, substs) => { let closure_tys = cx.closure_tys.borrow(); closure_tys.get(did).map(|closure_type| { closure_to_string(cx, &closure_type.subst(cx, substs)) diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 3ea14d3c58929..2fb0488cd704e 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -169,7 +169,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Univariant(mk_struct(cx, &ftys[..], packed, t), dtor) } - ty::ty_closure(def_id, _, substs) => { + ty::ty_closure(def_id, substs) => { let typer = NormalizingClosureTyper::new(cx.tcx()); let upvars = typer.closure_upvars(def_id, substs).unwrap(); let upvar_types = upvars.iter().map(|u| u.ty).collect::>(); diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 1f578ac0bdbab..7a6960d379026 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -291,7 +291,7 @@ pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty::ty_bare_fn(_, ref f) => { (&f.sig, f.abi, None) } - ty::ty_closure(closure_did, _, substs) => { + ty::ty_closure(closure_did, substs) => { let typer = common::NormalizingClosureTyper::new(ccx.tcx()); function_type = typer.closure_type(closure_did, substs); let self_type = self_type_for_closure(ccx, closure_did, fn_ty); @@ -685,7 +685,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, } }) } - ty::ty_closure(def_id, _, substs) => { + ty::ty_closure(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(); @@ -2437,7 +2437,7 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< let function_type; let (fn_sig, abi, env_ty) = match fn_ty.sty { ty::ty_bare_fn(_, ref f) => (&f.sig, f.abi, None), - ty::ty_closure(closure_did, _, substs) => { + ty::ty_closure(closure_did, substs) => { let typer = common::NormalizingClosureTyper::new(ccx.tcx()); function_type = typer.closure_type(closure_did, substs); let self_type = self_type_for_closure(ccx, closure_did, fn_ty); @@ -2454,7 +2454,7 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< // These have an odd calling convention, so we need to manually // unpack the input ty's let input_tys = match fn_ty.sty { - ty::ty_closure(_, _, _) => { + ty::ty_closure(..) => { assert!(abi == RustCall); match fn_sig.inputs[0].sty { diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index 1d4bbd79d7105..7fa26a7c12841 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -138,7 +138,7 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc // duplicate declarations let function_type = erase_regions(ccx.tcx(), &function_type); let params = match function_type.sty { - ty::ty_closure(_, _, substs) => &substs.types, + ty::ty_closure(_, substs) => &substs.types, _ => unreachable!() }; let mono_id = MonoId { diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index d70a904b81189..f3b7058336b2f 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -472,7 +472,7 @@ impl<'tcx> TypeMap<'tcx> { } } }, - ty::ty_closure(def_id, _, substs) => { + ty::ty_closure(def_id, substs) => { let typer = NormalizingClosureTyper::new(cx.tcx()); let closure_ty = typer.closure_type(def_id, substs); self.get_unique_type_id_of_closure_type(cx, @@ -2983,7 +2983,7 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::ty_bare_fn(_, ref barefnty) => { subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span) } - ty::ty_closure(def_id, _, substs) => { + ty::ty_closure(def_id, substs) => { let typer = NormalizingClosureTyper::new(cx.tcx()); let sig = typer.closure_type(def_id, substs).sig; subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span) diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 0ad15456df98f..f9495af79c5b0 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -137,7 +137,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, return Some(CallStep::Builtin); } - ty::ty_closure(def_id, _, substs) => { + ty::ty_closure(def_id, substs) => { assert_eq!(def_id.krate, ast::LOCAL_CRATE); // Check whether this is a call to a closure where we diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 0b7c5b04aaa44..0d4edc01a4c1d 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -16,7 +16,6 @@ use astconv; use middle::region; use middle::subst; use middle::ty::{self, ToPolyTraitRef, Ty}; -use rscope::RegionScope; use syntax::abi; use syntax::ast; use syntax::ast_util; @@ -61,17 +60,8 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, abi::RustCall, expected_sig); - let region = match fcx.anon_regions(expr.span, 1) { - Err(_) => { - fcx.ccx.tcx.sess.span_bug(expr.span, - "can't make anon regions here?!") - } - Ok(regions) => regions[0], - }; - let closure_type = ty::mk_closure(fcx.ccx.tcx, expr_def_id, - fcx.ccx.tcx.mk_region(region), fcx.ccx.tcx.mk_substs( fcx.inh.param_env.free_substs.clone())); diff --git a/src/librustc_typeck/check/implicator.rs b/src/librustc_typeck/check/implicator.rs index f65e585d23edd..f99ba8940297d 100644 --- a/src/librustc_typeck/check/implicator.rs +++ b/src/librustc_typeck/check/implicator.rs @@ -29,6 +29,7 @@ use util::ppaux::Repr; pub enum Implication<'tcx> { RegionSubRegion(Option>, ty::Region, ty::Region), RegionSubGeneric(Option>, ty::Region, GenericKind<'tcx>), + RegionSubClosure(Option>, ty::Region, ast::DefId, &'tcx Substs<'tcx>), Predicate(ast::DefId, ty::Predicate<'tcx>), } @@ -91,29 +92,9 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> { // No borrowed content reachable here. } - ty::ty_closure(_, region, _) => { - // An "closure type" is basically - // modeled here as equivalent to a struct like - // - // struct TheClosure<'b> { - // ... - // } - // - // where the `'b` is the lifetime bound of the - // contents (i.e., all contents must outlive 'b). - // - // Even though closures are glorified structs - // of upvars, we do not need to consider them as they - // can't generate any new constraints. The - // substitutions on the closure are equal to the free - // substitutions of the enclosing parameter - // environment. An upvar captured by value has the - // same type as the original local variable which is - // already checked for consistency. If the upvar is - // captured by reference it must also outlive the - // region bound on the closure, but this is explicitly - // handled by logic in regionck. - self.push_region_constraint_from_top(*region); + ty::ty_closure(def_id, substs) => { + let &(r_a, opt_ty) = self.stack.last().unwrap(); + self.out.push(Implication::RegionSubClosure(opt_ty, r_a, def_id, substs)); } ty::ty_trait(ref t) => { @@ -448,6 +429,13 @@ impl<'tcx> Repr<'tcx> for Implication<'tcx> { p.repr(tcx)) } + Implication::RegionSubClosure(_, ref a, ref b, ref c) => { + format!("RegionSubClosure({}, {}, {})", + a.repr(tcx), + b.repr(tcx), + c.repr(tcx)) + } + Implication::Predicate(ref def_id, ref p) => { format!("Predicate({}, {})", def_id.repr(tcx), diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index f24da78bc7d39..fbf002b709ee5 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -278,7 +278,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } ty::ty_enum(did, _) | ty::ty_struct(did, _) | - ty::ty_closure(did, _, _) => { + ty::ty_closure(did, _) => { self.assemble_inherent_impl_candidates_for_type(did); } ty::ty_uniq(_) => { @@ -641,8 +641,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // If so, add "synthetic impls". let steps = self.steps.clone(); for step in &*steps { - let (closure_def_id, _, _) = match step.self_ty.sty { - ty::ty_closure(a, b, ref c) => (a, b, c), + let closure_def_id = match step.self_ty.sty { + ty::ty_closure(a, _) => a, _ => continue, }; diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 1518a09e7dc06..a3e98b0c4c658 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -87,12 +87,11 @@ use check::dropck; use check::FnCtxt; use check::implicator; use check::vtable; -use middle::def; use middle::mem_categorization as mc; use middle::region::CodeExtent; +use middle::subst::Substs; use middle::traits; -use middle::ty::{ReScope}; -use middle::ty::{self, Ty, MethodCall}; +use middle::ty::{self, ClosureTyper, ReScope, Ty, MethodCall}; use middle::infer::{self, GenericKind}; use middle::pat_util; use util::ppaux::{ty_to_string, Repr}; @@ -179,20 +178,6 @@ pub struct Rcx<'a, 'tcx: 'a> { } -/// Returns the validity region of `def` -- that is, how long is `def` valid? -fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region { - let tcx = fcx.tcx(); - match def { - def::DefLocal(node_id) | def::DefUpvar(node_id, _) => { - tcx.region_maps.var_region(node_id) - } - _ => { - tcx.sess.bug(&format!("unexpected def in region_of_def: {:?}", - def)) - } - } -} - struct RepeatingScope(ast::NodeId); pub enum SubjectNode { Subject(ast::NodeId), None } @@ -368,7 +353,15 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { ty::ReInfer(ty::ReVar(vid_b))) => { self.fcx.inh.infcx.add_given(free_a, vid_b); } - implicator::Implication::RegionSubRegion(..) => { + implicator::Implication::RegionSubGeneric(_, r_a, ref generic_b) => { + debug!("RegionSubGeneric: {} <= {}", + r_a.repr(tcx), generic_b.repr(tcx)); + + self.region_bound_pairs.push((r_a, generic_b.clone())); + } + implicator::Implication::RegionSubRegion(..) | + implicator::Implication::RegionSubClosure(..) | + implicator::Implication::Predicate(..) => { // In principle, we could record (and take // advantage of) every relationship here, but // we are also free not to -- it simply means @@ -379,13 +372,6 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { // relationship that arises here, but // presently we do not.) } - implicator::Implication::RegionSubGeneric(_, r_a, ref generic_b) => { - debug!("RegionSubGeneric: {} <= {}", - r_a.repr(tcx), generic_b.repr(tcx)); - - self.region_bound_pairs.push((r_a, generic_b.clone())); - } - implicator::Implication::Predicate(..) => { } } } } @@ -792,124 +778,9 @@ fn constrain_cast(rcx: &mut Rcx, fn check_expr_fn_block(rcx: &mut Rcx, expr: &ast::Expr, body: &ast::Block) { - let tcx = rcx.fcx.tcx(); - let function_type = rcx.resolve_node_type(expr.id); - - match function_type.sty { - ty::ty_closure(_, region, _) => { - ty::with_freevars(tcx, expr.id, |freevars| { - constrain_captured_variables(rcx, *region, expr, freevars); - }) - } - _ => { } - } - let repeating_scope = rcx.set_repeating_scope(body.id); visit::walk_expr(rcx, expr); rcx.set_repeating_scope(repeating_scope); - - match function_type.sty { - ty::ty_closure(_, region, _) => { - ty::with_freevars(tcx, expr.id, |freevars| { - let bounds = ty::region_existential_bound(*region); - ensure_free_variable_types_outlive_closure_bound(rcx, &bounds, expr, freevars); - }) - } - _ => {} - } - - /// Make sure that the type of all free variables referenced inside a closure/proc outlive the - /// closure/proc's lifetime bound. This is just a special case of the usual rules about closed - /// over values outliving the object's lifetime bound. - fn ensure_free_variable_types_outlive_closure_bound( - rcx: &mut Rcx, - bounds: &ty::ExistentialBounds, - expr: &ast::Expr, - freevars: &[ty::Freevar]) - { - let tcx = rcx.fcx.ccx.tcx; - - debug!("ensure_free_variable_types_outlive_closure_bound({}, {})", - bounds.region_bound.repr(tcx), expr.repr(tcx)); - - for freevar in freevars { - let var_node_id = { - let def_id = freevar.def.def_id(); - assert!(def_id.krate == ast::LOCAL_CRATE); - def_id.node - }; - - // Compute the type of the field in the environment that - // represents `var_node_id`. For a by-value closure, this - // will be the same as the type of the variable. For a - // by-reference closure, this will be `&T` where `T` is - // the type of the variable. - let raw_var_ty = rcx.resolve_node_type(var_node_id); - let upvar_id = ty::UpvarId { var_id: var_node_id, - closure_expr_id: expr.id }; - let var_ty = match rcx.fcx.inh.upvar_capture_map.borrow()[upvar_id] { - ty::UpvarCapture::ByRef(ref upvar_borrow) => { - ty::mk_rptr(rcx.tcx(), - rcx.tcx().mk_region(upvar_borrow.region), - ty::mt { mutbl: upvar_borrow.kind.to_mutbl_lossy(), - ty: raw_var_ty }) - } - ty::UpvarCapture::ByValue => raw_var_ty, - }; - - // Check that the type meets the criteria of the existential bounds: - for builtin_bound in &bounds.builtin_bounds { - let code = traits::ClosureCapture(var_node_id, expr.span, builtin_bound); - let cause = traits::ObligationCause::new(freevar.span, rcx.fcx.body_id, code); - rcx.fcx.register_builtin_bound(var_ty, builtin_bound, cause); - } - - type_must_outlive( - rcx, infer::FreeVariable(expr.span, var_node_id), - var_ty, bounds.region_bound); - } - } - - /// Make sure that all free variables referenced inside the closure outlive the closure's - /// lifetime bound. Also, create an entry in the upvar_borrows map with a region. - fn constrain_captured_variables( - rcx: &mut Rcx, - region_bound: ty::Region, - expr: &ast::Expr, - freevars: &[ty::Freevar]) - { - let tcx = rcx.fcx.ccx.tcx; - debug!("constrain_captured_variables({}, {})", - region_bound.repr(tcx), expr.repr(tcx)); - for freevar in freevars { - debug!("constrain_captured_variables: freevar.def={:?}", freevar.def); - - // Identify the variable being closed over and its node-id. - let def = freevar.def; - let var_node_id = { - let def_id = def.def_id(); - assert!(def_id.krate == ast::LOCAL_CRATE); - def_id.node - }; - let upvar_id = ty::UpvarId { var_id: var_node_id, - closure_expr_id: expr.id }; - - match rcx.fcx.inh.upvar_capture_map.borrow()[upvar_id] { - ty::UpvarCapture::ByValue => { } - ty::UpvarCapture::ByRef(upvar_borrow) => { - rcx.fcx.mk_subr(infer::FreeVariable(freevar.span, var_node_id), - region_bound, upvar_borrow.region); - - // Guarantee that the closure does not outlive the variable itself. - let enclosing_region = region_of_def(rcx.fcx, def); - debug!("constrain_captured_variables: enclosing_region = {}", - enclosing_region.repr(tcx)); - rcx.fcx.mk_subr(infer::FreeVariable(freevar.span, var_node_id), - region_bound, enclosing_region); - } - } - } - } } fn constrain_callee(rcx: &mut Rcx, @@ -1538,6 +1409,9 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, let o1 = infer::ReferenceOutlivesReferent(ty, origin.span()); generic_must_outlive(rcx, o1, r_a, generic_b); } + implicator::Implication::RegionSubClosure(_, r_a, def_id, substs) => { + closure_must_outlive(rcx, origin.clone(), r_a, def_id, substs); + } implicator::Implication::Predicate(def_id, predicate) => { let cause = traits::ObligationCause::new(origin.span(), rcx.body_id, @@ -1549,6 +1423,23 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, } } +fn closure_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, + origin: infer::SubregionOrigin<'tcx>, + region: ty::Region, + def_id: ast::DefId, + substs: &'tcx Substs<'tcx>) { + debug!("closure_must_outlive(region={}, def_id={}, substs={})", + region.repr(rcx.tcx()), def_id.repr(rcx.tcx()), substs.repr(rcx.tcx())); + + let upvars = rcx.fcx.closure_upvars(def_id, substs).unwrap(); + for upvar in upvars { + let var_id = upvar.def.def_id().local_id(); + type_must_outlive( + rcx, infer::FreeVariable(origin.span(), var_id), + upvar.ty, region); + } +} + fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, origin: infer::SubregionOrigin<'tcx>, region: ty::Region, diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 1913b55f1d8e6..58b67d31ab580 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -397,7 +397,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { match self_type.ty.sty { ty::ty_enum(type_def_id, _) | ty::ty_struct(type_def_id, _) | - ty::ty_closure(type_def_id, _, _) => { + ty::ty_closure(type_def_id, _) => { tcx.destructor_for_type .borrow_mut() .insert(type_def_id, method_def_id.def_id()); diff --git a/src/test/compile-fail/issue-4335.rs b/src/test/compile-fail/issue-4335.rs index d0da51373d926..85298e4c6e096 100644 --- a/src/test/compile-fail/issue-4335.rs +++ b/src/test/compile-fail/issue-4335.rs @@ -14,7 +14,9 @@ fn id(t: T) -> T { t } fn f<'r, T>(v: &'r T) -> Box T + 'r> { - id(box || *v) //~ ERROR cannot infer + id(box || *v) + //~^ ERROR `v` does not live long enough + //~| ERROR cannot move out of borrowed content } fn main() { diff --git a/src/test/compile-fail/regions-proc-bound-capture.rs b/src/test/compile-fail/regions-proc-bound-capture.rs index 7ea4d1c7507af..cc33d11241757 100644 --- a/src/test/compile-fail/regions-proc-bound-capture.rs +++ b/src/test/compile-fail/regions-proc-bound-capture.rs @@ -18,7 +18,7 @@ fn borrowed_proc<'a>(x: &'a isize) -> Box(isize) + 'a> { fn static_proc(x: &isize) -> Box(isize) + 'static> { // This is illegal, because the region bound on `proc` is 'static. - box move|| { *x } //~ ERROR cannot infer + box move|| { *x } //~ ERROR captured variable `x` does not outlive the enclosing closure } fn main() { } diff --git a/src/test/compile-fail/regions-steal-closure.rs b/src/test/compile-fail/regions-steal-closure.rs index 97b51fdb32508..c9b378d1df26d 100644 --- a/src/test/compile-fail/regions-steal-closure.rs +++ b/src/test/compile-fail/regions-steal-closure.rs @@ -20,9 +20,9 @@ fn box_it<'r>(x: Box) -> closure_box<'r> { } fn main() { - let cl_box = { + let mut cl_box = { let mut i = 3; - box_it(box || i += 1) //~ ERROR cannot infer + box_it(box || i += 1) //~ ERROR `i` does not live long enough }; cl_box.cl.call_mut(()); } diff --git a/src/test/compile-fail/send-is-not-static-ensures-scoping.rs b/src/test/compile-fail/send-is-not-static-ensures-scoping.rs index abbcd7e45904f..fe03ca8353d29 100755 --- a/src/test/compile-fail/send-is-not-static-ensures-scoping.rs +++ b/src/test/compile-fail/send-is-not-static-ensures-scoping.rs @@ -13,9 +13,10 @@ use std::thread; fn main() { let bad = { let x = 1; - let y = &x; + let y = &x; //~ ERROR `x` does not live long enough - thread::scoped(|| { //~ ERROR cannot infer an appropriate lifetime + thread::scoped(|| { + //~^ ERROR `y` does not live long enough let _z = y; }) }; diff --git a/src/test/compile-fail/unboxed-closure-region.rs b/src/test/compile-fail/unboxed-closure-region.rs index 59c8495371852..5f4bf0d33be67 100644 --- a/src/test/compile-fail/unboxed-closure-region.rs +++ b/src/test/compile-fail/unboxed-closure-region.rs @@ -15,6 +15,6 @@ fn main() { let _f = { let x = 0_usize; - || x //~ ERROR cannot infer an appropriate lifetime due to conflicting requirements + || x //~ ERROR `x` does not live long enough }; }