diff --git a/src/libcollections/bitv.rs b/src/libcollections/bitv.rs index 6326f83b497..13180cdfa5b 100644 --- a/src/libcollections/bitv.rs +++ b/src/libcollections/bitv.rs @@ -632,7 +632,7 @@ impl<'a> RandomAccessIterator for Bits<'a> { } #[inline] - fn idx(&self, index: uint) -> Option { + fn idx(&mut self, index: uint) -> Option { if index >= self.indexable() { None } else { diff --git a/src/libcollections/ringbuf.rs b/src/libcollections/ringbuf.rs index 19dc2d2ae58..9204a9ca400 100644 --- a/src/libcollections/ringbuf.rs +++ b/src/libcollections/ringbuf.rs @@ -272,7 +272,7 @@ impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> { fn indexable(&self) -> uint { self.rindex - self.index } #[inline] - fn idx(&self, j: uint) -> Option<&'a T> { + fn idx(&mut self, j: uint) -> Option<&'a T> { if j >= self.indexable() { None } else { diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs index 46ee996608e..77c94d01508 100644 --- a/src/libnum/bigint.rs +++ b/src/libnum/bigint.rs @@ -672,7 +672,7 @@ impl ToStrRadix for BigUint { s.push_str("0".repeat(l - ss.len())); s.push_str(ss); } - s.as_slice().trim_left_chars(&'0').to_owned() + s.as_slice().trim_left_chars('0').to_owned() } } } diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs index b8f20b5e439..888a8f6bd8d 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -47,7 +47,7 @@ pub fn strip_items(krate: ast::Crate, ctxt.fold_crate(krate) } -fn filter_view_item<'r>(cx: &Context, view_item: &'r ast::ViewItem) +fn filter_view_item<'r>(cx: &mut Context, view_item: &'r ast::ViewItem) -> Option<&'r ast::ViewItem> { if view_item_in_cfg(cx, view_item) { Some(view_item) @@ -72,7 +72,7 @@ fn fold_mod(cx: &mut Context, m: &ast::Mod) -> ast::Mod { } } -fn filter_foreign_item(cx: &Context, item: @ast::ForeignItem) +fn filter_foreign_item(cx: &mut Context, item: @ast::ForeignItem) -> Option<@ast::ForeignItem> { if foreign_item_in_cfg(cx, item) { Some(item) @@ -144,7 +144,7 @@ fn fold_item_underscore(cx: &mut Context, item: &ast::Item_) -> ast::Item_ { fold::noop_fold_item_underscore(&item, cx) } -fn fold_struct(cx: &Context, def: &ast::StructDef) -> @ast::StructDef { +fn fold_struct(cx: &mut Context, def: &ast::StructDef) -> @ast::StructDef { let mut fields = def.fields.iter().map(|c| c.clone()).filter(|m| { (cx.in_cfg)(m.node.attrs.as_slice()) }); @@ -156,7 +156,7 @@ fn fold_struct(cx: &Context, def: &ast::StructDef) -> @ast::StructDef { } } -fn retain_stmt(cx: &Context, stmt: @ast::Stmt) -> bool { +fn retain_stmt(cx: &mut Context, stmt: @ast::Stmt) -> bool { match stmt.node { ast::StmtDecl(decl, _) => { match decl.node { @@ -189,23 +189,23 @@ fn fold_block(cx: &mut Context, b: ast::P) -> ast::P { }) } -fn item_in_cfg(cx: &Context, item: &ast::Item) -> bool { +fn item_in_cfg(cx: &mut Context, item: &ast::Item) -> bool { return (cx.in_cfg)(item.attrs.as_slice()); } -fn foreign_item_in_cfg(cx: &Context, item: &ast::ForeignItem) -> bool { +fn foreign_item_in_cfg(cx: &mut Context, item: &ast::ForeignItem) -> bool { return (cx.in_cfg)(item.attrs.as_slice()); } -fn view_item_in_cfg(cx: &Context, item: &ast::ViewItem) -> bool { +fn view_item_in_cfg(cx: &mut Context, item: &ast::ViewItem) -> bool { return (cx.in_cfg)(item.attrs.as_slice()); } -fn method_in_cfg(cx: &Context, meth: &ast::Method) -> bool { +fn method_in_cfg(cx: &mut Context, meth: &ast::Method) -> bool { return (cx.in_cfg)(meth.attrs.as_slice()); } -fn trait_method_in_cfg(cx: &Context, meth: &ast::TraitMethod) -> bool { +fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitMethod) -> bool { match *meth { ast::Required(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()), ast::Provided(meth) => (cx.in_cfg)(meth.attrs.as_slice()) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index d5ee1b15ae2..884fa70dc28 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -84,7 +84,7 @@ pub struct EncodeContext<'a> { pub non_inlineable_statics: &'a RefCell, pub link_meta: &'a LinkMeta, pub cstore: &'a cstore::CStore, - pub encode_inlined_item: EncodeInlinedItem<'a>, + pub encode_inlined_item: RefCell>, pub type_abbrevs: tyencode::abbrev_map, } @@ -765,8 +765,8 @@ fn encode_info_for_method(ecx: &EncodeContext, if num_params > 0u || is_default_impl || should_inline(ast_method.attrs.as_slice()) { - (ecx.encode_inlined_item)( - ecx, ebml_w, IIMethodRef(local_def(parent_id), false, ast_method)); + encode_inlined_item(ecx, ebml_w, + IIMethodRef(local_def(parent_id), false, ast_method)); } else { encode_symbol(ecx, ebml_w, m.def_id.node); } @@ -775,6 +775,14 @@ fn encode_info_for_method(ecx: &EncodeContext, ebml_w.end_tag(); } +fn encode_inlined_item(ecx: &EncodeContext, + ebml_w: &mut Encoder, + ii: InlinedItemRef) { + let mut eii = ecx.encode_inlined_item.borrow_mut(); + let eii: &mut EncodeInlinedItem = &mut *eii; + (*eii)(ecx, ebml_w, ii) +} + fn style_fn_family(s: FnStyle) -> char { match s { UnsafeFn => 'u', @@ -880,7 +888,7 @@ fn encode_info_for_item(ecx: &EncodeContext, let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id); if inlineable { - (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item)); + encode_inlined_item(ecx, ebml_w, IIItemRef(item)); } encode_visibility(ebml_w, vis); ebml_w.end_tag(); @@ -896,7 +904,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_path(ebml_w, path); encode_attributes(ebml_w, item.attrs.as_slice()); if tps_len > 0u || should_inline(item.attrs.as_slice()) { - (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item)); + encode_inlined_item(ecx, ebml_w, IIItemRef(item)); } else { encode_symbol(ecx, ebml_w, item.id); } @@ -954,7 +962,7 @@ fn encode_info_for_item(ecx: &EncodeContext, for v in (*enum_definition).variants.iter() { encode_variant_id(ebml_w, local_def(v.node.id)); } - (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item)); + encode_inlined_item(ecx, ebml_w, IIItemRef(item)); encode_path(ebml_w, path); // Encode inherent implementations for this enumeration. @@ -1002,7 +1010,7 @@ fn encode_info_for_item(ecx: &EncodeContext, needs to know*/ encode_struct_fields(ebml_w, fields.as_slice(), def_id); - (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item)); + encode_inlined_item(ecx, ebml_w, IIItemRef(item)); // Encode inherent implementations for this structure. encode_inherent_implementations(ecx, ebml_w, def_id); @@ -1175,8 +1183,8 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_bounds_and_type(ebml_w, ecx, &tpt); } encode_method_sort(ebml_w, 'p'); - (ecx.encode_inlined_item)( - ecx, ebml_w, IIMethodRef(def_id, true, m)); + encode_inlined_item(ecx, ebml_w, + IIMethodRef(def_id, true, m)); } } @@ -1212,7 +1220,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext, &lookup_item_type(ecx.tcx,local_def(nitem.id))); encode_name(ebml_w, nitem.ident.name); if abi == abi::RustIntrinsic { - (ecx.encode_inlined_item)(ecx, ebml_w, IIForeignRef(nitem)); + encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem)); } else { encode_symbol(ecx, ebml_w, nitem.id); } @@ -1544,12 +1552,12 @@ fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) { } } -struct MacroDefVisitor<'a, 'b> { - ecx: &'a EncodeContext<'a>, - ebml_w: &'a mut Encoder<'b> +struct MacroDefVisitor<'a, 'b, 'c> { + ecx: &'a EncodeContext<'b>, + ebml_w: &'a mut Encoder<'c> } -impl<'a, 'b> Visitor<()> for MacroDefVisitor<'a, 'b> { +impl<'a, 'b, 'c> Visitor<()> for MacroDefVisitor<'a, 'b, 'c> { fn visit_item(&mut self, item: &Item, _: ()) { match item.node { ItemMac(..) => { @@ -1565,9 +1573,9 @@ impl<'a, 'b> Visitor<()> for MacroDefVisitor<'a, 'b> { } } -fn encode_macro_defs(ecx: &EncodeContext, - krate: &Crate, - ebml_w: &mut Encoder) { +fn encode_macro_defs<'a>(ecx: &'a EncodeContext, + krate: &Crate, + ebml_w: &'a mut Encoder) { ebml_w.start_tag(tag_exported_macros); { let mut visitor = MacroDefVisitor { @@ -1579,12 +1587,12 @@ fn encode_macro_defs(ecx: &EncodeContext, ebml_w.end_tag(); } -struct ImplVisitor<'a,'b> { - ecx: &'a EncodeContext<'a>, - ebml_w: &'a mut Encoder<'b>, +struct ImplVisitor<'a,'b,'c> { + ecx: &'a EncodeContext<'b>, + ebml_w: &'a mut Encoder<'c>, } -impl<'a,'b> Visitor<()> for ImplVisitor<'a,'b> { +impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> { fn visit_item(&mut self, item: &Item, _: ()) { match item.node { ItemImpl(_, Some(ref trait_ref), _, _) => { @@ -1617,9 +1625,9 @@ impl<'a,'b> Visitor<()> for ImplVisitor<'a,'b> { /// * Destructors (implementations of the Drop trait). /// /// * Implementations of traits not defined in this crate. -fn encode_impls(ecx: &EncodeContext, - krate: &Crate, - ebml_w: &mut Encoder) { +fn encode_impls<'a>(ecx: &'a EncodeContext, + krate: &Crate, + ebml_w: &'a mut Encoder) { ebml_w.start_tag(tag_impls); { @@ -1744,7 +1752,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) non_inlineable_statics: non_inlineable_statics, link_meta: link_meta, cstore: cstore, - encode_inlined_item: encode_inlined_item, + encode_inlined_item: RefCell::new(encode_inlined_item), type_abbrevs: RefCell::new(HashMap::new()), }; diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index 9b3dce6147b..5e0b249ce3f 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -92,9 +92,9 @@ impl<'a> FileSearch<'a> { match fs::readdir(lib_search_path) { Ok(files) => { let mut rslt = FileDoesntMatch; - let is_rlib = |p: & &Path| { + fn is_rlib(p: & &Path) -> bool { p.extension_str() == Some("rlib") - }; + } // Reading metadata out of rlibs is faster, and if we find both // an rlib and a dylib we only read one of the files of // metadata, so in the name of speed, bring all rlib files to diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index e09507f5d5f..d0f47966832 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -327,7 +327,7 @@ impl<'a> CheckLoanCtxt<'a> { self.bccx.loan_path_to_str(&*old_loan.loan_path)) } - AddrOf | AutoRef | RefBinding => { + AddrOf | AutoRef | RefBinding | ClosureInvocation => { format!("previous borrow of `{}` occurs here", self.bccx.loan_path_to_str(&*old_loan.loan_path)) } diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index 7f748dffd70..8bb95b798d0 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -292,6 +292,26 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt, visit::walk_expr(this, ex, ()); } + ast::ExprCall(f, _) => { + let expr_ty = ty::expr_ty_adjusted(tcx, f); + match ty::get(expr_ty).sty { + ty::ty_closure(~ty::ClosureTy { + store: ty::RegionTraitStore(..), .. + }) => { + let scope_r = ty::ReScope(ex.id); + let base_cmt = this.bccx.cat_expr(f); + this.guarantee_valid_kind(f.id, + f.span, + base_cmt, + ty::UniqueImmBorrow, + scope_r, + ClosureInvocation); + } + _ => {} + } + visit::walk_expr(this, ex, ()); + } + _ => { visit::walk_expr(this, ex, ()); } diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 06491d36b02..3de64f15191 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -202,6 +202,7 @@ pub enum LoanCause { AddrOf, AutoRef, RefBinding, + ClosureInvocation, } #[deriving(Eq, TotalEq, Hash)] @@ -629,6 +630,10 @@ impl<'a> BorrowckCtxt<'a> { AddrOf | RefBinding | AutoRef => { format!("cannot borrow {} as mutable", descr) } + ClosureInvocation => { + self.tcx.sess.span_bug(err.span, + "err_mutbl with a closure invocation"); + } } } err_out_of_root_scope(..) => { @@ -677,6 +682,10 @@ impl<'a> BorrowckCtxt<'a> { BorrowViolation(RefBinding) => { "cannot borrow data mutably" } + + BorrowViolation(ClosureInvocation) => { + "closure invocation" + } }; match cause { diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index d1cc7d7bc40..05a225d8953 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -1164,7 +1164,7 @@ fn check_item_non_camel_case_types(cx: &Context, it: &ast::Item) { fn is_camel_case(ident: ast::Ident) -> bool { let ident = token::get_ident(ident); assert!(!ident.get().is_empty()); - let ident = ident.get().trim_chars(&'_'); + let ident = ident.get().trim_chars('_'); // start with a non-lowercase letter rather than non-uppercase // ones (some scripts don't have a concept of upper/lowercase) diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index eeccd1ca334..4e2d8cf585f 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -1104,34 +1104,34 @@ impl<'a> SanePrivacyVisitor<'a> { /// control over anything so this forbids any mention of any visibility fn check_all_inherited(&self, item: &ast::Item) { let tcx = self.tcx; - let check_inherited = |sp: Span, vis: ast::Visibility| { + fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) { if vis != ast::Inherited { tcx.sess.span_err(sp, "visibility has no effect inside functions"); } - }; + } let check_struct = |def: &@ast::StructDef| { for f in def.fields.iter() { match f.node.kind { - ast::NamedField(_, p) => check_inherited(f.span, p), + ast::NamedField(_, p) => check_inherited(tcx, f.span, p), ast::UnnamedField(..) => {} } } }; - check_inherited(item.span, item.vis); + check_inherited(tcx, item.span, item.vis); match item.node { ast::ItemImpl(_, _, _, ref methods) => { for m in methods.iter() { - check_inherited(m.span, m.vis); + check_inherited(tcx, m.span, m.vis); } } ast::ItemForeignMod(ref fm) => { for i in fm.items.iter() { - check_inherited(i.span, i.vis); + check_inherited(tcx, i.span, i.vis); } } ast::ItemEnum(ref def, _) => { for v in def.variants.iter() { - check_inherited(v.span, v.node.vis); + check_inherited(tcx, v.span, v.node.vis); match v.node.kind { ast::StructVariantKind(ref s) => check_struct(s), @@ -1146,7 +1146,8 @@ impl<'a> SanePrivacyVisitor<'a> { for m in methods.iter() { match *m { ast::Required(..) => {} - ast::Provided(ref m) => check_inherited(m.span, m.vis), + ast::Provided(ref m) => check_inherited(tcx, m.span, + m.vis), } } } diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 94cbd3a3a75..b59da8910af 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -751,7 +751,15 @@ fn constrain_callee(rcx: &mut Rcx, ty::ty_bare_fn(..) => { } ty::ty_closure(ref closure_ty) => { let region = match closure_ty.store { - ty::RegionTraitStore(r, _) => r, + ty::RegionTraitStore(r, _) => { + // While we're here, link the closure's region with a unique + // immutable borrow (gathered later in borrowck) + let mc = mc::MemCategorizationContext { typer: &*rcx }; + let expr_cmt = ignore_err!(mc.cat_expr(callee_expr)); + link_region(mc.typer, callee_expr.span, call_region, + ty::UniqueImmBorrow, expr_cmt); + r + } ty::UniqTraitStore => ty::ReStatic }; rcx.fcx.mk_subr(true, infer::InvokeClosure(callee_expr.span), @@ -874,7 +882,8 @@ fn constrain_autoderefs(rcx: &mut Rcx, { let mc = mc::MemCategorizationContext { typer: &*rcx }; let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i)); - link_region(mc.typer, deref_expr.span, r, m, self_cmt); + link_region(mc.typer, deref_expr.span, r, + ty::BorrowKind::from_mutbl(m), self_cmt); } // Specialized version of constrain_call. @@ -1092,7 +1101,8 @@ fn link_pattern(mc: mc::MemCategorizationContext<&Rcx>, match mc.cat_slice_pattern(sub_cmt, slice_pat) { Ok((slice_cmt, slice_mutbl, slice_r)) => { link_region(mc.typer, sub_pat.span, slice_r, - slice_mutbl, slice_cmt); + ty::BorrowKind::from_mutbl(slice_mutbl), + slice_cmt); } Err(()) => {} } @@ -1118,17 +1128,20 @@ fn link_autoref(rcx: &Rcx, match *autoref { ty::AutoPtr(r, m) => { - link_region(mc.typer, expr.span, r, m, expr_cmt); + link_region(mc.typer, expr.span, r, + ty::BorrowKind::from_mutbl(m), expr_cmt); } ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => { let cmt_index = mc.cat_index(expr, expr_cmt, autoderefs+1); - link_region(mc.typer, expr.span, r, m, cmt_index); + link_region(mc.typer, expr.span, r, + ty::BorrowKind::from_mutbl(m), cmt_index); } ty::AutoBorrowObj(r, m) => { let cmt_deref = mc.cat_deref_obj(expr, expr_cmt); - link_region(mc.typer, expr.span, r, m, cmt_deref); + link_region(mc.typer, expr.span, r, + ty::BorrowKind::from_mutbl(m), cmt_deref); } ty::AutoUnsafe(_) => {} @@ -1150,7 +1163,7 @@ fn link_by_ref(rcx: &Rcx, let mc = mc::MemCategorizationContext { typer: rcx }; let expr_cmt = ignore_err!(mc.cat_expr(expr)); let region_min = ty::ReScope(callee_scope); - link_region(mc.typer, expr.span, region_min, ast::MutImmutable, expr_cmt); + link_region(mc.typer, expr.span, region_min, ty::ImmBorrow, expr_cmt); } fn link_region_from_node_type(rcx: &Rcx, @@ -1169,18 +1182,19 @@ fn link_region_from_node_type(rcx: &Rcx, let tcx = rcx.fcx.ccx.tcx; debug!("rptr_ty={}", ty_to_str(tcx, rptr_ty)); let r = ty::ty_region(tcx, span, rptr_ty); - link_region(rcx, span, r, mutbl, cmt_borrowed); + link_region(rcx, span, r, ty::BorrowKind::from_mutbl(mutbl), + cmt_borrowed); } } fn link_region(rcx: &Rcx, span: Span, region_min: ty::Region, - mutbl: ast::Mutability, + kind: ty::BorrowKind, cmt_borrowed: mc::cmt) { /*! * Informs the inference engine that a borrow of `cmt` - * must have mutability `mutbl` and lifetime `region_min`. + * must have the borrow kind `kind` and lifetime `region_min`. * If `cmt` is a deref of a region pointer with * lifetime `r_borrowed`, this will add the constraint that * `region_min <= r_borrowed`. @@ -1190,9 +1204,9 @@ fn link_region(rcx: &Rcx, // for the lifetime `region_min` for the borrow to be valid: let mut cmt_borrowed = cmt_borrowed; loop { - debug!("link_region(region_min={}, mutbl={}, cmt_borrowed={})", + debug!("link_region(region_min={}, kind={}, cmt_borrowed={})", region_min.repr(rcx.tcx()), - mutbl.repr(rcx.tcx()), + kind.repr(rcx.tcx()), cmt_borrowed.repr(rcx.tcx())); match cmt_borrowed.cat.clone() { mc::cat_deref(base, _, mc::BorrowedPtr(_, r_borrowed)) => { @@ -1214,7 +1228,7 @@ fn link_region(rcx: &Rcx, adjust_upvar_borrow_kind_for_loan( *upvar_id, upvar_borrow, - mutbl); + kind); infer::ReborrowUpvar(span, *upvar_id) } None => { @@ -1236,7 +1250,7 @@ fn link_region(rcx: &Rcx, r_borrowed.repr(rcx.tcx())); rcx.fcx.mk_subr(true, cause, region_min, r_borrowed); - if mutbl == ast::MutMutable { + if kind != ty::ImmBorrow { // If this is a mutable borrow, then the thing // being borrowed will have to be unique. // In user code, this means it must be an `&mut` @@ -1428,12 +1442,11 @@ fn link_upvar_borrow_kind_for_nested_closures(rcx: &mut Rcx, fn adjust_upvar_borrow_kind_for_loan(upvar_id: ty::UpvarId, upvar_borrow: &mut ty::UpvarBorrow, - mutbl: ast::Mutability) { + kind: ty::BorrowKind) { debug!("adjust_upvar_borrow_kind_for_loan: upvar_id={:?} kind={:?} -> {:?}", - upvar_id, upvar_borrow.kind, mutbl); + upvar_id, upvar_borrow.kind, kind); - adjust_upvar_borrow_kind(upvar_id, upvar_borrow, - ty::BorrowKind::from_mutbl(mutbl)) + adjust_upvar_borrow_kind(upvar_id, upvar_borrow, kind) } fn adjust_upvar_borrow_kind(upvar_id: ty::UpvarId, diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index f61b282767f..7621a7ec4cd 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -107,9 +107,9 @@ impl<'a> Parser<'a> { } // Return result of first successful parser - fn read_or(&mut self, parsers: &[|&mut Parser| -> Option]) + fn read_or(&mut self, parsers: &mut [|&mut Parser| -> Option]) -> Option { - for pf in parsers.iter() { + for pf in parsers.mut_iter() { match self.read_atomically(|p: &mut Parser| (*pf)(p)) { Some(r) => return Some(r), None => {} @@ -305,7 +305,7 @@ impl<'a> Parser<'a> { fn read_ip_addr(&mut self) -> Option { let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr(); let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr(); - self.read_or([ipv4_addr, ipv6_addr]) + self.read_or(&mut [ipv4_addr, ipv6_addr]) } fn read_socket_addr(&mut self) -> Option { @@ -318,7 +318,7 @@ impl<'a> Parser<'a> { p.read_seq_3::(open_br, ip_addr, clos_br) .map(|t| match t { (_, ip, _) => ip }) }; - p.read_or([ipv4_p, ipv6_p]) + p.read_or(&mut [ipv4_p, ipv6_p]) }; let colon = |p: &mut Parser| p.read_given_char(':'); let port = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16); diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index 7a04303268b..d895331752f 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -703,7 +703,7 @@ pub trait RandomAccessIterator: Iterator { fn indexable(&self) -> uint; /// Return an element at an index - fn idx(&self, index: uint) -> Option; + fn idx(&mut self, index: uint) -> Option; } /// An iterator that knows its exact length @@ -771,8 +771,9 @@ impl + RandomAccessIterator> RandomAccessIterato #[inline] fn indexable(&self) -> uint { self.iter.indexable() } #[inline] - fn idx(&self, index: uint) -> Option { - self.iter.idx(self.indexable() - index - 1) + fn idx(&mut self, index: uint) -> Option { + let amt = self.indexable(); + self.iter.idx(amt - index - 1) } } @@ -1071,7 +1072,7 @@ impl> RandomAccessIterator for Cycle } #[inline] - fn idx(&self, index: uint) -> Option { + fn idx(&mut self, index: uint) -> Option { let liter = self.iter.indexable(); let lorig = self.orig.indexable(); if lorig == 0 { @@ -1143,7 +1144,7 @@ for Chain { } #[inline] - fn idx(&self, index: uint) -> Option { + fn idx(&mut self, index: uint) -> Option { let len = self.a.indexable(); if index < len { self.a.idx(index) @@ -1221,7 +1222,7 @@ RandomAccessIterator<(A, B)> for Zip { } #[inline] - fn idx(&self, index: uint) -> Option<(A, B)> { + fn idx(&mut self, index: uint) -> Option<(A, B)> { match self.a.idx(index) { None => None, Some(x) => match self.b.idx(index) { @@ -1240,7 +1241,7 @@ pub struct Map<'a, A, B, T> { impl<'a, A, B, T> Map<'a, A, B, T> { #[inline] - fn do_map(&self, elt: Option) -> Option { + fn do_map(&mut self, elt: Option) -> Option { match elt { Some(a) => Some((self.f)(a)), _ => None @@ -1276,8 +1277,9 @@ impl<'a, A, B, T: RandomAccessIterator> RandomAccessIterator for Map<'a, A } #[inline] - fn idx(&self, index: uint) -> Option { - self.do_map(self.iter.idx(index)) + fn idx(&mut self, index: uint) -> Option { + let elt = self.iter.idx(index); + self.do_map(elt) } } @@ -1415,7 +1417,7 @@ impl> RandomAccessIterator<(uint, A)> for Enumerat } #[inline] - fn idx(&self, index: uint) -> Option<(uint, A)> { + fn idx(&mut self, index: uint) -> Option<(uint, A)> { match self.iter.idx(index) { Some(a) => Some((self.count + index, a)), _ => None, @@ -1600,7 +1602,7 @@ impl> RandomAccessIterator for Skip { } #[inline] - fn idx(&self, index: uint) -> Option { + fn idx(&mut self, index: uint) -> Option { if index >= self.indexable() { None } else { @@ -1649,7 +1651,7 @@ impl> RandomAccessIterator for Take { } #[inline] - fn idx(&self, index: uint) -> Option { + fn idx(&mut self, index: uint) -> Option { if index >= self.n { None } else { @@ -1799,7 +1801,7 @@ impl> RandomAccessIterator for Fuse { } #[inline] - fn idx(&self, index: uint) -> Option { + fn idx(&mut self, index: uint) -> Option { self.iter.idx(index) } } @@ -1822,7 +1824,7 @@ pub struct Inspect<'a, A, T> { impl<'a, A, T> Inspect<'a, A, T> { #[inline] - fn do_inspect(&self, elt: Option) -> Option { + fn do_inspect(&mut self, elt: Option) -> Option { match elt { Some(ref a) => (self.f)(a), None => () @@ -1862,8 +1864,9 @@ for Inspect<'a, A, T> { } #[inline] - fn idx(&self, index: uint) -> Option { - self.do_inspect(self.iter.idx(index)) + fn idx(&mut self, index: uint) -> Option { + let element = self.iter.idx(index); + self.do_inspect(element) } } @@ -2164,7 +2167,7 @@ impl RandomAccessIterator for Repeat { #[inline] fn indexable(&self) -> uint { uint::MAX } #[inline] - fn idx(&self, _: uint) -> Option { Some(self.element.clone()) } + fn idx(&mut self, _: uint) -> Option { Some(self.element.clone()) } } /// Functions for lexicographical ordering of sequences. @@ -2907,7 +2910,7 @@ mod tests { let xs = [1, 2, 3, 4, 5]; // test .map and .inspect that don't implement Clone - let it = xs.iter().inspect(|_| {}); + let mut it = xs.iter().inspect(|_| {}); assert_eq!(xs.len(), it.indexable()); for (i, elt) in xs.iter().enumerate() { assert_eq!(Some(elt), it.idx(i)); @@ -2919,7 +2922,7 @@ mod tests { fn test_random_access_map() { let xs = [1, 2, 3, 4, 5]; - let it = xs.iter().map(|x| *x); + let mut it = xs.iter().map(|x| *x); assert_eq!(xs.len(), it.indexable()); for (i, elt) in xs.iter().enumerate() { assert_eq!(Some(*elt), it.idx(i)); diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 557e2043381..efbb1abacfa 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -873,9 +873,9 @@ mod tests { assert_eq!(v, None); // test that it does not take more elements than it needs - let functions = [|| Some(()), || None, || fail!()]; + let mut functions = [|| Some(()), || None, || fail!()]; - let v: Option<~[()]> = collect(functions.iter().map(|f| (*f)())); + let v: Option<~[()]> = collect(functions.mut_iter().map(|f| (*f)())); assert_eq!(v, None); } diff --git a/src/libstd/result.rs b/src/libstd/result.rs index 7080da266f6..058548eb151 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -695,9 +695,9 @@ mod tests { assert_eq!(v, Err(2)); // test that it does not take more elements than it needs - let functions = [|| Ok(()), || Err(1), || fail!()]; + let mut functions = [|| Ok(()), || Err(1), || fail!()]; - let v: Result<~[()], int> = collect(functions.iter().map(|f| (*f)())); + let v: Result<~[()], int> = collect(functions.mut_iter().map(|f| (*f)())); assert_eq!(v, Err(1)); } @@ -715,9 +715,9 @@ mod tests { Err(2)); // test that it does not take more elements than it needs - let functions = [|| Ok(()), || Err(1), || fail!()]; + let mut functions = [|| Ok(()), || Err(1), || fail!()]; - assert_eq!(fold_(functions.iter() + assert_eq!(fold_(functions.mut_iter() .map(|f| (*f)())), Err(1)); } diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index f75b5315207..2dab0e975da 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -109,7 +109,7 @@ impl Task { /// This function is *not* meant to be abused as a "try/catch" block. This /// is meant to be used at the absolute boundaries of a task's lifetime, and /// only for that purpose. - pub fn run(~self, f: ||) -> ~Task { + pub fn run(~self, mut f: ||) -> ~Task { // Need to put ourselves into TLS, but also need access to the unwinder. // Unsafely get a handle to the task so we can continue to use it after // putting it in tls (so we can invoke the unwinder). diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index 620baabeef5..929c47b05b9 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -212,8 +212,7 @@ impl<'a, T> Iterator<&'a [T]> for RevSplits<'a, T> { return Some(self.v); } - let pred = &mut self.pred; - match self.v.iter().rposition(|x| (*pred)(x)) { + match self.v.iter().rposition(|x| (self.pred)(x)) { None => { self.finished = true; Some(self.v) @@ -489,7 +488,7 @@ impl<'a, T> RandomAccessIterator<&'a [T]> for Chunks<'a, T> { } #[inline] - fn idx(&self, index: uint) -> Option<&'a [T]> { + fn idx(&mut self, index: uint) -> Option<&'a [T]> { if index < self.indexable() { let lo = index * self.size; let mut hi = lo + self.size; @@ -2101,7 +2100,7 @@ impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> { } #[inline] - fn idx(&self, index: uint) -> Option<&'a T> { + fn idx(&mut self, index: uint) -> Option<&'a T> { unsafe { if index < self.indexable() { transmute(self.ptr.offset(index as int)) @@ -2138,7 +2137,8 @@ impl<'a, T> Iterator<&'a mut [T]> for MutSplits<'a, T> { fn next(&mut self) -> Option<&'a mut [T]> { if self.finished { return None; } - match self.v.iter().position(|x| (self.pred)(x)) { + let pred = &mut self.pred; + match self.v.iter().position(|x| (*pred)(x)) { None => { self.finished = true; let tmp = mem::replace(&mut self.v, &mut []); @@ -2173,7 +2173,8 @@ impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T> { fn next_back(&mut self) -> Option<&'a mut [T]> { if self.finished { return None; } - match self.v.iter().rposition(|x| (self.pred)(x)) { + let pred = &mut self.pred; + match self.v.iter().rposition(|x| (*pred)(x)) { None => { self.finished = true; let tmp = mem::replace(&mut self.v, &mut []); @@ -3346,7 +3347,7 @@ mod tests { assert_eq!(v.chunks(6).collect::<~[&[int]]>(), ~[&[1i,2,3,4,5]]); assert_eq!(v.chunks(2).rev().collect::<~[&[int]]>(), ~[&[5i], &[3,4], &[1,2]]); - let it = v.chunks(2); + let mut it = v.chunks(2); assert_eq!(it.indexable(), 3); assert_eq!(it.idx(0).unwrap(), &[1,2]); assert_eq!(it.idx(1).unwrap(), &[3,4]); diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 9d91545bc12..99f1c66e702 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -217,7 +217,7 @@ impl<'a, S: Str> StrVector for Vec { /// Something that can be used to compare against a character pub trait CharEq { /// Determine if the splitter should split at the given character - fn matches(&self, char) -> bool; + fn matches(&mut self, char) -> bool; /// Indicate if this is only concerned about ASCII characters, /// which can allow for a faster implementation. fn only_ascii(&self) -> bool; @@ -225,7 +225,7 @@ pub trait CharEq { impl CharEq for char { #[inline] - fn matches(&self, c: char) -> bool { *self == c } + fn matches(&mut self, c: char) -> bool { *self == c } #[inline] fn only_ascii(&self) -> bool { (*self as uint) < 128 } @@ -233,7 +233,7 @@ impl CharEq for char { impl<'a> CharEq for |char|: 'a -> bool { #[inline] - fn matches(&self, c: char) -> bool { (*self)(c) } + fn matches(&mut self, c: char) -> bool { (*self)(c) } #[inline] fn only_ascii(&self) -> bool { false } @@ -241,16 +241,16 @@ impl<'a> CharEq for |char|: 'a -> bool { impl CharEq for extern "Rust" fn(char) -> bool { #[inline] - fn matches(&self, c: char) -> bool { (*self)(c) } + fn matches(&mut self, c: char) -> bool { (*self)(c) } #[inline] fn only_ascii(&self) -> bool { false } } -impl<'a, C: CharEq> CharEq for &'a [C] { +impl<'a> CharEq for &'a [char] { #[inline] - fn matches(&self, c: char) -> bool { - self.iter().any(|m| m.matches(c)) + fn matches(&mut self, c: char) -> bool { + self.iter().any(|&mut m| m.matches(c)) } #[inline] @@ -1981,11 +1981,11 @@ pub trait StrSlice<'a> { /// # Example /// /// ```rust - /// assert_eq!("11foo1bar11".trim_chars(&'1'), "foo1bar") - /// assert_eq!("12foo1bar12".trim_chars(& &['1', '2']), "foo1bar") - /// assert_eq!("123foo1bar123".trim_chars(&|c: char| c.is_digit()), "foo1bar") + /// assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar") + /// assert_eq!("12foo1bar12".trim_chars(&['1', '2']), "foo1bar") + /// assert_eq!("123foo1bar123".trim_chars(|c: char| c.is_digit()), "foo1bar") /// ``` - fn trim_chars(&self, to_trim: &C) -> &'a str; + fn trim_chars(&self, to_trim: C) -> &'a str; /// Returns a string with leading `chars_to_trim` removed. /// @@ -1996,11 +1996,11 @@ pub trait StrSlice<'a> { /// # Example /// /// ```rust - /// assert_eq!("11foo1bar11".trim_left_chars(&'1'), "foo1bar11") - /// assert_eq!("12foo1bar12".trim_left_chars(& &['1', '2']), "foo1bar12") - /// assert_eq!("123foo1bar123".trim_left_chars(&|c: char| c.is_digit()), "foo1bar123") + /// assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11") + /// assert_eq!("12foo1bar12".trim_left_chars(&['1', '2']), "foo1bar12") + /// assert_eq!("123foo1bar123".trim_left_chars(|c: char| c.is_digit()), "foo1bar123") /// ``` - fn trim_left_chars(&self, to_trim: &C) -> &'a str; + fn trim_left_chars(&self, to_trim: C) -> &'a str; /// Returns a string with trailing `chars_to_trim` removed. /// @@ -2011,11 +2011,11 @@ pub trait StrSlice<'a> { /// # Example /// /// ```rust - /// assert_eq!("11foo1bar11".trim_right_chars(&'1'), "11foo1bar") - /// assert_eq!("12foo1bar12".trim_right_chars(& &['1', '2']), "12foo1bar") - /// assert_eq!("123foo1bar123".trim_right_chars(&|c: char| c.is_digit()), "123foo1bar") + /// assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar") + /// assert_eq!("12foo1bar12".trim_right_chars(&['1', '2']), "12foo1bar") + /// assert_eq!("123foo1bar123".trim_right_chars(|c: char| c.is_digit()), "123foo1bar") /// ``` - fn trim_right_chars(&self, to_trim: &C) -> &'a str; + fn trim_right_chars(&self, to_trim: C) -> &'a str; /// Replace all occurrences of one string with another. /// @@ -2491,21 +2491,31 @@ impl<'a> StrSlice<'a> for &'a str { #[inline] fn trim_left(&self) -> &'a str { - self.trim_left_chars(&char::is_whitespace) + self.trim_left_chars(char::is_whitespace) } #[inline] fn trim_right(&self) -> &'a str { - self.trim_right_chars(&char::is_whitespace) + self.trim_right_chars(char::is_whitespace) } #[inline] - fn trim_chars(&self, to_trim: &C) -> &'a str { - self.trim_left_chars(to_trim).trim_right_chars(to_trim) + fn trim_chars(&self, mut to_trim: C) -> &'a str { + let cur = match self.find(|c: char| !to_trim.matches(c)) { + None => "", + Some(i) => unsafe { raw::slice_bytes(*self, i, self.len()) } + }; + match cur.rfind(|c: char| !to_trim.matches(c)) { + None => "", + Some(i) => { + let right = cur.char_range_at(i).next; + unsafe { raw::slice_bytes(cur, 0, right) } + } + } } #[inline] - fn trim_left_chars(&self, to_trim: &C) -> &'a str { + fn trim_left_chars(&self, mut to_trim: C) -> &'a str { match self.find(|c: char| !to_trim.matches(c)) { None => "", Some(first) => unsafe { raw::slice_bytes(*self, first, self.len()) } @@ -2513,7 +2523,7 @@ impl<'a> StrSlice<'a> for &'a str { } #[inline] - fn trim_right_chars(&self, to_trim: &C) -> &'a str { + fn trim_right_chars(&self, mut to_trim: C) -> &'a str { match self.rfind(|c: char| !to_trim.matches(c)) { None => "", Some(last) => { @@ -2631,7 +2641,7 @@ impl<'a> StrSlice<'a> for &'a str { unsafe { cast::transmute(*self) } } - fn find(&self, search: C) -> Option { + fn find(&self, mut search: C) -> Option { if search.only_ascii() { self.bytes().position(|b| search.matches(b as char)) } else { @@ -2642,7 +2652,7 @@ impl<'a> StrSlice<'a> for &'a str { } } - fn rfind(&self, search: C) -> Option { + fn rfind(&self, mut search: C) -> Option { if search.only_ascii() { self.bytes().rposition(|b| search.matches(b as char)) } else { @@ -3160,40 +3170,40 @@ mod tests { #[test] fn test_trim_left_chars() { let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_left_chars(&v), " *** foo *** "); - assert_eq!(" *** foo *** ".trim_left_chars(& &['*', ' ']), "foo *** "); - assert_eq!(" *** *** ".trim_left_chars(& &['*', ' ']), ""); - assert_eq!("foo *** ".trim_left_chars(& &['*', ' ']), "foo *** "); + assert_eq!(" *** foo *** ".trim_left_chars(v), " *** foo *** "); + assert_eq!(" *** foo *** ".trim_left_chars(&['*', ' ']), "foo *** "); + assert_eq!(" *** *** ".trim_left_chars(&['*', ' ']), ""); + assert_eq!("foo *** ".trim_left_chars(&['*', ' ']), "foo *** "); - assert_eq!("11foo1bar11".trim_left_chars(&'1'), "foo1bar11"); - assert_eq!("12foo1bar12".trim_left_chars(& &['1', '2']), "foo1bar12"); - assert_eq!("123foo1bar123".trim_left_chars(&|c: char| c.is_digit()), "foo1bar123"); + assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11"); + assert_eq!("12foo1bar12".trim_left_chars(&['1', '2']), "foo1bar12"); + assert_eq!("123foo1bar123".trim_left_chars(|c: char| c.is_digit()), "foo1bar123"); } #[test] fn test_trim_right_chars() { let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_right_chars(&v), " *** foo *** "); - assert_eq!(" *** foo *** ".trim_right_chars(& &['*', ' ']), " *** foo"); - assert_eq!(" *** *** ".trim_right_chars(& &['*', ' ']), ""); - assert_eq!(" *** foo".trim_right_chars(& &['*', ' ']), " *** foo"); + assert_eq!(" *** foo *** ".trim_right_chars(v), " *** foo *** "); + assert_eq!(" *** foo *** ".trim_right_chars(&['*', ' ']), " *** foo"); + assert_eq!(" *** *** ".trim_right_chars(&['*', ' ']), ""); + assert_eq!(" *** foo".trim_right_chars(&['*', ' ']), " *** foo"); - assert_eq!("11foo1bar11".trim_right_chars(&'1'), "11foo1bar"); - assert_eq!("12foo1bar12".trim_right_chars(& &['1', '2']), "12foo1bar"); - assert_eq!("123foo1bar123".trim_right_chars(&|c: char| c.is_digit()), "123foo1bar"); + assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar"); + assert_eq!("12foo1bar12".trim_right_chars(&['1', '2']), "12foo1bar"); + assert_eq!("123foo1bar123".trim_right_chars(|c: char| c.is_digit()), "123foo1bar"); } #[test] fn test_trim_chars() { let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_chars(&v), " *** foo *** "); - assert_eq!(" *** foo *** ".trim_chars(& &['*', ' ']), "foo"); - assert_eq!(" *** *** ".trim_chars(& &['*', ' ']), ""); - assert_eq!("foo".trim_chars(& &['*', ' ']), "foo"); + assert_eq!(" *** foo *** ".trim_chars(v), " *** foo *** "); + assert_eq!(" *** foo *** ".trim_chars(&['*', ' ']), "foo"); + assert_eq!(" *** *** ".trim_chars(&['*', ' ']), ""); + assert_eq!("foo".trim_chars(&['*', ' ']), "foo"); - assert_eq!("11foo1bar11".trim_chars(&'1'), "foo1bar"); - assert_eq!("12foo1bar12".trim_chars(& &['1', '2']), "foo1bar"); - assert_eq!("123foo1bar123".trim_chars(&|c: char| c.is_digit()), "foo1bar"); + assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar"); + assert_eq!("12foo1bar12".trim_chars(&['1', '2']), "foo1bar"); + assert_eq!("123foo1bar123".trim_chars(|c: char| c.is_digit()), "foo1bar"); } #[test] @@ -4123,7 +4133,7 @@ mod bench { fn split_unicode_not_ascii(b: &mut Bencher) { struct NotAscii(char); impl CharEq for NotAscii { - fn matches(&self, c: char) -> bool { + fn matches(&mut self, c: char) -> bool { let NotAscii(cc) = *self; cc == c } @@ -4148,7 +4158,7 @@ mod bench { struct NotAscii(char); impl CharEq for NotAscii { #[inline] - fn matches(&self, c: char) -> bool { + fn matches(&mut self, c: char) -> bool { let NotAscii(cc) = *self; cc == c } diff --git a/src/libstd/unstable/finally.rs b/src/libstd/unstable/finally.rs index c98ef880c10..3d00c0ac74a 100644 --- a/src/libstd/unstable/finally.rs +++ b/src/libstd/unstable/finally.rs @@ -35,19 +35,19 @@ use ops::Drop; #[cfg(test)] use task::failing; pub trait Finally { - fn finally(&self, dtor: ||) -> T; + fn finally(&mut self, dtor: ||) -> T; } impl<'a,T> Finally for ||: 'a -> T { - fn finally(&self, dtor: ||) -> T { - try_finally(&mut (), (), - |_, _| (*self)(), + fn finally(&mut self, dtor: ||) -> T { + try_finally(&mut (), self, + |_, f| (*f)(), |_| dtor()) } } impl Finally for fn() -> T { - fn finally(&self, dtor: ||) -> T { + fn finally(&mut self, dtor: ||) -> T { try_finally(&mut (), (), |_, _| (*self)(), |_| dtor()) @@ -145,7 +145,7 @@ fn test_fail() { #[test] fn test_retval() { - let closure: || -> int = || 10; + let mut closure: || -> int = || 10; let i = closure.finally(|| { }); assert_eq!(i, 10); } @@ -154,6 +154,6 @@ fn test_retval() { fn test_compact() { fn do_some_fallible_work() {} fn but_always_run_this_function() { } - do_some_fallible_work.finally( - but_always_run_this_function); + let mut f = do_some_fallible_work; + f.finally(but_always_run_this_function); } diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 367accb4b19..e0b493cd8d9 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -34,7 +34,9 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, ret_ty: Self, inline: true, const_nonmatching: false, - combine_substructure: |c, s, sub| cs_clone("Clone", c, s, sub) + combine_substructure: combine_substructure(|c, s, sub| { + cs_clone("Clone", c, s, sub) + }), } ) }; diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 975b8885de7..35b7e7c1a66 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -40,7 +40,9 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, ret_ty: Literal(Path::new(vec!("bool"))), inline: true, const_nonmatching: true, - combine_substructure: $f + combine_substructure: combine_substructure(|a, b, c| { + $f(a, b, c) + }) } } ); diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 5605c0b6107..afe2d3dae6a 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -30,7 +30,9 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, ret_ty: Literal(Path::new(vec!("bool"))), inline: true, const_nonmatching: false, - combine_substructure: |cx, span, substr| cs_op($op, $equal, cx, span, substr) + combine_substructure: combine_substructure(|cx, span, substr| { + cs_op($op, $equal, cx, span, substr) + }) } } ); diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index 33512b3df5e..d161f966850 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -48,7 +48,9 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, ret_ty: nil_ty(), inline: true, const_nonmatching: true, - combine_substructure: cs_total_eq_assert + combine_substructure: combine_substructure(|a, b, c| { + cs_total_eq_assert(a, b, c) + }) } ) }; diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index a584f8abe05..69c413890e9 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -37,7 +37,9 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt, ret_ty: Literal(Path::new(vec!("std", "cmp", "Ordering"))), inline: true, const_nonmatching: false, - combine_substructure: cs_cmp + combine_substructure: combine_substructure(|a, b, c| { + cs_cmp(a, b, c) + }), } ) }; diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 35a1eb0bb83..6d6cdc55d40 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -52,7 +52,9 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt, vec!(~Self, ~Literal(Path::new_local("__E"))), true)), inline: false, const_nonmatching: true, - combine_substructure: decodable_substructure, + combine_substructure: combine_substructure(|a, b, c| { + decodable_substructure(a, b, c) + }), }) }; diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index 94675f91e9d..633674eff5c 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -34,7 +34,9 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, ret_ty: Self, inline: true, const_nonmatching: false, - combine_substructure: default_substructure + combine_substructure: combine_substructure(|a, b, c| { + default_substructure(a, b, c) + }) }) }; trait_def.expand(cx, mitem, item, push) diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 806560f6826..acdef8c8645 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -123,7 +123,9 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt, true)), inline: false, const_nonmatching: true, - combine_substructure: encodable_substructure, + combine_substructure: combine_substructure(|a, b, c| { + encodable_substructure(a, b, c) + }), }) }; diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 914451fb402..673745b41e8 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -177,6 +177,8 @@ StaticEnum(, ~[(, , Unnamed(~[ { /// actual enum variants, i.e. can use _ => .. match. pub const_nonmatching: bool, - pub combine_substructure: CombineSubstructureFunc<'a>, + pub combine_substructure: RefCell>, } /// All the data about the data structure/method being derived upon. @@ -317,6 +319,11 @@ pub type EnumNonMatchFunc<'a> = &[@Expr]|: 'a -> @Expr; +pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>) + -> RefCell> { + RefCell::new(f) +} + impl<'a> TraitDef<'a> { pub fn expand(&self, @@ -509,8 +516,9 @@ impl<'a> MethodDef<'a> { nonself_args: nonself_args, fields: fields }; - (self.combine_substructure)(cx, trait_.span, - &substructure) + let mut f = self.combine_substructure.borrow_mut(); + let f: &mut CombineSubstructureFunc = &mut *f; + (*f)(cx, trait_.span, &substructure) } fn get_ret_ty(&self, diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index d22027d203f..9e160b0e35d 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -49,7 +49,9 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, ret_ty: nil_ty(), inline: true, const_nonmatching: false, - combine_substructure: hash_substructure + combine_substructure: combine_substructure(|a, b, c| { + hash_substructure(a, b, c) + }) } ) }; diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index 267a12fdff9..e42a3c67e34 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -41,7 +41,9 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, // liable to cause code-bloat inline: true, const_nonmatching: false, - combine_substructure: |c, s, sub| cs_from("i64", c, s, sub), + combine_substructure: combine_substructure(|c, s, sub| { + cs_from("i64", c, s, sub) + }), }, MethodDef { name: "from_u64", @@ -56,7 +58,9 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, // liable to cause code-bloat inline: true, const_nonmatching: false, - combine_substructure: |c, s, sub| cs_from("u64", c, s, sub), + combine_substructure: combine_substructure(|c, s, sub| { + cs_from("u64", c, s, sub) + }), }) }; diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index e81aa55d10d..09c3abf42b8 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -43,7 +43,9 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt, ret_ty: Self, inline: false, const_nonmatching: false, - combine_substructure: rand_substructure + combine_substructure: combine_substructure(|a, b, c| { + rand_substructure(a, b, c) + }) } ) }; diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index 067958e4bde..7098d0dd6ef 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -44,7 +44,9 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt, ret_ty: Literal(Path::new(vec!("std", "fmt", "Result"))), inline: false, const_nonmatching: false, - combine_substructure: show_substructure + combine_substructure: combine_substructure(|a, b, c| { + show_substructure(a, b, c) + }) } ) }; diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs index 10692bd7f93..0aeeabcaeab 100644 --- a/src/libsyntax/ext/deriving/zero.rs +++ b/src/libsyntax/ext/deriving/zero.rs @@ -34,7 +34,9 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt, ret_ty: Self, inline: true, const_nonmatching: false, - combine_substructure: zero_substructure + combine_substructure: combine_substructure(|a, b, c| { + zero_substructure(a, b, c) + }) }, MethodDef { name: "is_zero", @@ -44,13 +46,13 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt, ret_ty: Literal(Path::new(vec!("bool"))), inline: true, const_nonmatching: false, - combine_substructure: |cx, span, substr| { + combine_substructure: combine_substructure(|cx, span, substr| { cs_and(|cx, span, _, _| cx.span_bug(span, "Non-matching enum \ variant in \ deriving(Zero)"), cx, span, substr) - } + }) } ) }; diff --git a/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs b/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs new file mode 100644 index 00000000000..002ae5a7d28 --- /dev/null +++ b/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs @@ -0,0 +1,64 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Ensure that invoking a closure counts as a unique immutable borrow + + +type Fn<'a> = ||:'a; + +struct Test<'a> { + f: ||: 'a +} + +fn call(f: |Fn|) { + f(|| { + //~^ ERROR: closure requires unique access to `f` but it is already borrowed + f(|| {}) + }); +} + +fn test1() { + call(|a| { + a(); + }); +} + +fn test2(f: &||) { + (*f)(); //~ ERROR: closure invocation in a `&` reference +} + +fn test3(f: &mut ||) { + (*f)(); +} + +fn test4(f: &Test) { + (f.f)() //~ ERROR: closure invocation in a `&` reference +} + +fn test5(f: &mut Test) { + (f.f)() +} + +fn test6() { + let f = || {}; + (|| { + f(); + })(); +} + +fn test7() { + fn foo(_: |g: |int|, b: int|) {} + let f = |g: |int|, b: int| {}; + f(|a| { //~ ERROR: cannot borrow `f` as immutable because previous closure + foo(f); //~ ERROR: cannot move out of captured outer variable + }, 3); +} + +fn main() {} diff --git a/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs b/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs index e5fe1891cb8..6556d0a51f8 100644 --- a/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs +++ b/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs @@ -16,7 +16,7 @@ struct R<'a> { // This struct is needed to create the // otherwise infinite type of a fn that // accepts itself as argument: - c: |&R, bool|: 'a + c: |&mut R, bool|: 'a } fn innocent_looking_victim() { @@ -28,6 +28,7 @@ fn innocent_looking_victim() { match x { Some(ref msg) => { (f.c)(f, true); + //~^ ERROR: cannot borrow `*f` as mutable because println!("{:?}", msg); }, None => fail!("oops"), @@ -36,9 +37,9 @@ fn innocent_looking_victim() { }) } -fn conspirator(f: |&R, bool|) { - let r = R {c: f}; - f(&r, false) //~ ERROR use of moved value +fn conspirator(f: |&mut R, bool|) { + let mut r = R {c: f}; + f(&mut r, false) //~ ERROR use of moved value } fn main() { innocent_looking_victim() } diff --git a/src/test/run-pass/const-vec-of-fns.rs b/src/test/run-pass/const-vec-of-fns.rs index 1f5c1a556a9..202354b1326 100644 --- a/src/test/run-pass/const-vec-of-fns.rs +++ b/src/test/run-pass/const-vec-of-fns.rs @@ -18,13 +18,13 @@ fn f() { } static bare_fns: &'static [fn()] = &[f, f]; struct S<'a>(||:'a); -static mut closures: &'static [S<'static>] = &[S(f), S(f)]; +static mut closures: &'static mut [S<'static>] = &mut [S(f), S(f)]; pub fn main() { unsafe { for &bare_fn in bare_fns.iter() { bare_fn() } - for closure in closures.iter() { - let S(ref closure) = *closure; + for closure in closures.mut_iter() { + let S(ref mut closure) = *closure; (*closure)() } } diff --git a/src/test/run-pass/issue-6157.rs b/src/test/run-pass/issue-6157.rs index 5a78aed5826..4144c8227dc 100644 --- a/src/test/run-pass/issue-6157.rs +++ b/src/test/run-pass/issue-6157.rs @@ -8,23 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait OpInt<'a> { fn call<'a>(&'a self, int, int) -> int; } +pub trait OpInt<'a> { fn call<'a>(&'a mut self, int, int) -> int; } impl<'a> OpInt<'a> for |int, int|: 'a -> int { - fn call(&self, a:int, b:int) -> int { + fn call(&mut self, a:int, b:int) -> int { (*self)(a, b) } } -fn squarei<'a>(x: int, op: &'a OpInt) -> int { op.call(x, x) } +fn squarei<'a>(x: int, op: &'a mut OpInt) -> int { op.call(x, x) } fn muli(x:int, y:int) -> int { x * y } pub fn main() { - let f = |x,y| muli(x,y); + let mut f = |x,y| muli(x,y); { - let g = &f; - let h = g as &OpInt; + let g = &mut f; + let h = g as &mut OpInt; squarei(3, h); } }