]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #14945 : alexcrichton/rust/issue-14940, r=brson
authorbors <bors@rust-lang.org>
Tue, 17 Jun 2014 06:31:28 +0000 (06:31 +0000)
committerbors <bors@rust-lang.org>
Tue, 17 Jun 2014 06:31:28 +0000 (06:31 +0000)
This just takes a similar approach to reading stdin on windows by artificially
limiting the size of the buffers going in and out.

Closes #14940

src/librustc/middle/borrowck/check_loans.rs
src/librustc/middle/borrowck/gather_loans/mod.rs
src/librustc/middle/borrowck/gather_loans/restrictions.rs
src/librustc/middle/borrowck/mod.rs

index 111441180475e9a03d4fac38d3086ebd6833ceda..166d069880f9fa7fd189aa11feb74937ac7faf96 100644 (file)
@@ -155,6 +155,12 @@ enum UseError {
     UseWhileBorrowed(/*loan*/Rc<LoanPath>, /*loan*/Span)
 }
 
+fn compatible_borrow_kinds(borrow_kind1: ty::BorrowKind,
+                           borrow_kind2: ty::BorrowKind)
+                           -> bool {
+    borrow_kind1 == ty::ImmBorrow && borrow_kind2 == ty::ImmBorrow
+}
+
 impl<'a> CheckLoanCtxt<'a> {
     pub fn tcx(&self) -> &'a ty::ctxt { self.bccx.tcx }
 
@@ -189,29 +195,75 @@ pub fn each_in_scope_loan(&self,
         })
     }
 
-    pub fn each_in_scope_restriction(&self,
-                                     scope_id: ast::NodeId,
-                                     loan_path: &LoanPath,
-                                     op: |&Loan, &Restriction| -> bool)
-                                     -> bool {
-        //! Iterates through all the in-scope restrictions for the
-        //! given `loan_path`
+    fn each_in_scope_loan_affecting_path(&self,
+                                         scope_id: ast::NodeId,
+                                         loan_path: &LoanPath,
+                                         op: |&Loan| -> bool)
+                                         -> bool {
+        //! Iterates through all of the in-scope loans affecting `loan_path`,
+        //! calling `op`, and ceasing iteration if `false` is returned.
 
-        self.each_in_scope_loan(scope_id, |loan| {
-            debug!("each_in_scope_restriction found loan: {:?}",
-                   loan.repr(self.tcx()));
+        // First, we check for a loan restricting the path P being used. This
+        // accounts for borrows of P but also borrows of subpaths, like P.a.b.
+        // Consider the following example:
+        //
+        //     let x = &mut a.b.c; // Restricts a, a.b, and a.b.c
+        //     let y = a;          // Conflicts with restriction
 
+        let cont = self.each_in_scope_loan(scope_id, |loan| {
             let mut ret = true;
-            for restr in loan.restrictions.iter() {
-                if *restr.loan_path == *loan_path {
-                    if !op(loan, restr) {
+            for restr_path in loan.restricted_paths.iter() {
+                if **restr_path == *loan_path {
+                    if !op(loan) {
                         ret = false;
                         break;
                     }
                 }
             }
             ret
-        })
+        });
+
+        if !cont {
+            return false;
+        }
+
+        // Next, we must check for *loans* (not restrictions) on the path P or
+        // any base path. This rejects examples like the following:
+        //
+        //     let x = &mut a.b;
+        //     let y = a.b.c;
+        //
+        // Limiting this search to *loans* and not *restrictions* means that
+        // examples like the following continue to work:
+        //
+        //     let x = &mut a.b;
+        //     let y = a.c;
+
+        let mut loan_path = loan_path;
+        loop {
+            match *loan_path {
+                LpVar(_) => {
+                    break;
+                }
+                LpExtend(ref lp_base, _, _) => {
+                    loan_path = &**lp_base;
+                }
+            }
+
+            let cont = self.each_in_scope_loan(scope_id, |loan| {
+                if *loan.loan_path == *loan_path {
+                    op(loan)
+                } else {
+                    true
+                }
+            });
+
+            if !cont {
+                return false;
+            }
+        }
+
+        return true;
     }
 
     pub fn loans_generated_by(&self, scope_id: ast::NodeId) -> Vec<uint> {
@@ -288,26 +340,12 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                loan1.repr(self.tcx()),
                loan2.repr(self.tcx()));
 
-        // Restrictions that would cause the new loan to be illegal:
-        let illegal_if = match loan2.kind {
-            // Look for restrictions against mutation. These are
-            // generated by all other borrows.
-            ty::MutBorrow => RESTR_MUTATE,
-
-            // Look for restrictions against freezing (immutable borrows).
-            // These are generated by `&mut` borrows.
-            ty::ImmBorrow => RESTR_FREEZE,
-
-            // No matter how the data is borrowed (as `&`, as `&mut`,
-            // or as `&unique imm`) it will always generate a
-            // restriction against mutating the data. So look for those.
-            ty::UniqueImmBorrow => RESTR_MUTATE,
-        };
-        debug!("illegal_if={:?}", illegal_if);
+        if compatible_borrow_kinds(loan1.kind, loan2.kind) {
+            return true;
+        }
 
-        for restr in loan1.restrictions.iter() {
-            if !restr.set.intersects(illegal_if) { continue; }
-            if restr.loan_path != loan2.loan_path { continue; }
+        for restr_path in loan1.restricted_paths.iter() {
+            if *restr_path != loan2.loan_path { continue; }
 
             let old_pronoun = if new_loan.loan_path == old_loan.loan_path {
                 "it".to_string()
@@ -534,15 +572,8 @@ pub fn analyze_restrictions_on_use(&self,
 
         let mut ret = UseOk;
 
-        // First, we check for a restriction on the path P being used. This
-        // accounts for borrows of P but also borrows of subpaths, like P.a.b.
-        // Consider the following example:
-        //
-        //     let x = &mut a.b.c; // Restricts a, a.b, and a.b.c
-        //     let y = a;          // Conflicts with restriction
-
-        self.each_in_scope_restriction(expr_id, use_path, |loan, _restr| {
-            if incompatible(loan.kind, borrow_kind) {
+        self.each_in_scope_loan_affecting_path(expr_id, use_path, |loan| {
+            if !compatible_borrow_kinds(loan.kind, borrow_kind) {
                 ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
                 false
             } else {
@@ -550,47 +581,7 @@ pub fn analyze_restrictions_on_use(&self,
             }
         });
 
-        // Next, we must check for *loans* (not restrictions) on the path P or
-        // any base path. This rejects examples like the following:
-        //
-        //     let x = &mut a.b;
-        //     let y = a.b.c;
-        //
-        // Limiting this search to *loans* and not *restrictions* means that
-        // examples like the following continue to work:
-        //
-        //     let x = &mut a.b;
-        //     let y = a.c;
-
-        let mut loan_path = use_path;
-        loop {
-            self.each_in_scope_loan(expr_id, |loan| {
-                if *loan.loan_path == *loan_path &&
-                   incompatible(loan.kind, borrow_kind) {
-                    ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
-                    false
-                } else {
-                    true
-                }
-            });
-
-            match *loan_path {
-                LpVar(_) => {
-                    break;
-                }
-                LpExtend(ref lp_base, _, _) => {
-                    loan_path = &**lp_base;
-                }
-            }
-        }
-
         return ret;
-
-        fn incompatible(borrow_kind1: ty::BorrowKind,
-                        borrow_kind2: ty::BorrowKind)
-                        -> bool {
-            borrow_kind1 != ty::ImmBorrow || borrow_kind2 != ty::ImmBorrow
-        }
     }
 
     fn check_if_path_is_moved(&self,
@@ -668,11 +659,9 @@ fn check_assignment(&self,
         // and aliasing restrictions:
         if assignee_cmt.mutbl.is_mutable() {
             if check_for_aliasable_mutable_writes(self, assignment_span, assignee_cmt.clone()) {
-                if mode != euv::Init &&
-                    check_for_assignment_to_restricted_or_frozen_location(
-                        self, assignment_id, assignment_span, assignee_cmt.clone())
-                {
-                    // Safe, but record for lint pass later:
+                if mode != euv::Init {
+                    check_for_assignment_to_borrowed_path(
+                        self, assignment_id, assignment_span, assignee_cmt.clone());
                     mark_variable_as_used_mut(self, assignee_cmt);
                 }
             }
@@ -807,138 +796,24 @@ fn check_for_aliasability_violation(this: &CheckLoanCtxt,
             }
         }
 
-        fn check_for_assignment_to_restricted_or_frozen_location(
+        fn check_for_assignment_to_borrowed_path(
             this: &CheckLoanCtxt,
             assignment_id: ast::NodeId,
             assignment_span: Span,
-            assignee_cmt: mc::cmt) -> bool
+            assignee_cmt: mc::cmt)
         {
             //! Check for assignments that violate the terms of an
             //! outstanding loan.
 
             let loan_path = match opt_loan_path(&assignee_cmt) {
                 Some(lp) => lp,
-                None => { return true; /* no loan path, can't be any loans */ }
+                None => { return; /* no loan path, can't be any loans */ }
             };
 
-            // Start by searching for an assignment to a *restricted*
-            // location. Here is one example of the kind of error caught
-            // by this check:
-            //
-            //    let mut v = ~[1, 2, 3];
-            //    let p = &v;
-            //    v = ~[4];
-            //
-            // In this case, creating `p` triggers a RESTR_MUTATE
-            // restriction on the path `v`.
-            //
-            // Here is a second, more subtle example:
-            //
-            //    let mut v = ~[1, 2, 3];
-            //    let p = &const v[0];
-            //    v[0] = 4;                   // OK
-            //    v[1] = 5;                   // OK
-            //    v = ~[4, 5, 3];             // Error
-            //
-            // In this case, `p` is pointing to `v[0]`, and it is a
-            // `const` pointer in any case. So the first two
-            // assignments are legal (and would be permitted by this
-            // check). However, the final assignment (which is
-            // logically equivalent) is forbidden, because it would
-            // cause the existing `v` array to be freed, thus
-            // invalidating `p`. In the code, this error results
-            // because `gather_loans::restrictions` adds a
-            // `RESTR_MUTATE` restriction whenever the contents of an
-            // owned pointer are borrowed, and hence while `v[*]` is not
-            // restricted from being written, `v` is.
-            let cont = this.each_in_scope_restriction(assignment_id,
-                                                      &*loan_path,
-                                                      |loan, restr| {
-                if restr.set.intersects(RESTR_MUTATE) {
-                    this.report_illegal_mutation(assignment_span, &*loan_path, loan);
-                    false
-                } else {
-                    true
-                }
+            this.each_in_scope_loan_affecting_path(assignment_id, &*loan_path, |loan| {
+                this.report_illegal_mutation(assignment_span, &*loan_path, loan);
+                false
             });
-
-            if !cont { return false }
-
-            // The previous code handled assignments to paths that
-            // have been restricted. This covers paths that have been
-            // directly lent out and their base paths, but does not
-            // cover random extensions of those paths. For example,
-            // the following program is not declared illegal by the
-            // previous check:
-            //
-            //    let mut v = ~[1, 2, 3];
-            //    let p = &v;
-            //    v[0] = 4; // declared error by loop below, not code above
-            //
-            // The reason that this passes the previous check whereas
-            // an assignment like `v = ~[4]` fails is because the assignment
-            // here is to `v[*]`, and the existing restrictions were issued
-            // for `v`, not `v[*]`.
-            //
-            // So in this loop, we walk back up the loan path so long
-            // as the mutability of the path is dependent on a super
-            // path, and check that the super path was not lent out as
-            // mutable or immutable (a const loan is ok).
-            //
-            // Mutability of a path can be dependent on the super path
-            // in two ways. First, it might be inherited mutability.
-            // Second, the pointee of an `&mut` pointer can only be
-            // mutated if it is found in an unaliased location, so we
-            // have to check that the owner location is not borrowed.
-            //
-            // Note that we are *not* checking for any and all
-            // restrictions.  We are only interested in the pointers
-            // that the user created, whereas we add restrictions for
-            // all kinds of paths that are not directly aliased. If we checked
-            // for all restrictions, and not just loans, then the following
-            // valid program would be considered illegal:
-            //
-            //    let mut v = ~[1, 2, 3];
-            //    let p = &const v[0];
-            //    v[1] = 5; // ok
-            //
-            // Here the restriction that `v` not be mutated would be misapplied
-            // to block the subpath `v[1]`.
-            let full_loan_path = loan_path.clone();
-            let mut loan_path = loan_path;
-            loop {
-                loan_path = match *loan_path {
-                    // Peel back one layer if, for `loan_path` to be
-                    // mutable, `lp_base` must be mutable. This occurs
-                    // with inherited mutability, owned pointers and
-                    // `&mut` pointers.
-                    LpExtend(ref lp_base, mc::McInherited, _) |
-                    LpExtend(ref lp_base, _, LpDeref(mc::OwnedPtr)) |
-                    LpExtend(ref lp_base, _, LpDeref(mc::GcPtr)) |
-                    LpExtend(ref lp_base, _, LpDeref(mc::BorrowedPtr(ty::MutBorrow, _))) => {
-                        lp_base.clone()
-                    }
-
-                    // Otherwise stop iterating
-                    LpExtend(_, mc::McDeclared, _) |
-                    LpExtend(_, mc::McImmutable, _) |
-                    LpVar(_) => {
-                        return true;
-                    }
-                };
-
-                // Check for a non-const loan of `loan_path`
-                let cont = this.each_in_scope_loan(assignment_id, |loan| {
-                    if loan.loan_path == loan_path {
-                        this.report_illegal_mutation(assignment_span, &*full_loan_path, loan);
-                        false
-                    } else {
-                        true
-                    }
-                });
-
-                if !cont { return false }
-            }
         }
     }
 
index ac94b73564060dc46bf43f05b50335d23412f20d..89f304513ffb315580607438d55c03a7af2a07a5 100644 (file)
@@ -259,7 +259,7 @@ fn guarantee_valid(&mut self,
         // loan is safe.
         let restr = restrictions::compute_restrictions(
             self.bccx, borrow_span, cause,
-            cmt.clone(), loan_region, self.restriction_set(req_kind));
+            cmt.clone(), loan_region);
 
         // Create the loan record (if needed).
         let loan = match restr {
@@ -268,7 +268,7 @@ fn guarantee_valid(&mut self,
                 return;
             }
 
-            restrictions::SafeIf(loan_path, restrictions) => {
+            restrictions::SafeIf(loan_path, restricted_paths) => {
                 let loan_scope = match loan_region {
                     ty::ReScope(id) => id,
                     ty::ReFree(ref fr) => fr.scope_id,
@@ -314,7 +314,7 @@ fn guarantee_valid(&mut self,
                     gen_scope: gen_scope,
                     kill_scope: kill_scope,
                     span: borrow_span,
-                    restrictions: restrictions,
+                    restricted_paths: restricted_paths,
                     cause: cause,
                 }
             }
@@ -390,21 +390,6 @@ fn check_mutability(bccx: &BorrowckCtxt,
         }
     }
 
-    fn restriction_set(&self, req_kind: ty::BorrowKind) -> RestrictionSet {
-        match req_kind {
-            // If borrowing data as immutable, no mutation allowed:
-            ty::ImmBorrow => RESTR_MUTATE,
-
-            // If borrowing data as mutable, no mutation nor other
-            // borrows allowed:
-            ty::MutBorrow => RESTR_MUTATE | RESTR_FREEZE,
-
-            // If borrowing data as unique imm, no mutation nor other
-            // borrows allowed:
-            ty::UniqueImmBorrow => RESTR_MUTATE | RESTR_FREEZE,
-        }
-    }
-
     pub fn mark_loan_path_as_mutated(&self, loan_path: &LoanPath) {
         //! For mutable loans of content whose mutability derives
         //! from a local variable, mark the mutability decl as necessary.
index 7c1f5937472970f86af8903950c8a46b1fa13063..5b3e1ac0b2c74ab42f30f927c10d2a57234ee243 100644 (file)
 
 pub enum RestrictionResult {
     Safe,
-    SafeIf(Rc<LoanPath>, Vec<Restriction>)
+    SafeIf(Rc<LoanPath>, Vec<Rc<LoanPath>>)
 }
 
 pub fn compute_restrictions(bccx: &BorrowckCtxt,
                             span: Span,
                             cause: euv::LoanCause,
                             cmt: mc::cmt,
-                            loan_region: ty::Region,
-                            restr: RestrictionSet) -> RestrictionResult {
+                            loan_region: ty::Region) -> RestrictionResult {
     let ctxt = RestrictionsContext {
         bccx: bccx,
         span: span,
@@ -39,7 +38,7 @@ pub fn compute_restrictions(bccx: &BorrowckCtxt,
         loan_region: loan_region,
     };
 
-    ctxt.restrict(cmt, restr)
+    ctxt.restrict(cmt)
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -54,11 +53,8 @@ struct RestrictionsContext<'a> {
 
 impl<'a> RestrictionsContext<'a> {
     fn restrict(&self,
-                cmt: mc::cmt,
-                restrictions: RestrictionSet) -> RestrictionResult {
-        debug!("restrict(cmt={}, restrictions={})",
-               cmt.repr(self.bccx.tcx),
-               restrictions.repr(self.bccx.tcx));
+                cmt: mc::cmt) -> RestrictionResult {
+        debug!("restrict(cmt={})", cmt.repr(self.bccx.tcx));
 
         match cmt.cat.clone() {
             mc::cat_rvalue(..) => {
@@ -75,19 +71,14 @@ fn restrict(&self,
             mc::cat_upvar(ty::UpvarId {var_id: local_id, ..}, _) => {
                 // R-Variable
                 let lp = Rc::new(LpVar(local_id));
-                SafeIf(lp.clone(), vec!(Restriction {
-                    loan_path: lp,
-                    set: restrictions
-                }))
+                SafeIf(lp.clone(), vec!(lp))
             }
 
             mc::cat_downcast(cmt_base) => {
                 // When we borrow the interior of an enum, we have to
                 // ensure the enum itself is not mutated, because that
                 // could cause the type of the memory to change.
-                self.restrict(
-                    cmt_base,
-                    restrictions | RESTR_MUTATE)
+                self.restrict(cmt_base)
             }
 
             mc::cat_interior(cmt_base, i) => {
@@ -96,8 +87,8 @@ fn restrict(&self,
                 // Overwriting the base would not change the type of
                 // the memory, so no additional restrictions are
                 // needed.
-                let result = self.restrict(cmt_base, restrictions);
-                self.extend(result, cmt.mutbl, LpInterior(i), restrictions)
+                let result = self.restrict(cmt_base);
+                self.extend(result, cmt.mutbl, LpInterior(i))
             }
 
             mc::cat_deref(cmt_base, _, pk @ mc::OwnedPtr) |
@@ -112,10 +103,8 @@ fn restrict(&self,
                 // same, because this could be the last ref.
                 // Eventually we should make these non-special and
                 // just rely on Deref<T> implementation.
-                let result = self.restrict(
-                    cmt_base,
-                    restrictions | RESTR_MUTATE);
-                self.extend(result, cmt.mutbl, LpDeref(pk), restrictions)
+                let result = self.restrict(cmt_base);
+                self.extend(result, cmt.mutbl, LpDeref(pk))
             }
 
             mc::cat_copied_upvar(..) | // FIXME(#2152) allow mutation of upvars
@@ -133,7 +122,7 @@ fn restrict(&self,
                             cause: self.cause,
                             cmt: cmt_base,
                             code: err_borrowed_pointer_too_short(
-                                self.loan_region, lt, restrictions)});
+                                self.loan_region, lt)});
                     return Safe;
                 }
                 Safe
@@ -148,12 +137,12 @@ fn restrict(&self,
                             cause: self.cause,
                             cmt: cmt_base,
                             code: err_borrowed_pointer_too_short(
-                                self.loan_region, lt, restrictions)});
+                                self.loan_region, lt)});
                     return Safe;
                 }
 
-                let result = self.restrict(cmt_base, restrictions);
-                self.extend(result, cmt.mutbl, LpDeref(pk), restrictions)
+                let result = self.restrict(cmt_base);
+                self.extend(result, cmt.mutbl, LpDeref(pk))
             }
 
             mc::cat_deref(_, _, mc::UnsafePtr(..)) => {
@@ -162,7 +151,7 @@ fn restrict(&self,
             }
 
             mc::cat_discr(cmt_base, _) => {
-                self.restrict(cmt_base, restrictions)
+                self.restrict(cmt_base)
             }
         }
     }
@@ -170,16 +159,12 @@ fn restrict(&self,
     fn extend(&self,
               result: RestrictionResult,
               mc: mc::MutabilityCategory,
-              elem: LoanPathElem,
-              restrictions: RestrictionSet) -> RestrictionResult {
+              elem: LoanPathElem) -> RestrictionResult {
         match result {
             Safe => Safe,
             SafeIf(base_lp, mut base_vec) => {
                 let lp = Rc::new(LpExtend(base_lp, mc, elem));
-                base_vec.push(Restriction {
-                    loan_path: lp.clone(),
-                    set: restrictions
-                });
+                base_vec.push(lp.clone());
                 SafeIf(lp, base_vec)
             }
         }
index 44d722c209490d27abe6a2bba00f43df30f6b891..18cd0b1326d9610e38955b000c5035a8e29cfd54 100644 (file)
@@ -21,7 +21,6 @@
 use util::ppaux::{note_and_explain_region, Repr, UserString};
 
 use std::cell::{Cell};
-use std::ops::{BitOr, BitAnd};
 use std::rc::Rc;
 use std::gc::{Gc, GC};
 use std::string::String;
@@ -182,7 +181,7 @@ pub struct Loan {
     index: uint,
     loan_path: Rc<LoanPath>,
     kind: ty::BorrowKind,
-    restrictions: Vec<Restriction>,
+    restricted_paths: Vec<Rc<LoanPath>>,
     gen_scope: ast::NodeId,
     kill_scope: ast::NodeId,
     span: Span,
@@ -250,58 +249,6 @@ pub fn opt_loan_path(cmt: &mc::cmt) -> Option<Rc<LoanPath>> {
     }
 }
 
-///////////////////////////////////////////////////////////////////////////
-// Restrictions
-//
-// Borrowing an lvalue often results in *restrictions* that limit what
-// can be done with this lvalue during the scope of the loan:
-//
-// - `RESTR_MUTATE`: The lvalue may not be modified or `&mut` borrowed.
-// - `RESTR_FREEZE`: `&` borrows of the lvalue are forbidden.
-//
-// In addition, no value which is restricted may be moved. Therefore,
-// restrictions are meaningful even if the RestrictionSet is empty,
-// because the restriction against moves is implied.
-
-pub struct Restriction {
-    loan_path: Rc<LoanPath>,
-    set: RestrictionSet
-}
-
-#[deriving(PartialEq)]
-pub struct RestrictionSet {
-    bits: u32
-}
-
-#[allow(dead_code)] // potentially useful
-pub static RESTR_EMPTY: RestrictionSet  = RestrictionSet {bits: 0b0000};
-pub static RESTR_MUTATE: RestrictionSet = RestrictionSet {bits: 0b0001};
-pub static RESTR_FREEZE: RestrictionSet = RestrictionSet {bits: 0b0010};
-
-impl RestrictionSet {
-    pub fn intersects(&self, restr: RestrictionSet) -> bool {
-        (self.bits & restr.bits) != 0
-    }
-}
-
-impl BitOr<RestrictionSet,RestrictionSet> for RestrictionSet {
-    fn bitor(&self, rhs: &RestrictionSet) -> RestrictionSet {
-        RestrictionSet {bits: self.bits | rhs.bits}
-    }
-}
-
-impl BitAnd<RestrictionSet,RestrictionSet> for RestrictionSet {
-    fn bitand(&self, rhs: &RestrictionSet) -> RestrictionSet {
-        RestrictionSet {bits: self.bits & rhs.bits}
-    }
-}
-
-impl Repr for RestrictionSet {
-    fn repr(&self, _tcx: &ty::ctxt) -> String {
-        format!("RestrictionSet(0x{:x})", self.bits as uint)
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Errors
 
@@ -310,8 +257,7 @@ fn repr(&self, _tcx: &ty::ctxt) -> String {
 pub enum bckerr_code {
     err_mutbl,
     err_out_of_scope(ty::Region, ty::Region), // superscope, subscope
-    err_borrowed_pointer_too_short(
-        ty::Region, ty::Region, RestrictionSet), // loan, ptr
+    err_borrowed_pointer_too_short(ty::Region, ty::Region), // loan, ptr
 }
 
 // Combination of an error code and the categorization of the expression
@@ -711,7 +657,7 @@ pub fn note_and_explain_bckerr(&self, err: BckError) {
                     suggestion);
             }
 
-            err_borrowed_pointer_too_short(loan_scope, ptr_scope, _) => {
+            err_borrowed_pointer_too_short(loan_scope, ptr_scope) => {
                 let descr = match opt_loan_path(&err.cmt) {
                     Some(lp) => {
                         format!("`{}`", self.loan_path_to_str(&*lp))
@@ -827,15 +773,7 @@ fn repr(&self, tcx: &ty::ctxt) -> String {
                  self.kind,
                  self.gen_scope,
                  self.kill_scope,
-                 self.restrictions.repr(tcx))).to_string()
-    }
-}
-
-impl Repr for Restriction {
-    fn repr(&self, tcx: &ty::ctxt) -> String {
-        (format!("Restriction({}, {:x})",
-                 self.loan_path.repr(tcx),
-                 self.set.bits as uint)).to_string()
+                 self.restricted_paths.repr(tcx))).to_string()
     }
 }