diff --git a/src/doc/intro.md b/src/doc/intro.md index 07a90959deb..d145eaada2b 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -510,10 +510,10 @@ numbers[1] is 3 numbers[0] is 2 ``` -Each time, we can get a slithtly different output because the threads -are not quaranteed to run in any set order. If you get the same order -every time it is because each of these threads are very small and -complete too fast for their indeterminate behavior to surface. +Each time, we can get a slightly different output because the threads are not +guaranteed to run in any set order. If you get the same order every time it is +because each of these threads are very small and complete too fast for their +indeterminate behavior to surface. The important part here is that the Rust compiler was able to use ownership to give us assurance _at compile time_ that we weren't doing something incorrect diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md index a40374fe30f..4e7222269a8 100644 --- a/src/doc/trpl/guessing-game.md +++ b/src/doc/trpl/guessing-game.md @@ -422,11 +422,11 @@ In this case, we say `x` is a `u32` explicitly, so Rust is able to properly tell `random()` what to generate. In a similar fashion, both of these work: ```{rust,ignore} -let input_num = "5".parse::(); // input_num: Option -let input_num: Result = "5".parse(); // input_num: Result::Err> +let input_num_option = "5".parse::().ok(); // input_num: Option +let input_num_result: Result = "5".parse(); // input_num: Result::Err> ``` -Here we're converting the `Result` returned by `parse` to an `Option` by using +Above, we're converting the `Result` returned by `parse` to an `Option` by using the `ok` method as well. Anyway, with us now converting our input to a number, our code looks like this: @@ -470,14 +470,14 @@ Let's try it out! ```bash $ cargo build Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) -src/main.rs:22:15: 22:24 error: mismatched types: expected `u32` but found `core::option::Option` (expected u32 but found enum core::option::Option) -src/main.rs:22 match cmp(input_num, secret_number) { +src/main.rs:21:15: 21:24 error: mismatched types: expected `u32`, found `core::result::Result` (expected u32, found enum `core::result::Result`) [E0308] +src/main.rs:21 match cmp(input_num, secret_number) { ^~~~~~~~~ error: aborting due to previous error ``` -Oh yeah! Our `input_num` has the type `Option`, rather than `u32`. We -need to unwrap the Option. If you remember from before, `match` is a great way +Oh yeah! Our `input_num` has the type `Result>`, rather than `u32`. We +need to unwrap the Result. If you remember from before, `match` is a great way to do that. Try this code: ```{rust,no_run} @@ -500,7 +500,7 @@ fn main() { let input_num: Result = input.parse(); let num = match input_num { - Ok(num) => num, + Ok(n) => n, Err(_) => { println!("Please input a number!"); return; @@ -524,7 +524,7 @@ fn cmp(a: u32, b: u32) -> Ordering { } ``` -We use a `match` to either give us the `u32` inside of the `Option`, or else +We use a `match` to either give us the `u32` inside of the `Result`, or else print an error message and return. Let's give this a shot: ```bash diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index 98673af3c68..5a20ba4b49f 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -364,7 +364,7 @@ //! * `o` - precedes the argument with a "0o" //! * '0' - This is used to indicate for integer formats that the padding should //! both be done with a `0` character as well as be sign-aware. A format -//! like `{:08d}` would yield `00000001` for the integer `1`, while the +//! like `{:08}` would yield `00000001` for the integer `1`, while the //! same format would yield `-0000001` for the integer `-1`. Notice that //! the negative version has one fewer zero than the positive version. //! diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index baecfb7eb22..b33839f33e8 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 76a365259aa..ebb4153e32b 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 7584a2e44cc..063845c6c34 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 b782a655d89..be94a73df37 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 5cb034667cc..224a568c77f 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 c4446b87855..1f02f13a4a1 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 7db1138ac72..b4db3aba786 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 7d4febb38e6..b9a863f4fe4 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 d8c62780a78..470315c78f8 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 635ec09d339..aaba840825e 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 4bf47c3a75f..1b904aacc30 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 3336e7ee8bf..5b5eac45178 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 15b3c6d9d06..0eeb746022c 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 3ea14d3c589..2fb0488cd70 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 1f578ac0bdb..7a6960d3790 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 1d4bbd79d71..7fa26a7c128 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 d70a904b811..f3b7058336b 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_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index 9491c8377a6..1151b11d21f 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -313,8 +313,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ty::mk_nil(bcx.tcx())); let (_, variant_cx) = invoke(variant_cx, dtor_addr, &args[..], dtor_ty, DebugLoc::None); - variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope); - variant_cx + variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope) }) } diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 0ad15456df9..f9495af79c5 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 0b7c5b04aaa..0d4edc01a4c 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 f65e585d23e..f99ba894029 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 f24da78bc7d..fbf002b709e 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 1518a09e7dc..a3e98b0c4c6 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 1913b55f1d8..58b67d31ab5 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/libstd/thread.rs b/src/libstd/thread.rs index 5dd4be336ec..883c1bbbbe5 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -28,25 +28,25 @@ //! a thread will unwind the stack, running destructors and freeing //! owned resources. Thread panic is unrecoverable from within //! the panicking thread (i.e. there is no 'try/catch' in Rust), but -//! panic may optionally be detected from a different thread. If -//! the main thread panics the application will exit with a non-zero +//! the panic may optionally be detected from a different thread. If +//! the main thread panics, the application will exit with a non-zero //! exit code. //! //! When the main thread of a Rust program terminates, the entire program shuts //! down, even if other threads are still running. However, this module provides //! convenient facilities for automatically waiting for the termination of a -//! child thread (i.e., join), described below. +//! child thread (i.e., join). //! //! ## The `Thread` type //! -//! Already-running threads are represented via the `Thread` type, which you can +//! Threads are represented via the `Thread` type, which you can //! get in one of two ways: //! -//! * By spawning a new thread, e.g. using the `thread::spawn` constructor; +//! * By spawning a new thread, e.g. using the `thread::spawn` function. //! * By requesting the current thread, using the `thread::current` function. //! //! Threads can be named, and provide some built-in support for low-level -//! synchronization described below. +//! synchronization (described below). //! //! The `thread::current()` function is available even for threads not spawned //! by the APIs of this module. @@ -59,29 +59,27 @@ //! use std::thread; //! //! thread::spawn(move || { -//! println!("Hello, World!"); -//! // some computation here +//! // some work here //! }); //! ``` //! //! In this example, the spawned thread is "detached" from the current -//! thread, meaning that it can outlive the thread that spawned -//! it. (Note, however, that when the main thread terminates all -//! detached threads are terminated as well.) +//! thread. This means that it can outlive its parent (the thread that spawned +//! it), unless this parent is the main thread. //! //! ## Scoped threads //! //! Often a parent thread uses a child thread to perform some particular task, //! and at some point must wait for the child to complete before continuing. -//! For this scenario, use the `scoped` constructor: +//! For this scenario, use the `thread::scoped` function: //! //! ```rust //! use std::thread; //! //! let guard = thread::scoped(move || { -//! println!("Hello, World!"); -//! // some computation here +//! // some work here //! }); +//! //! // do some other work in the meantime //! let output = guard.join(); //! ``` @@ -92,11 +90,7 @@ //! terminates) when it is dropped. You can join the child thread in //! advance by calling the `join` method on the guard, which will also //! return the result produced by the thread. A handle to the thread -//! itself is available via the `thread` method on the join guard. -//! -//! (Note: eventually, the `scoped` constructor will allow the parent and child -//! threads to data that lives on the parent thread's stack, but some language -//! changes are needed before this is possible.) +//! itself is available via the `thread` method of the join guard. //! //! ## Configuring threads //! @@ -108,7 +102,7 @@ //! use std::thread; //! //! thread::Builder::new().name("child1".to_string()).spawn(move || { -//! println!("Hello, world!") +//! println!("Hello, world!"); //! }); //! ``` //! @@ -121,7 +115,7 @@ //! initially not present: //! //! * The `thread::park()` function blocks the current thread unless or until -//! the token is available for its thread handle, at which point It atomically +//! the token is available for its thread handle, at which point it atomically //! consumes the token. It may also return *spuriously*, without consuming the //! token. `thread::park_timeout()` does the same, but allows specifying a //! maximum time to block the thread for. @@ -143,7 +137,7 @@ //! * It avoids the need to allocate mutexes and condvars when building new //! synchronization primitives; the threads already provide basic blocking/signaling. //! -//! * It can be implemented highly efficiently on many platforms. +//! * It can be implemented very efficiently on many platforms. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index ffc136d5a1d..8043bd9bd70 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -173,6 +173,7 @@ pub static KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ ("plugin_registrar", Normal), ("cfg", Normal), + ("cfg_attr", Normal), ("main", Normal), ("start", Normal), ("test", Normal), diff --git a/src/test/compile-fail/issue-4335.rs b/src/test/compile-fail/issue-4335.rs index d0da51373d9..85298e4c6e0 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 7ea4d1c7507..cc33d112417 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 97b51fdb325..c9b378d1df2 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 abbcd7e4590..fe03ca8353d 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 59c84953718..5f4bf0d33be 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 }; }