diff --git a/src/libfourcc/lib.rs b/src/libfourcc/lib.rs index 50cdd6cedc23c..fe0b6bcfd0f0a 100644 --- a/src/libfourcc/lib.rs +++ b/src/libfourcc/lib.rs @@ -91,7 +91,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> let s = match expr.node { // expression is a literal - ast::ExprLit(lit) => match lit.node { + ast::ExprLit(ref lit) => match lit.node { // string literal ast::LitStr(ref s, _) => { if s.get().char_len() != 4 { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index cf0e7e161c1fc..10650b747bd78 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -348,8 +348,7 @@ pub fn phase_3_run_analysis_passes(sess: Session, time(time_passes, "effect checking", (), |_| middle::effect::check_crate(&ty_cx, krate)); - let middle::moves::MoveMaps {moves_map, moved_variables_set, - capture_map} = + let middle::moves::MoveMaps {moves_map, capture_map} = time(time_passes, "compute moves", (), |_| middle::moves::compute_moves(&ty_cx, krate)); @@ -359,14 +358,11 @@ pub fn phase_3_run_analysis_passes(sess: Session, time(time_passes, "liveness checking", (), |_| middle::liveness::check_crate(&ty_cx, &capture_map, krate)); - let root_map = - time(time_passes, "borrow checking", (), |_| - middle::borrowck::check_crate(&ty_cx, &moves_map, - &moved_variables_set, - &capture_map, krate)); + time(time_passes, "borrow checking", (), |_| + middle::borrowck::check_crate(&ty_cx, &moves_map, + &capture_map, krate)); drop(moves_map); - drop(moved_variables_set); time(time_passes, "kind checking", (), |_| kind::check_crate(&ty_cx, krate)); @@ -391,7 +387,6 @@ pub fn phase_3_run_analysis_passes(sess: Session, exported_items: exported_items, public_items: public_items, maps: astencode::Maps { - root_map: root_map, capture_map: RefCell::new(capture_map) }, reachable: reachable_map diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 08133a8b69e40..7f3757c478c02 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -54,7 +54,6 @@ use writer = serialize::ebml::writer; // Auxiliary maps of things to be encoded pub struct Maps { - pub root_map: middle::borrowck::root_map, pub capture_map: RefCell, } diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index a27fe5cec2252..4c17ddbb31f86 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -65,9 +65,6 @@ struct GuaranteeLifetimeContext<'a> { } impl<'a> GuaranteeLifetimeContext<'a> { - fn tcx(&self) -> &'a ty::ctxt { - self.bccx.tcx - } fn check(&self, cmt: &mc::cmt, discr_scope: Option) -> R { //! Main routine. Walks down `cmt` until we find the "guarantor". @@ -90,29 +87,10 @@ impl<'a> GuaranteeLifetimeContext<'a> { Ok(()) } - mc::cat_deref(ref base, derefs, mc::GcPtr) => { - let base_scope = self.scope(base); - - // L-Deref-Managed-Imm-User-Root - let omit_root = - self.bccx.is_subregion_of(self.loan_region, base_scope) && - self.is_rvalue_or_immutable(base) && - !self.is_moved(base); - - if !omit_root { - // L-Deref-Managed-Imm-Compiler-Root - // L-Deref-Managed-Mut-Compiler-Root - self.check_root(cmt, base, derefs, discr_scope) - } else { - debug!("omitting root, base={}, base_scope={:?}", - base.repr(self.tcx()), base_scope); - Ok(()) - } - } - mc::cat_downcast(ref base) | mc::cat_deref(ref base, _, mc::OwnedPtr) | // L-Deref-Send - mc::cat_interior(ref base, _) => { // L-Field + mc::cat_interior(ref base, _) | // L-Field + mc::cat_deref(ref base, _, mc::GcPtr) => { self.check(base, discr_scope) } @@ -174,74 +152,6 @@ impl<'a> GuaranteeLifetimeContext<'a> { } } - fn is_rvalue_or_immutable(&self, - cmt: &mc::cmt) -> bool { - //! We can omit the root on an `@T` value if the location - //! that holds the box is either (1) an rvalue, in which case - //! it is in a non-user-accessible temporary, or (2) an immutable - //! lvalue. - - cmt.mutbl.is_immutable() || match cmt.guarantor().cat { - mc::cat_rvalue(..) => true, - _ => false - } - } - - fn check_root(&self, - cmt_deref: &mc::cmt, - cmt_base: &mc::cmt, - derefs: uint, - discr_scope: Option) -> R { - debug!("check_root(cmt_deref={}, cmt_base={}, derefs={:?}, \ - discr_scope={:?})", - cmt_deref.repr(self.tcx()), - cmt_base.repr(self.tcx()), - derefs, - discr_scope); - - // Make sure that the loan does not exceed the maximum time - // that we can root the value, dynamically. - let root_region = ty::ReScope(self.root_scope_id); - if !self.bccx.is_subregion_of(self.loan_region, root_region) { - return Err(self.report_error( - err_out_of_root_scope(root_region, self.loan_region))); - } - - // Extract the scope id that indicates how long the rooting is required - let root_scope = match self.loan_region { - ty::ReScope(id) => id, - _ => { - // the check above should fail for anything is not ReScope - self.bccx.tcx.sess.span_bug( - cmt_base.span, - format!("cannot issue root for scope region: {:?}", - self.loan_region)); - } - }; - - // If inside of a match arm, expand the rooting to the entire - // match. See the detailed discussion in `check()` above. - let root_scope = match discr_scope { - None => root_scope, - Some(id) => { - if self.bccx.is_subscope_of(root_scope, id) { - id - } else { - root_scope - } - } - }; - - // Add a record of what is required - let rm_key = root_map_key {id: cmt_deref.id, derefs: derefs}; - let root_info = RootInfo {scope: root_scope}; - - self.bccx.root_map.borrow_mut().insert(rm_key, root_info); - - debug!("root_key: {:?} root_info: {:?}", rm_key, root_info); - Ok(()) - } - fn check_scope(&self, max_scope: ty::Region) -> R { //! Reports an error if `loan_region` is larger than `valid_scope` @@ -252,32 +162,6 @@ impl<'a> GuaranteeLifetimeContext<'a> { } } - fn is_moved(&self, cmt: &mc::cmt) -> bool { - //! True if `cmt` is something that is potentially moved - //! out of the current stack frame. - - match cmt.guarantor().cat { - mc::cat_local(id) | - mc::cat_arg(id) => { - self.bccx.moved_variables_set.contains(&id) - } - mc::cat_rvalue(..) | - mc::cat_static_item | - mc::cat_copied_upvar(..) | - mc::cat_deref(..) | - mc::cat_upvar(..) => { - false - } - ref r @ mc::cat_downcast(..) | - ref r @ mc::cat_interior(..) | - ref r @ mc::cat_discr(..) => { - self.tcx().sess.span_bug( - cmt.span, - format!("illegal guarantor category: {:?}", r)); - } - } - } - fn scope(&self, cmt: &mc::cmt) -> ty::Region { //! Returns the maximal region scope for the which the //! lvalue `cmt` is guaranteed to be valid without any diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index de4ce84fb0a59..4d0249a3011bd 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -101,12 +101,18 @@ impl<'a> RestrictionsContext<'a> { self.extend(result, cmt.mutbl, LpInterior(i), restrictions) } - mc::cat_deref(cmt_base, _, pk @ mc::OwnedPtr) => { + mc::cat_deref(cmt_base, _, pk @ mc::OwnedPtr) | + mc::cat_deref(cmt_base, _, pk @ mc::GcPtr) => { // R-Deref-Send-Pointer // // When we borrow the interior of an owned pointer, we // cannot permit the base to be mutated, because that // would cause the unique pointer to be freed. + // + // For a managed pointer, the rules are basically the + // same, because this could be the last ref. + // Eventually we should make these non-special and + // just rely on Deref implementation. let result = self.restrict( cmt_base, restrictions | RESTR_MUTATE); @@ -134,11 +140,6 @@ impl<'a> RestrictionsContext<'a> { Safe } - mc::cat_deref(_, _, mc::GcPtr) => { - // R-Deref-Imm-Managed - Safe - } - mc::cat_deref(cmt_base, _, pk @ mc::BorrowedPtr(ty::MutBorrow, lt)) => { // R-Deref-Mut-Borrowed if !self.bccx.is_subregion_of(self.loan_region, lt) { diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 06491d36b021b..1011a001aaf7d 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -21,11 +21,10 @@ use middle::dataflow::DataFlowOperator; use util::nodemap::{NodeMap, NodeSet}; use util::ppaux::{note_and_explain_region, Repr, UserString}; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::ops::{BitOr, BitAnd}; use std::rc::Rc; use std::strbuf::StrBuf; -use collections::HashMap; use syntax::ast; use syntax::ast_map; use syntax::ast_util; @@ -77,21 +76,39 @@ impl<'a> Visitor<()> for BorrowckCtxt<'a> { pub fn check_crate(tcx: &ty::ctxt, moves_map: &NodeSet, - moved_variables_set: &NodeSet, capture_map: &moves::CaptureMap, - krate: &ast::Crate) - -> root_map { + krate: &ast::Crate) { let mut bccx = BorrowckCtxt { tcx: tcx, moves_map: moves_map, - moved_variables_set: moved_variables_set, capture_map: capture_map, - root_map: RefCell::new(HashMap::new()) + stats: @BorrowStats { + loaned_paths_same: Cell::new(0), + loaned_paths_imm: Cell::new(0), + stable_paths: Cell::new(0), + guaranteed_paths: Cell::new(0), + } }; visit::walk_crate(&mut bccx, krate, ()); - return bccx.root_map.unwrap(); + if tcx.sess.borrowck_stats() { + println!("--- borrowck stats ---"); + println!("paths requiring guarantees: {}", + bccx.stats.guaranteed_paths.get()); + println!("paths requiring loans : {}", + make_stat(&bccx, bccx.stats.loaned_paths_same.get())); + println!("paths requiring imm loans : {}", + make_stat(&bccx, bccx.stats.loaned_paths_imm.get())); + println!("stable paths : {}", + make_stat(&bccx, bccx.stats.stable_paths.get())); + } + + fn make_stat(bccx: &BorrowckCtxt, stat: uint) -> ~str { + let stat_f = stat as f64; + let total = bccx.stats.guaranteed_paths.get() as f64; + format!("{} ({:.0f}%)", stat , stat_f * 100.0 / total) + } } fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) { @@ -148,28 +165,17 @@ fn borrowck_fn(this: &mut BorrowckCtxt, pub struct BorrowckCtxt<'a> { tcx: &'a ty::ctxt, moves_map: &'a NodeSet, - moved_variables_set: &'a NodeSet, capture_map: &'a moves::CaptureMap, - root_map: RefCell, + + // Statistics: + stats: @BorrowStats } -// The keys to the root map combine the `id` of the deref expression -// with the number of types that it is *autodereferenced*. So, for -// example, imagine I have a variable `x: @@@T` and an expression -// `(*x).f`. This will have 3 derefs, one explicit and then two -// autoderefs. These are the relevant `root_map_key` values that could -// appear: -// -// {id:*x, derefs:0} --> roots `x` (type: @@@T, due to explicit deref) -// {id:*x, derefs:1} --> roots `*x` (type: @@T, due to autoderef #1) -// {id:*x, derefs:2} --> roots `**x` (type: @T, due to autoderef #2) -// -// Note that there is no entry with derefs:3---the type of that expression -// is T, which is not a box. -#[deriving(Eq, TotalEq, Hash)] -pub struct root_map_key { - pub id: ast::NodeId, - pub derefs: uint +pub struct BorrowStats { + loaned_paths_same: Cell, + loaned_paths_imm: Cell, + stable_paths: Cell, + guaranteed_paths: Cell, } pub type BckResult = Result; @@ -317,31 +323,6 @@ impl Repr for RestrictionSet { } } -/////////////////////////////////////////////////////////////////////////// -// Rooting of managed boxes -// -// When we borrow the interior of a managed box, it is sometimes -// necessary to *root* the box, meaning to stash a copy of the box -// somewhere that the garbage collector will find it. This ensures -// that the box is not collected for the lifetime of the borrow. -// -// As part of this rooting, we sometimes also freeze the box at -// runtime, meaning that we dynamically detect when the box is -// borrowed in incompatible ways. -// -// Both of these actions are driven through the `root_map`, which maps -// from a node to the dynamic rooting action that should be taken when -// that node executes. The node is identified through a -// `root_map_key`, which pairs a node-id and a deref count---the -// problem is that sometimes the box that needs to be rooted is only -// uncovered after a certain number of auto-derefs. - -pub struct RootInfo { - pub scope: ast::NodeId, -} - -pub type root_map = HashMap; - /////////////////////////////////////////////////////////////////////////// // Errors @@ -349,7 +330,6 @@ pub type root_map = HashMap; #[deriving(Eq)] pub enum bckerr_code { err_mutbl, - err_out_of_root_scope(ty::Region, ty::Region), // superscope, subscope err_out_of_scope(ty::Region, ty::Region), // superscope, subscope err_borrowed_pointer_too_short( ty::Region, ty::Region, RestrictionSet), // loan, ptr @@ -631,9 +611,6 @@ impl<'a> BorrowckCtxt<'a> { } } } - err_out_of_root_scope(..) => { - format!("cannot root managed value long enough") - } err_out_of_scope(..) => { let msg = match opt_loan_path(&err.cmt) { None => format!("borrowed value"), @@ -709,19 +686,6 @@ impl<'a> BorrowckCtxt<'a> { match code { err_mutbl(..) => { } - err_out_of_root_scope(super_scope, sub_scope) => { - note_and_explain_region( - self.tcx, - "managed value would have to be rooted for ", - sub_scope, - "..."); - note_and_explain_region( - self.tcx, - "...but can only be rooted for ", - super_scope, - ""); - } - err_out_of_scope(super_scope, sub_scope) => { note_and_explain_region( self.tcx, diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index cd3ab100e55c2..6a2262aeaef9f 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -24,7 +24,6 @@ use syntax::visit; use syntax::{ast, ast_map, ast_util}; use std::cell::RefCell; -use collections::HashMap; use std::rc::Rc; // @@ -127,7 +126,6 @@ pub fn lookup_variant_by_id(tcx: &ty::ctxt, None => {} } let maps = astencode::Maps { - root_map: HashMap::new(), capture_map: RefCell::new(NodeMap::new()) }; let e = match csearch::maybe_get_item_ast(tcx, enum_def, @@ -166,7 +164,6 @@ pub fn lookup_const_by_id(tcx: &ty::ctxt, def_id: ast::DefId) None => {} } let maps = astencode::Maps { - root_map: HashMap::new(), capture_map: RefCell::new(NodeMap::new()) }; let e = match csearch::maybe_get_item_ast(tcx, def_id, diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index 53d3dec671301..1e44e1ab7f967 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -101,11 +101,6 @@ borrow checker and trans, for example, only care about the outermost expressions that are moved. It is more efficient therefore just to store those entries. -Sometimes though we want to know the variables that are moved (in -particular in the borrow checker). For these cases, the set -`moved_variables_set` just collects the ids of variables that are -moved. - Finally, the `capture_map` maps from the node_id of a closure expression to an array of `CaptureVar` structs detailing which variables are captured and how (by ref, by copy, by move). @@ -170,7 +165,6 @@ pub struct MoveMaps { * pub Note: The `moves_map` stores expression ids that are moves, * whereas this set stores the ids of the variables that are * moved at some point */ - pub moved_variables_set: NodeSet, pub capture_map: CaptureMap } @@ -206,7 +200,6 @@ pub fn compute_moves(tcx: &ty::ctxt, krate: &Crate) -> MoveMaps { tcx: tcx, move_maps: MoveMaps { moves_map: NodeSet::new(), - moved_variables_set: NodeSet::new(), capture_map: NodeMap::new() } }; @@ -326,19 +319,6 @@ impl<'a> VisitContext<'a> { debug!("comp_mode = {:?}", comp_mode); match expr.node { - ExprPath(..) => { - match comp_mode { - Move => { - let def = self.tcx.def_map.borrow().get_copy(&expr.id); - let r = moved_variable_node_id_from_def(def); - for &id in r.iter() { - self.move_maps.moved_variables_set.insert(id); - } - } - Read => {} - } - } - ExprUnary(UnDeref, base) => { // *base if !self.use_overloaded_operator(expr, base, []) { // Moving out of *base moves out of base. @@ -475,6 +455,7 @@ impl<'a> VisitContext<'a> { self.use_expr(base, Read); } + ExprPath(..) | ExprInlineAsm(..) | ExprBreak(..) | ExprAgain(..) | diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 55f8b3d1fd227..ddda95c06cb25 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -198,7 +198,6 @@ use back::abi; use driver::session::FullDebugInfo; use lib::llvm::{llvm, ValueRef, BasicBlockRef}; use middle::const_eval; -use middle::borrowck::root_map_key; use middle::lang_items::{UniqStrEqFnLangItem, StrEqFnLangItem}; use middle::pat_util::*; use middle::resolve::DefMap; @@ -1156,14 +1155,6 @@ fn collect_record_or_struct_fields<'a>( } } -fn pats_require_rooting(bcx: &Block, m: &[Match], col: uint) -> bool { - m.iter().any(|br| { - let pat_id = br.pats.get(col).id; - let key = root_map_key {id: pat_id, derefs: 0u }; - bcx.ccx().maps.root_map.contains_key(&key) - }) -} - // Macro for deciding whether any of the remaining matches fit a given kind of // pattern. Note that, because the macro is well-typed, either ALL of the // matches should fit that sort of pattern or NONE (however, some of the @@ -1551,10 +1542,6 @@ fn compile_submatch_continue<'a, 'b>( } } - // If we are not matching against an `@T`, we should not be - // required to root any values. - assert!(!pats_require_rooting(bcx, m, col)); - match collect_record_or_struct_fields(bcx, m, col) { Some(ref rec_fields) => { let pat_ty = node_id_type(bcx, pat_id); diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 27a97af610899..0c7d36e0dbedf 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -640,7 +640,7 @@ pub fn create_function_debug_context(cx: &CrateContext, } } } - ast_map::NodeMethod(method) => { + ast_map::NodeMethod(ref method) => { (method.ident, method.decl, &method.generics, @@ -667,9 +667,9 @@ pub fn create_function_debug_context(cx: &CrateContext, "create_function_debug_context: expected an expr_fn_block here") } } - ast_map::NodeTraitMethod(trait_method) => { - match *trait_method { - ast::Provided(method) => { + ast_map::NodeTraitMethod(ref trait_method) => { + match **trait_method { + ast::Provided(ref method) => { (method.ident, method.decl, &method.generics, diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 3c1dfedcac616..9bb0375bf44d2 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -59,7 +59,6 @@ use middle::trans::meth; use middle::trans::inline; use middle::trans::tvec; use middle::trans::type_of; -use middle::trans::write_guard; use middle::ty::struct_fields; use middle::ty::{AutoBorrowObj, AutoDerefRef, AutoAddEnv, AutoObject, AutoUnsafe}; use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef}; @@ -1676,8 +1675,6 @@ fn deref_once<'a>(bcx: &'a Block<'a>, derefs: uint) -> DatumBlock<'a, Expr> { let ccx = bcx.ccx(); - let bcx = write_guard::root_and_write_guard(&datum, bcx, expr.span, - expr.id, derefs); debug!("deref_once(expr={}, datum={}, derefs={})", expr.repr(bcx.tcx()), diff --git a/src/librustc/middle/trans/mod.rs b/src/librustc/middle/trans/mod.rs index 7ac491edfeb2a..f07adb1ed87c0 100644 --- a/src/librustc/middle/trans/mod.rs +++ b/src/librustc/middle/trans/mod.rs @@ -15,7 +15,6 @@ pub mod monomorphize; pub mod controlflow; pub mod glue; pub mod datum; -pub mod write_guard; pub mod callee; pub mod expr; pub mod common; diff --git a/src/librustc/middle/trans/write_guard.rs b/src/librustc/middle/trans/write_guard.rs deleted file mode 100644 index 8f114827bfd27..0000000000000 --- a/src/librustc/middle/trans/write_guard.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2012 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. - -//! Logic relating to rooting and write guards for managed values. -//! This code is primarily for use by datum; -//! it exists in its own module both to keep datum.rs bite-sized -//! and for each in debugging (e.g., so you can use -//! `RUST_LOG=rustc::middle::trans::write_guard`). - - -use middle::borrowck::{RootInfo, root_map_key}; -use middle::trans::cleanup; -use middle::trans::common::*; -use middle::trans::datum::*; -use syntax::codemap::Span; -use syntax::ast; - -pub fn root_and_write_guard<'a, K:KindOps>(datum: &Datum, - bcx: &'a Block<'a>, - span: Span, - expr_id: ast::NodeId, - derefs: uint) -> &'a Block<'a> { - let key = root_map_key { id: expr_id, derefs: derefs }; - debug!("write_guard::root_and_write_guard(key={:?})", key); - - // root the autoderef'd value, if necessary: - // - // (Note: root'd values are always boxes) - let ccx = bcx.ccx(); - match ccx.maps.root_map.find(&key) { - None => bcx, - Some(&root_info) => root(datum, bcx, span, key, root_info) - } -} - -fn root<'a, K:KindOps>(datum: &Datum, - bcx: &'a Block<'a>, - _span: Span, - root_key: root_map_key, - root_info: RootInfo) -> &'a Block<'a> { - //! In some cases, borrowck will decide that an @T value must be - //! rooted for the program to be safe. In that case, we will call - //! this function, which will stash a copy away until we exit the - //! scope `scope_id`. - - debug!("write_guard::root(root_key={:?}, root_info={:?}, datum={:?})", - root_key, root_info, datum.to_str(bcx.ccx())); - - // Root the datum. Note that we must zero this value, - // because sometimes we root on one path but not another. - // See e.g. #4904. - lvalue_scratch_datum( - bcx, datum.ty, "__write_guard", true, - cleanup::AstScope(root_info.scope), (), - |(), bcx, llval| datum.shallow_copy_and_take(bcx, llval)).bcx -} diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 94cbd3a3a7507..558d8298a1aee 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -1263,12 +1263,12 @@ fn link_region(rcx: &Rcx, } mc::cat_discr(cmt_base, _) | mc::cat_downcast(cmt_base) | + mc::cat_deref(cmt_base, _, mc::GcPtr(..)) | mc::cat_deref(cmt_base, _, mc::OwnedPtr) | mc::cat_interior(cmt_base, _) => { // Interior or owned data requires its base to be valid cmt_borrowed = cmt_base; } - mc::cat_deref(_, _, mc::GcPtr(..)) | mc::cat_deref(_, _, mc::UnsafePtr(..)) | mc::cat_static_item | mc::cat_copied_upvar(..) | diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index bb9c6a87babda..df102b8aadf3f 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -674,14 +674,16 @@ impl<'a> ErrorReporting for InferCtxt<'a> { let parent = self.tcx.map.get_parent(scope_id); let parent_node = self.tcx.map.find(parent); let node_inner = match parent_node { - Some(node) => match node { - ast_map::NodeItem(item) => match item.node { - ast::ItemFn(ref fn_decl, ref pur, _, ref gen, _) => { - Some((fn_decl, gen, *pur, item.ident, None, item.span)) - }, - _ => None - }, - ast_map::NodeMethod(m) => { + Some(ref node) => match *node { + ast_map::NodeItem(ref item) => { + match item.node { + ast::ItemFn(ref fn_decl, ref pur, _, ref gen, _) => { + Some((fn_decl, gen, *pur, item.ident, None, item.span)) + }, + _ => None + } + } + ast_map::NodeMethod(ref m) => { Some((&m.decl, &m.generics, m.fn_style, m.ident, Some(m.explicit_self.node), m.span)) }, diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index 3f1c99cffd640..be05ccdfcb412 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -684,7 +684,8 @@ impl Clean for ast::Ty { fn clean(&self) -> Type { use syntax::ast::*; debug!("cleaning type `{:?}`", self); - let codemap = local_data::get(super::ctxtkey, |x| *x.unwrap()).sess().codemap(); + let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap()); + let codemap = ctxt.sess().codemap(); debug!("span corresponds to `{}`", codemap.span_to_str(self.span)); match self.node { TyNil => Unit, @@ -866,7 +867,8 @@ pub struct Span { impl Clean for syntax::codemap::Span { fn clean(&self) -> Span { - let cm = local_data::get(super::ctxtkey, |x| *x.unwrap()).sess().codemap(); + let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap()); + let cm = ctxt.sess().codemap(); let filename = cm.span_to_filename(*self); let lo = cm.lookup_char_pos(self.lo); let hi = cm.lookup_char_pos(self.hi); @@ -1193,7 +1195,8 @@ trait ToSource { impl ToSource for syntax::codemap::Span { fn to_src(&self) -> ~str { debug!("converting span {:?} to snippet", self.clean()); - let cm = local_data::get(super::ctxtkey, |x| x.unwrap().clone()).sess().codemap().clone(); + let ctxt = local_data::get(super::ctxtkey, |x| x.unwrap().clone()); + let cm = ctxt.sess().codemap().clone(); let sn = match cm.span_to_snippet(*self) { Some(x) => x, None => "".to_owned() diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 7a167237d3e5d..865c3be4ae646 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -363,14 +363,15 @@ impl Map { } pub fn with_attrs(&self, id: NodeId, f: |Option<&[Attribute]>| -> T) -> T { - let attrs = match self.get(id) { - NodeItem(i) => Some(i.attrs.as_slice()), - NodeForeignItem(fi) => Some(fi.attrs.as_slice()), - NodeTraitMethod(tm) => match *tm { + let node = self.get(id); + let attrs = match node { + NodeItem(ref i) => Some(i.attrs.as_slice()), + NodeForeignItem(ref fi) => Some(fi.attrs.as_slice()), + NodeTraitMethod(ref tm) => match **tm { Required(ref type_m) => Some(type_m.attrs.as_slice()), - Provided(m) => Some(m.attrs.as_slice()) + Provided(ref m) => Some(m.attrs.as_slice()) }, - NodeMethod(m) => Some(m.attrs.as_slice()), + NodeMethod(ref m) => Some(m.attrs.as_slice()), NodeVariant(ref v) => Some(v.node.attrs.as_slice()), // unit/tuple structs take the attributes straight from // the struct definition. diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 914451fb4024e..852dd0ed02a37 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -814,26 +814,25 @@ impl<'a> MethodDef<'a> { "no self match on an enum in \ generic `deriving`"); } + + // `ref` inside let matches is buggy. Causes havoc wih rusc. + // let (variant_index, ref self_vec) = matches_so_far[0]; + let (variant, self_vec) = match matches_so_far.get(0) { + &(_, v, ref s) => (v, s) + }; + // we currently have a vec of vecs, where each // subvec is the fields of one of the arguments, // but if the variants all match, we want this as // vec of tuples, where each tuple represents a // field. - let substructure; - // most arms don't have matching variants, so do a // quick check to see if they match (even though // this means iterating twice) instead of being // optimistic and doing a pile of allocations etc. - match matching { + let substructure = match matching { Some(variant_index) => { - // `ref` inside let matches is buggy. Causes havoc wih rusc. - // let (variant_index, ref self_vec) = matches_so_far[0]; - let (variant, self_vec) = match matches_so_far.get(0) { - &(_, v, ref s) => (v, s) - }; - let mut enum_matching_fields = Vec::from_elem(self_vec.len(), Vec::new()); for triple in matches_so_far.tail().iter() { @@ -856,12 +855,12 @@ impl<'a> MethodDef<'a> { other: (*other).clone() } }).collect(); - substructure = EnumMatching(variant_index, variant, field_tuples); + EnumMatching(variant_index, variant, field_tuples) } None => { - substructure = EnumNonMatching(matches_so_far.as_slice()); + EnumNonMatching(matches_so_far.as_slice()) } - } + }; self.call_substructure_method(cx, trait_, type_ident, self_args, nonself_args, &substructure) diff --git a/src/test/compile-fail/borrowck-managed-pointer-deref-scope.rs b/src/test/compile-fail/borrowck-managed-pointer-deref-scope.rs new file mode 100644 index 0000000000000..4695360a688de --- /dev/null +++ b/src/test/compile-fail/borrowck-managed-pointer-deref-scope.rs @@ -0,0 +1,33 @@ +// 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. + +// Verify that managed pointers scope is treated like ownoed pointers. +// regresion test for #11586 + +#![feature(managed_boxes)] + +fn foo<'a>(x: &'a @int) -> &'a int { + match x { + &ref y => { + &**y // Do not expect an error here + } + } +} + +fn bar() { + let a = 3; + let mut y = &a; + if true { + let x = @3; + y = &*x; //~ ERROR `*x` does not live long enough + } +} + +fn main() {} diff --git a/src/test/run-pass/borrowck-preserve-box-in-field.rs b/src/test/compile-fail/borrowck-preserve-box-in-field.rs similarity index 87% rename from src/test/run-pass/borrowck-preserve-box-in-field.rs rename to src/test/compile-fail/borrowck-preserve-box-in-field.rs index f05b8c67d77e2..ff138451e93f2 100644 --- a/src/test/run-pass/borrowck-preserve-box-in-field.rs +++ b/src/test/compile-fail/borrowck-preserve-box-in-field.rs @@ -26,8 +26,10 @@ struct F { f: ~int } pub fn main() { let mut x = @F {f: ~3}; borrow(x.f, |b_x| { + //~^ ERROR cannot borrow `x` as mutable because `*x.f` is also borrowed as immutable assert_eq!(*b_x, 3); assert_eq!(&(*x.f) as *int, &(*b_x) as *int); + //~^ NOTE borrow occurs due to use of `x` in closure x = @F {f: ~4}; println!("&*b_x = {:p}", &(*b_x)); diff --git a/src/test/run-pass/borrowck-preserve-box-in-uniq.rs b/src/test/compile-fail/borrowck-preserve-box-in-uniq.rs similarity index 86% rename from src/test/run-pass/borrowck-preserve-box-in-uniq.rs rename to src/test/compile-fail/borrowck-preserve-box-in-uniq.rs index 0896d4de625c9..b06eb0d6ba23a 100644 --- a/src/test/run-pass/borrowck-preserve-box-in-uniq.rs +++ b/src/test/compile-fail/borrowck-preserve-box-in-uniq.rs @@ -26,8 +26,10 @@ struct F { f: ~int } pub fn main() { let mut x = ~@F{f: ~3}; borrow(x.f, |b_x| { + //~^ ERROR cannot borrow `x` as mutable because `*x.f` is also borrowed as immutable assert_eq!(*b_x, 3); assert_eq!(&(*x.f) as *int, &(*b_x) as *int); + //~^ NOTE borrow occurs due to use of `x` in closure *x = @F{f: ~4}; println!("&*b_x = {:p}", &(*b_x)); diff --git a/src/test/run-pass/borrowck-preserve-box.rs b/src/test/compile-fail/borrowck-preserve-box.rs similarity index 86% rename from src/test/run-pass/borrowck-preserve-box.rs rename to src/test/compile-fail/borrowck-preserve-box.rs index cfb9a4b91df17..1a920c7871e1c 100644 --- a/src/test/run-pass/borrowck-preserve-box.rs +++ b/src/test/compile-fail/borrowck-preserve-box.rs @@ -24,8 +24,10 @@ fn borrow(x: &int, f: |x: &int|) { pub fn main() { let mut x = @3; borrow(x, |b_x| { + //~^ ERROR cannot borrow `x` as mutable because `*x` is also borrowed as immutable assert_eq!(*b_x, 3); assert_eq!(&(*x) as *int, &(*b_x) as *int); + //~^ NOTE borrow occurs due to use of `x` in closure x = @22; println!("&*b_x = {:p}", &(*b_x)); diff --git a/src/test/run-pass/borrowck-preserve-cond-box.rs b/src/test/compile-fail/borrowck-preserve-cond-box.rs similarity index 88% rename from src/test/run-pass/borrowck-preserve-cond-box.rs rename to src/test/compile-fail/borrowck-preserve-cond-box.rs index 52ea474dbf550..7000e2351dd91 100644 --- a/src/test/run-pass/borrowck-preserve-cond-box.rs +++ b/src/test/compile-fail/borrowck-preserve-cond-box.rs @@ -30,8 +30,8 @@ fn testfn(cond: bool) { println!("*r = {}, exp = {}", *r, exp); assert_eq!(*r, exp); - x = @5; - y = @6; + x = @5; //~ERROR cannot assign to `x` because it is borrowed + y = @6; //~ERROR cannot assign to `y` because it is borrowed println!("*r = {}, exp = {}", *r, exp); assert_eq!(*r, exp); diff --git a/src/test/run-pass/borrowck-preserve-expl-deref.rs b/src/test/compile-fail/borrowck-preserve-expl-deref.rs similarity index 87% rename from src/test/run-pass/borrowck-preserve-expl-deref.rs rename to src/test/compile-fail/borrowck-preserve-expl-deref.rs index 749c806395003..aeabf6d9f8b55 100644 --- a/src/test/run-pass/borrowck-preserve-expl-deref.rs +++ b/src/test/compile-fail/borrowck-preserve-expl-deref.rs @@ -26,8 +26,10 @@ struct F { f: ~int } pub fn main() { let mut x = @F {f: ~3}; borrow((*x).f, |b_x| { + //~^ ERROR cannot borrow `x` as mutable because `*x.f` is also borrowed as immutable assert_eq!(*b_x, 3); assert_eq!(&(*x.f) as *int, &(*b_x) as *int); + //~^ NOTE borrow occurs due to use of `x` in closure x = @F {f: ~4}; println!("&*b_x = {:p}", &(*b_x)); diff --git a/src/test/run-pass/regions-appearance-constraint.rs b/src/test/compile-fail/regions-appearance-constraint.rs similarity index 78% rename from src/test/run-pass/regions-appearance-constraint.rs rename to src/test/compile-fail/regions-appearance-constraint.rs index a65a878b3c785..68bbebb8cb048 100644 --- a/src/test/run-pass/regions-appearance-constraint.rs +++ b/src/test/compile-fail/regions-appearance-constraint.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/* Tests conditional rooting of the box y */ +// Test no-special rooting is used for managed boxes #![feature(managed_boxes)] @@ -25,12 +25,11 @@ fn testfn(cond: bool) { exp = 4; } - x = @5; - y = @6; + x = @5; //~ERROR cannot assign to `x` because it is borrowed + y = @6; //~ERROR cannot assign to `y` because it is borrowed assert_eq!(*a, exp); assert_eq!(x, @5); assert_eq!(y, @6); } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/compile-fail/regions-infer-borrow-scope-too-big.rs b/src/test/compile-fail/regions-infer-borrow-scope-too-big.rs index b069a35ad7a26..1508349344c9a 100644 --- a/src/test/compile-fail/regions-infer-borrow-scope-too-big.rs +++ b/src/test/compile-fail/regions-infer-borrow-scope-too-big.rs @@ -20,7 +20,7 @@ fn x_coord<'r>(p: &'r point) -> &'r int { } fn foo(p: @point) -> &int { - let xc = x_coord(p); //~ ERROR cannot root + let xc = x_coord(p); //~ ERROR `*p` does not live long enough assert_eq!(*xc, 3); return xc; } diff --git a/src/test/compile-fail/regions-infer-borrow-scope-within-loop.rs b/src/test/compile-fail/regions-infer-borrow-scope-within-loop.rs index 9be8a5fef4dee..3cd70ce6c8a31 100644 --- a/src/test/compile-fail/regions-infer-borrow-scope-within-loop.rs +++ b/src/test/compile-fail/regions-infer-borrow-scope-within-loop.rs @@ -19,7 +19,7 @@ fn foo(cond: || -> bool, make_box: || -> @int) { // Here we complain because the resulting region // of this borrow is the fn body as a whole. - y = borrow(x); //~ ERROR cannot root + y = borrow(x); //~ ERROR `*x` does not live long enough assert_eq!(*x, *y); if cond() { break; } diff --git a/src/test/run-pass/struct-field-assignability.rs b/src/test/compile-fail/struct-field-assignability.rs similarity index 88% rename from src/test/run-pass/struct-field-assignability.rs rename to src/test/compile-fail/struct-field-assignability.rs index 3469936c05b3e..68a1726610656 100644 --- a/src/test/run-pass/struct-field-assignability.rs +++ b/src/test/compile-fail/struct-field-assignability.rs @@ -15,6 +15,6 @@ struct Foo<'a> { } pub fn main() { - let f = Foo { x: @3 }; + let f = Foo { x: @3 }; //~ ERROR borrowed value does not live long enough assert_eq!(*f.x, 3); }