about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-08-10 16:32:18 -0700
committerbors <bors@rust-lang.org>2013-08-10 16:32:18 -0700
commitbf809768ee8ff3ea4ef434721ff82b09a4df261a (patch)
treef7492e25ff06c4eeb3d1e480f641344b306c4247 /src
parent8b9e1ce75a3e1416f2db80d30f65879fd902183f (diff)
parent20953bb1fbfafc3839e739f38ddf7d495eb1fe8b (diff)
downloadrust-bf809768ee8ff3ea4ef434721ff82b09a4df261a.tar.gz
rust-bf809768ee8ff3ea4ef434721ff82b09a4df261a.zip
auto merge of #8444 : erickt/rust/rollup, r=cmr
This merges these PR together:

#8430: r=thestinger 
#8370: r=thestinger
#8386: r=bstrie
#8388: r=thestinger
#8390: r=graydon
#8394: r=graydon
#8402: r=thestinger
#8403: r=catamorphism
Diffstat (limited to 'src')
-rw-r--r--src/etc/emacs/rust-mode.el17
-rw-r--r--src/librustc/middle/check_match.rs26
-rw-r--r--src/librustc/middle/privacy.rs1
-rw-r--r--src/librustc/middle/trans/_match.rs215
-rw-r--r--src/libstd/trie.rs102
-rw-r--r--src/libsyntax/ext/base.rs20
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs2
-rw-r--r--src/libsyntax/opt_vec.rs24
-rw-r--r--src/libsyntax/parse/attr.rs131
-rw-r--r--src/libsyntax/parse/lexer.rs6
-rw-r--r--src/libsyntax/parse/parser.rs14
-rw-r--r--src/libsyntax/parse/token.rs3
-rw-r--r--src/test/auxiliary/xc_private_method_lib.rs30
-rw-r--r--src/test/compile-fail/borrowck-move-out-of-vec-tail.rs2
-rw-r--r--src/test/compile-fail/borrowck-vec-pattern-element-loan.rs6
-rw-r--r--src/test/compile-fail/borrowck-vec-pattern-nesting.rs14
-rw-r--r--src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs2
-rw-r--r--src/test/compile-fail/macro-inner-attributes.rs21
-rw-r--r--src/test/compile-fail/macro-outer-attributes.rs19
-rw-r--r--src/test/compile-fail/match-vec-fixed.rs16
-rw-r--r--src/test/compile-fail/match-vec-unreachable.rs4
-rw-r--r--src/test/compile-fail/xc-private-method.rs10
-rw-r--r--src/test/run-pass/issue-3121.rs1
-rw-r--r--src/test/run-pass/vec-matching-autoslice.rs10
-rw-r--r--src/test/run-pass/vec-matching-fixed.rs28
-rw-r--r--src/test/run-pass/vec-matching.rs35
-rw-r--r--src/test/run-pass/vec-tail-matching.rs2
27 files changed, 592 insertions, 169 deletions
diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el
index 87c505e69d0..ecb223f896c 100644
--- a/src/etc/emacs/rust-mode.el
+++ b/src/etc/emacs/rust-mode.el
@@ -29,6 +29,11 @@
 
     table))
 
+(defcustom rust-indent-offset default-tab-width
+  "*Indent Rust code by this number of spaces.
+
+The initializer is `DEFAULT-TAB-WIDTH'.")
+
 (defun rust-paren-level () (nth 0 (syntax-ppss)))
 (defun rust-in-str-or-cmnt () (nth 8 (syntax-ppss)))
 (defun rust-rewind-past-str-cmnt () (goto-char (nth 8 (syntax-ppss))))
@@ -49,10 +54,10 @@
            (let ((level (rust-paren-level)))
              (cond
               ;; A function return type is 1 level indented
-              ((looking-at "->") (* default-tab-width (+ level 1)))
+              ((looking-at "->") (* rust-indent-offset (+ level 1)))
 
               ;; A closing brace is 1 level unindended
-              ((looking-at "}") (* default-tab-width (- level 1)))
+              ((looking-at "}") (* rust-indent-offset (- level 1)))
 
               ;; If we're in any other token-tree / sexp, then:
               ;;  - [ or ( means line up with the opening token
@@ -70,18 +75,18 @@
                      (goto-char pt)
                      (back-to-indentation)
                      (if (looking-at "\\<else\\>")
-                         (* default-tab-width (+ 1 level))
+                         (* rust-indent-offset (+ 1 level))
                        (progn
                          (goto-char pt)
                          (beginning-of-line)
                          (rust-rewind-irrelevant)
                          (end-of-line)
                          (if (looking-back "[{};,]")
-                             (* default-tab-width level)
+                             (* rust-indent-offset level)
                            (back-to-indentation)
                            (if (looking-at "#")
-                               (* default-tab-width level)
-                             (* default-tab-width (+ 1 level))))))))))
+                               (* rust-indent-offset level)
+                             (* rust-indent-offset (+ 1 level))))))))))
 
               ;; Otherwise we're in a column-zero definition
               (t 0))))))
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index b640181515b..37f45142a11 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -255,6 +255,9 @@ pub fn is_useful(cx: &MatchCheckCtxt, m: &matrix, v: &[@pat]) -> useful {
                 }
                 not_useful
               }
+              ty::ty_evec(_, ty::vstore_fixed(n)) => {
+                is_useful_specialized(cx, m, v, vec(n), n, left_ty)
+              }
               ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
                 let max_len = do m.rev_iter().fold(0) |max_len, r| {
                   match r[0].node {
@@ -409,6 +412,29 @@ pub fn missing_ctor(cx: &MatchCheckCtxt,
         else if true_found { Some(val(const_bool(false))) }
         else { Some(val(const_bool(true))) }
       }
+      ty::ty_evec(_, ty::vstore_fixed(n)) => {
+        let mut missing = true;
+        let mut wrong = false;
+        for r in m.iter() {
+          match r[0].node {
+            pat_vec(ref before, ref slice, ref after) => {
+              let count = before.len() + after.len();
+              if (count < n && slice.is_none()) || count > n {
+                wrong = true;
+              }
+              if count == n || (count < n && slice.is_some()) {
+                missing = false;
+              }
+            }
+            _ => {}
+          }
+        }
+        match (wrong, missing) {
+          (true, _) => Some(vec(n)), // should be compile-time error
+          (_, true) => Some(vec(n)),
+          _         => None
+        }
+      }
       ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
 
         // Find the lengths and slices of all vector patterns.
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 9ffeb99ac35..a4b88870b97 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -403,6 +403,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                     // Ditto
                     match ty::get(ty::type_autoderef(tcx, ty::expr_ty(tcx,
                                                           base))).sty {
+                        ty_enum(id, _) |
                         ty_struct(id, _)
                         if id.crate != LOCAL_CRATE ||
                            !privileged_items.iter().any(|x| x == &(id.node)) => {
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 1a9c36313df..c98d859337c 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -145,6 +145,51 @@
  * - `store_non_ref_bindings()`
  * - `insert_lllocals()`
  *
+ *
+ * ## Notes on vector pattern matching.
+ *
+ * Vector pattern matching is surprisingly tricky. The problem is that
+ * the structure of the vector isn't fully known, and slice matches
+ * can be done on subparts of it.
+ *
+ * The way that vector pattern matches are dealt with, then, is as
+ * follows. First, we make the actual condition associated with a
+ * vector pattern simply a vector length comparison. So the pattern
+ * [1, .. x] gets the condition "vec len >= 1", and the pattern
+ * [.. x] gets the condition "vec len >= 0". The problem here is that
+ * having the condition "vec len >= 1" hold clearly does not mean that
+ * only a pattern that has exactly that condition will match. This
+ * means that it may well be the case that a condition holds, but none
+ * of the patterns matching that condition match; to deal with this,
+ * when doing vector length matches, we have match failures proceed to
+ * the next condition to check.
+ *
+ * There are a couple more subtleties to deal with. While the "actual"
+ * condition associated with vector length tests is simply a test on
+ * the vector length, the actual vec_len Opt entry contains more
+ * information used to restrict which matches are associated with it.
+ * So that all matches in a submatch are matching against the same
+ * values from inside the vector, they are split up by how many
+ * elements they match at the front and at the back of the vector. In
+ * order to make sure that arms are properly checked in order, even
+ * with the overmatching conditions, each vec_len Opt entry is
+ * associated with a range of matches.
+ * Consider the following:
+ *
+ *   match &[1, 2, 3] {
+ *       [1, 1, .. _] => 0,
+ *       [1, 2, 2, .. _] => 1,
+ *       [1, 2, 3, .. _] => 2,
+ *       [1, 2, .. _] => 3,
+ *       _ => 4
+ *   }
+ * The proper arm to match is arm 2, but arms 0 and 3 both have the
+ * condition "len >= 2". If arm 3 was lumped in with arm 0, then the
+ * wrong branch would be taken. Instead, vec_len Opts are associated
+ * with a contiguous range of matches that have the same "shape".
+ * This is sort of ugly and requires a bunch of special handling of
+ * vec_len options.
+ *
  */
 
 
@@ -189,14 +234,19 @@ enum Lit {
     ConstLit(ast::def_id),              // the def ID of the constant
 }
 
+#[deriving(Eq)]
+pub enum VecLenOpt {
+    vec_len_eq,
+    vec_len_ge(/* length of prefix */uint)
+}
+
 // An option identifying a branch (either a literal, a enum variant or a
 // range)
 enum Opt {
     lit(Lit),
     var(/* disr val */ uint, @adt::Repr),
     range(@ast::expr, @ast::expr),
-    vec_len_eq(uint),
-    vec_len_ge(uint, /* slice */uint)
+    vec_len(/* length */ uint, VecLenOpt, /*range of matches*/(uint, uint))
 }
 
 fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
@@ -247,9 +297,9 @@ fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
             }
         }
         (&var(a, _), &var(b, _)) => a == b,
-            (&vec_len_eq(a), &vec_len_eq(b)) => a == b,
-            (&vec_len_ge(a, _), &vec_len_ge(b, _)) => a == b,
-            _ => false
+        (&vec_len(a1, a2, _), &vec_len(b1, b2, _)) =>
+            a1 == b1 && a2 == b2,
+        _ => false
     }
 }
 
@@ -283,10 +333,10 @@ fn trans_opt(bcx: @mut Block, o: &Opt) -> opt_result {
             return range_result(rslt(bcx, consts::const_expr(ccx, l1)),
                                 rslt(bcx, consts::const_expr(ccx, l2)));
         }
-        vec_len_eq(n) => {
+        vec_len(n, vec_len_eq, _) => {
             return single_result(rslt(bcx, C_int(ccx, n as int)));
         }
-        vec_len_ge(n, _) => {
+        vec_len(n, vec_len_ge(_), _) => {
             return lower_bound(rslt(bcx, C_int(ccx, n as int)));
         }
     }
@@ -471,10 +521,11 @@ fn enter_match<'r>(bcx: @mut Block,
 }
 
 fn enter_default<'r>(bcx: @mut Block,
-                         dm: DefMap,
-                         m: &[Match<'r>],
-                         col: uint,
-                         val: ValueRef)
+                     dm: DefMap,
+                     m: &[Match<'r>],
+                     col: uint,
+                     val: ValueRef,
+                     chk: Option<mk_fail>)
                       -> ~[Match<'r>] {
     debug!("enter_default(bcx=%s, m=%s, col=%u, val=%s)",
            bcx.to_str(),
@@ -483,13 +534,36 @@ fn enter_default<'r>(bcx: @mut Block,
            bcx.val_to_str(val));
     let _indenter = indenter();
 
-    do enter_match(bcx, dm, m, col, val) |p| {
+    // Collect all of the matches that can match against anything.
+    let matches = do enter_match(bcx, dm, m, col, val) |p| {
         match p.node {
           ast::pat_wild | ast::pat_tup(_) => Some(~[]),
           ast::pat_ident(_, _, None) if pat_is_binding(dm, p) => Some(~[]),
           _ => None
         }
-    }
+    };
+
+    // Ok, now, this is pretty subtle. A "default" match is a match
+    // that needs to be considered if none of the actual checks on the
+    // value being considered succeed. The subtlety lies in that sometimes
+    // identifier/wildcard matches are *not* default matches. Consider:
+    // "match x { _ if something => foo, true => bar, false => baz }".
+    // There is a wildcard match, but it is *not* a default case. The boolean
+    // case on the value being considered is exhaustive. If the case is
+    // exhaustive, then there are no defaults.
+    //
+    // We detect whether the case is exhaustive in the following
+    // somewhat kludgy way: if the last wildcard/binding match has a
+    // guard, then by non-redundancy, we know that there aren't any
+    // non guarded matches, and thus by exhaustiveness, we know that
+    // we don't need any default cases. If the check *isn't* nonexhaustive
+    // (because chk is Some), then we need the defaults anyways.
+    let is_exhaustive = match matches.last_opt() {
+        Some(m) if m.data.arm.guard.is_some() && chk.is_none() => true,
+        _ => false
+    };
+
+    if is_exhaustive { ~[] } else { matches }
 }
 
 // <pcwalton> nmatsakis: what does enter_opt do?
@@ -523,17 +597,19 @@ fn enter_opt<'r>(bcx: @mut Block,
                      variant_size: uint,
                      val: ValueRef)
                   -> ~[Match<'r>] {
-    debug!("enter_opt(bcx=%s, m=%s, col=%u, val=%s)",
+    debug!("enter_opt(bcx=%s, m=%s, opt=%?, col=%u, val=%s)",
            bcx.to_str(),
            m.repr(bcx.tcx()),
+           *opt,
            col,
            bcx.val_to_str(val));
     let _indenter = indenter();
 
     let tcx = bcx.tcx();
     let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
+    let mut i = 0;
     do enter_match(bcx, tcx.def_map, m, col, val) |p| {
-        match p.node {
+        let answer = match p.node {
             ast::pat_enum(*) |
             ast::pat_ident(_, _, None) if pat_is_const(tcx.def_map, p) => {
                 let const_def = tcx.def_map.get_copy(&p.id);
@@ -599,32 +675,53 @@ fn enter_opt<'r>(bcx: @mut Block,
                 }
             }
             ast::pat_vec(ref before, slice, ref after) => {
+                let (lo, hi) = match *opt {
+                    vec_len(_, _, (lo, hi)) => (lo, hi),
+                    _ => tcx.sess.span_bug(p.span,
+                                           "vec pattern but not vec opt")
+                };
+
                 match slice {
-                    Some(slice) => {
+                    Some(slice) if i >= lo && i <= hi => {
                         let n = before.len() + after.len();
-                        let i = before.len();
-                        if opt_eq(tcx, &vec_len_ge(n, i), opt) {
+                        let this_opt = vec_len(n, vec_len_ge(before.len()),
+                                               (lo, hi));
+                        if opt_eq(tcx, &this_opt, opt) {
                             Some(vec::append_one((*before).clone(), slice) +
                                     *after)
                         } else {
                             None
                         }
                     }
-                    None => {
+                    None if i >= lo && i <= hi => {
                         let n = before.len();
-                        if opt_eq(tcx, &vec_len_eq(n), opt) {
+                        if opt_eq(tcx, &vec_len(n, vec_len_eq, (lo,hi)), opt) {
                             Some((*before).clone())
                         } else {
                             None
                         }
                     }
+                    _ => None
                 }
             }
             _ => {
                 assert_is_binding_or_wild(bcx, p);
-                Some(vec::from_elem(variant_size, dummy))
+                // In most cases, a binding/wildcard match be
+                // considered to match against any Opt. However, when
+                // doing vector pattern matching, submatches are
+                // considered even if the eventual match might be from
+                // a different submatch. Thus, when a submatch fails
+                // when doing a vector match, we proceed to the next
+                // submatch. Thus, including a default match would
+                // cause the default match to fire spuriously.
+                match *opt {
+                    vec_len(*) => None,
+                    _ => Some(vec::from_elem(variant_size, dummy))
+                }
             }
-        }
+        };
+        i += 1;
+        answer
     }
 }
 
@@ -805,9 +902,25 @@ fn get_options(bcx: @mut Block, m: &[Match], col: uint) -> ~[Opt] {
         if set.iter().any(|l| opt_eq(tcx, l, &val)) {return;}
         set.push(val);
     }
+    // Vector comparisions are special in that since the actual
+    // conditions over-match, we need to be careful about them. This
+    // means that in order to properly handle things in order, we need
+    // to not always merge conditions.
+    fn add_veclen_to_set(set: &mut ~[Opt], i: uint,
+                         len: uint, vlo: VecLenOpt) {
+        match set.last_opt() {
+            // If the last condition in the list matches the one we want
+            // to add, then extend its range. Otherwise, make a new
+            // vec_len with a range just covering the new entry.
+            Some(&vec_len(len2, vlo2, (start, end)))
+                 if len == len2 && vlo == vlo2 =>
+                 set[set.len() - 1] = vec_len(len, vlo, (start, end+1)),
+            _ => set.push(vec_len(len, vlo, (i, i)))
+        }
+    }
 
     let mut found = ~[];
-    for br in m.iter() {
+    for (i, br) in m.iter().enumerate() {
         let cur = br.pats[col];
         match cur.node {
             ast::pat_lit(l) => {
@@ -852,12 +965,12 @@ fn get_options(bcx: @mut Block, m: &[Match], col: uint) -> ~[Opt] {
                 add_to_set(ccx.tcx, &mut found, range(l1, l2));
             }
             ast::pat_vec(ref before, slice, ref after) => {
-                let opt = match slice {
-                    None => vec_len_eq(before.len()),
-                    Some(_) => vec_len_ge(before.len() + after.len(),
-                                          before.len())
+                let (len, vec_opt) = match slice {
+                    None => (before.len(), vec_len_eq),
+                    Some(_) => (before.len() + after.len(),
+                                vec_len_ge(before.len()))
                 };
-                add_to_set(ccx.tcx, &mut found, opt);
+                add_veclen_to_set(&mut found, i, len, vec_opt);
             }
             _ => {}
         }
@@ -1075,13 +1188,13 @@ fn pick_col(m: &[Match]) -> uint {
     }
     let mut scores = vec::from_elem(m[0].pats.len(), 0u);
     for br in m.iter() {
-        let mut i = 0u;
-        for p in br.pats.iter() { scores[i] += score(*p); i += 1u; }
+        for (i, p) in br.pats.iter().enumerate() {
+            scores[i] += score(*p);
+        }
     }
     let mut max_score = 0u;
     let mut best_col = 0u;
-    let mut i = 0u;
-    for score in scores.iter() {
+    for (i, score) in scores.iter().enumerate() {
         let score = *score;
 
         // Irrefutable columns always go first, they'd only be duplicated in
@@ -1090,7 +1203,6 @@ fn pick_col(m: &[Match]) -> uint {
         // If no irrefutable ones are found, we pick the one with the biggest
         // branching factor.
         if score > max_score { max_score = score; best_col = i; }
-        i += 1u;
     }
     return best_col;
 }
@@ -1460,7 +1572,7 @@ fn compile_submatch_continue(mut bcx: @mut Block,
                 test_val = Load(bcx, val);
                 kind = compare;
             },
-            vec_len_eq(*) | vec_len_ge(*) => {
+            vec_len(*) => {
                 let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
                 let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
                 let (_, len) = tvec::get_base_and_len(
@@ -1487,16 +1599,19 @@ fn compile_submatch_continue(mut bcx: @mut Block,
         C_int(ccx, 0) // Placeholder for when not using a switch
     };
 
-    let defaults = enter_default(else_cx, dm, m, col, val);
+    let defaults = enter_default(else_cx, dm, m, col, val, chk);
     let exhaustive = chk.is_none() && defaults.len() == 0u;
     let len = opts.len();
-    let mut i = 0u;
 
     // Compile subtrees for each option
-    for opt in opts.iter() {
-        i += 1u;
+    for (i, opt) in opts.iter().enumerate() {
+        // In some cases in vector pattern matching, we need to override
+        // the failure case so that instead of failing, it proceeds to
+        // try more matching. branch_chk, then, is the proper failure case
+        // for the current conditional branch.
+        let mut branch_chk = chk;
         let mut opt_cx = else_cx;
-        if !exhaustive || i < len {
+        if !exhaustive || i+1 < len {
             opt_cx = sub_block(bcx, "match_case");
             match kind {
               single => Br(bcx, opt_cx.llbb),
@@ -1586,6 +1701,10 @@ fn compile_submatch_continue(mut bcx: @mut Block,
                       }
                   };
                   bcx = sub_block(after_cx, "compare_vec_len_next");
+
+                  // If none of these subcases match, move on to the
+                  // next condition.
+                  branch_chk = Some::<mk_fail>(|| bcx.llbb);
                   CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
               }
               _ => ()
@@ -1604,17 +1723,13 @@ fn compile_submatch_continue(mut bcx: @mut Block,
                 unpacked = argvals;
                 opt_cx = new_bcx;
             }
-            vec_len_eq(n) | vec_len_ge(n, _) => {
-                let n = match *opt {
-                    vec_len_ge(*) => n + 1u,
-                    _ => n
-                };
-                let slice = match *opt {
-                    vec_len_ge(_, i) => Some(i),
-                    _ => None
+            vec_len(n, vt, _) => {
+                let (n, slice) = match vt {
+                    vec_len_ge(i) => (n + 1u, Some(i)),
+                    vec_len_eq => (n, None)
                 };
-                let args = extract_vec_elems(opt_cx, pat_span, pat_id, n, slice,
-                                             val, test_val);
+                let args = extract_vec_elems(opt_cx, pat_span, pat_id, n,
+                                             slice, val, test_val);
                 size = args.vals.len();
                 unpacked = args.vals.clone();
                 opt_cx = args.bcx;
@@ -1623,7 +1738,7 @@ fn compile_submatch_continue(mut bcx: @mut Block,
         }
         let opt_ms = enter_opt(opt_cx, m, opt, col, size, val);
         let opt_vals = vec::append(unpacked, vals_left);
-        compile_submatch(opt_cx, opt_ms, opt_vals, chk);
+        compile_submatch(opt_cx, opt_ms, opt_vals, branch_chk);
     }
 
     // Compile the fall-through case, if any
diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs
index 0bfee145a3c..da1fb9abaee 100644
--- a/src/libstd/trie.rs
+++ b/src/libstd/trie.rs
@@ -156,6 +156,53 @@ impl<T> TrieMap<T> {
             remaining_max: self.length
         }
     }
+
+    // If `upper` is true then returns upper_bound else returns lower_bound.
+    #[inline]
+    fn bound_iter<'a>(&'a self, key: uint, upper: bool) -> TrieMapIterator<'a, T> {
+        let mut node: &'a TrieNode<T> = &self.root;
+        let mut idx = 0;
+        let mut it = TrieMapIterator {
+            stack: ~[],
+            remaining_min: 0,
+            remaining_max: self.length
+        };
+        loop {
+            let children = &node.children;
+            let child_id = chunk(key, idx);
+            match children[child_id] {
+                Internal(ref n) => {
+                    node = &**n;
+                    it.stack.push(children.slice_from(child_id + 1).iter());
+                }
+                External(stored, _) => {
+                    if stored < key || (upper && stored == key) {
+                        it.stack.push(children.slice_from(child_id + 1).iter());
+                    } else {
+                        it.stack.push(children.slice_from(child_id).iter());
+                    }
+                    return it;
+                }
+                Nothing => {
+                    it.stack.push(children.slice_from(child_id + 1).iter());
+                    return it
+                }
+            }
+            idx += 1;
+        }
+    }
+
+    /// Get an iterator pointing to the first key-value pair whose key is not less than `key`.
+    /// If all keys in the map are less than `key` an empty iterator is returned.
+    pub fn lower_bound_iter<'a>(&'a self, key: uint) -> TrieMapIterator<'a, T> {
+        self.bound_iter(key, false)
+    }
+
+    /// Get an iterator pointing to the first key-value pair whose key is greater than `key`.
+    /// If all keys in the map are not greater than `key` an empty iterator is returned.
+    pub fn upper_bound_iter<'a>(&'a self, key: uint) -> TrieMapIterator<'a, T> {
+        self.bound_iter(key, true)
+    }
 }
 
 impl<T, Iter: Iterator<(uint, T)>> FromIterator<(uint, T), Iter> for TrieMap<T> {
@@ -233,6 +280,18 @@ impl TrieSet {
     pub fn iter<'a>(&'a self) -> TrieSetIterator<'a> {
         TrieSetIterator{iter: self.map.iter()}
     }
+
+    /// Get an iterator pointing to the first value that is not less than `val`.
+    /// If all values in the set are less than `val` an empty iterator is returned.
+    pub fn lower_bound_iter<'a>(&'a self, val: uint) -> TrieSetIterator<'a> {
+        TrieSetIterator{iter: self.map.lower_bound_iter(val)}
+    }
+
+    /// Get an iterator pointing to the first value that key is greater than `val`.
+    /// If all values in the set are not greater than `val` an empty iterator is returned.
+    pub fn upper_bound_iter<'a>(&'a self, val: uint) -> TrieSetIterator<'a> {
+        TrieSetIterator{iter: self.map.upper_bound_iter(val)}
+    }
 }
 
 impl<Iter: Iterator<uint>> FromIterator<uint, Iter> for TrieSet {
@@ -645,6 +704,49 @@ mod test_map {
         }
         assert_eq!(i, last - first);
     }
+
+    #[test]
+    fn test_bound_iter() {
+        let empty_map : TrieMap<uint> = TrieMap::new();
+        assert_eq!(empty_map.lower_bound_iter(0).next(), None);
+        assert_eq!(empty_map.upper_bound_iter(0).next(), None);
+
+        let last = 999u;
+        let step = 3u;
+        let value = 42u;
+
+        let mut map : TrieMap<uint> = TrieMap::new();
+        do uint::range_step(0u, last, step as int) |x| {
+            assert!(x % step == 0);
+            map.insert(x, value);
+            true
+        };
+
+        for i in range(0u, last - step) {
+            let mut lb = map.lower_bound_iter(i);
+            let mut ub = map.upper_bound_iter(i);
+            let next_key = i - i % step + step;
+            let next_pair = (next_key, &value);
+            if (i % step == 0) {
+                assert_eq!(lb.next(), Some((i, &value)));
+            } else {
+                assert_eq!(lb.next(), Some(next_pair));
+            }
+            assert_eq!(ub.next(), Some(next_pair));
+        }
+
+        let mut lb = map.lower_bound_iter(last - step);
+        assert_eq!(lb.next(), Some((last - step, &value)));
+        let mut ub = map.upper_bound_iter(last - step);
+        assert_eq!(ub.next(), None);
+
+        for i in range(last - step + 1, last) {
+            let mut lb = map.lower_bound_iter(i);
+            assert_eq!(lb.next(), None);
+            let mut ub = map.upper_bound_iter(i);
+            assert_eq!(ub.next(), None);
+        }
+    }
 }
 
 #[cfg(test)]
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 1e696451701..dfaffa0c275 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -421,12 +421,12 @@ pub enum MapChain<K,V> {
 // get the map from an env frame
 impl <K: Eq + Hash + IterBytes + 'static, V: 'static> MapChain<K,V>{
     // Constructor. I don't think we need a zero-arg one.
-    fn new(init: ~HashMap<K,@V>) -> @mut MapChain<K,V> {
+    pub fn new(init: ~HashMap<K,@V>) -> @mut MapChain<K,V> {
         @mut BaseMapChain(init)
     }
 
     // add a new frame to the environment (functionally)
-    fn push_frame (@mut self) -> @mut MapChain<K,V> {
+    pub fn push_frame (@mut self) -> @mut MapChain<K,V> {
         @mut ConsMapChain(~HashMap::new() ,self)
     }
 
@@ -436,7 +436,7 @@ impl <K: Eq + Hash + IterBytes + 'static, V: 'static> MapChain<K,V>{
 
     // ugh: can't get this to compile with mut because of the
     // lack of flow sensitivity.
-    fn get_map<'a>(&'a self) -> &'a HashMap<K,@V> {
+    pub fn get_map<'a>(&'a self) -> &'a HashMap<K,@V> {
         match *self {
             BaseMapChain (~ref map) => map,
             ConsMapChain (~ref map,_) => map
@@ -446,7 +446,7 @@ impl <K: Eq + Hash + IterBytes + 'static, V: 'static> MapChain<K,V>{
 // traits just don't work anywhere...?
 //impl Map<Name,SyntaxExtension> for MapChain {
 
-    fn contains_key (&self, key: &K) -> bool {
+    pub fn contains_key (&self, key: &K) -> bool {
         match *self {
             BaseMapChain (ref map) => map.contains_key(key),
             ConsMapChain (ref map,ref rest) =>
@@ -457,17 +457,17 @@ impl <K: Eq + Hash + IterBytes + 'static, V: 'static> MapChain<K,V>{
     // should each_key and each_value operate on shadowed
     // names? I think not.
     // delaying implementing this....
-    fn each_key (&self, _f: &fn (&K)->bool) {
+    pub fn each_key (&self, _f: &fn (&K)->bool) {
         fail!("unimplemented 2013-02-15T10:01");
     }
 
-    fn each_value (&self, _f: &fn (&V) -> bool) {
+    pub fn each_value (&self, _f: &fn (&V) -> bool) {
         fail!("unimplemented 2013-02-15T10:02");
     }
 
     // Returns a copy of the value that the name maps to.
     // Goes down the chain 'til it finds one (or bottom out).
-    fn find (&self, key: &K) -> Option<@V> {
+    pub fn find (&self, key: &K) -> Option<@V> {
         match self.get_map().find (key) {
             Some(ref v) => Some(**v),
             None => match *self {
@@ -477,7 +477,7 @@ impl <K: Eq + Hash + IterBytes + 'static, V: 'static> MapChain<K,V>{
         }
     }
 
-    fn find_in_topmost_frame(&self, key: &K) -> Option<@V> {
+    pub fn find_in_topmost_frame(&self, key: &K) -> Option<@V> {
         let map = match *self {
             BaseMapChain(ref map) => map,
             ConsMapChain(ref map,_) => map
@@ -487,7 +487,7 @@ impl <K: Eq + Hash + IterBytes + 'static, V: 'static> MapChain<K,V>{
     }
 
     // insert the binding into the top-level map
-    fn insert (&mut self, key: K, ext: @V) -> bool {
+    pub fn insert (&mut self, key: K, ext: @V) -> bool {
         // can't abstract over get_map because of flow sensitivity...
         match *self {
             BaseMapChain (~ref mut map) => map.insert(key, ext),
@@ -499,7 +499,7 @@ impl <K: Eq + Hash + IterBytes + 'static, V: 'static> MapChain<K,V>{
     // ... there are definitely some opportunities for abstraction
     // here that I'm ignoring. (e.g., manufacturing a predicate on
     // the maps in the chain, and using an abstract "find".
-    fn insert_into_frame(&mut self, key: K, ext: @V, n: K, pred: &fn(&@V)->bool) {
+    pub fn insert_into_frame(&mut self, key: K, ext: @V, n: K, pred: &fn(&@V)->bool) {
         match *self {
             BaseMapChain (~ref mut map) => {
                 if satisfies_pred(map,&n,pred) {
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 5a1317034b2..918949113ad 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -17,6 +17,7 @@ use codemap;
 use parse::lexer::*; //resolve bug?
 use parse::ParseSess;
 use parse::parser::Parser;
+use parse::attr::parser_attr;
 use parse::token::{Token, EOF, to_str, nonterminal, get_ident_interner, ident_to_str};
 use parse::token;
 
@@ -430,6 +431,7 @@ pub fn parse_nt(p: &Parser, name: &str) -> nonterminal {
                      + token::to_str(get_ident_interner(), p.token))
       },
       "path" => token::nt_path(p.parse_path_with_tps(false)),
+      "attr" => token::nt_attr(@p.parse_attribute(false)),
       "tt" => {
         *p.quote_depth += 1u; //but in theory, non-quoted tts might be useful
         let res = token::nt_tt(@p.parse_token_tree());
diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs
index 5d79532c8c5..3a10206b513 100644
--- a/src/libsyntax/opt_vec.rs
+++ b/src/libsyntax/opt_vec.rs
@@ -36,7 +36,7 @@ pub fn from<T>(t: ~[T]) -> OptVec<T> {
 }
 
 impl<T> OptVec<T> {
-    fn push(&mut self, t: T) {
+    pub fn push(&mut self, t: T) {
         match *self {
             Vec(ref mut v) => {
                 v.push(t);
@@ -50,32 +50,32 @@ impl<T> OptVec<T> {
         *self = Vec(~[t]);
     }
 
-    fn map<U>(&self, op: &fn(&T) -> U) -> OptVec<U> {
+    pub fn map<U>(&self, op: &fn(&T) -> U) -> OptVec<U> {
         match *self {
             Empty => Empty,
             Vec(ref v) => Vec(v.map(op))
         }
     }
 
-    fn map_move<U>(self, op: &fn(T) -> U) -> OptVec<U> {
+    pub fn map_move<U>(self, op: &fn(T) -> U) -> OptVec<U> {
         match self {
             Empty => Empty,
             Vec(v) => Vec(v.move_iter().map(op).collect())
         }
     }
 
-    fn get<'a>(&'a self, i: uint) -> &'a T {
+    pub fn get<'a>(&'a self, i: uint) -> &'a T {
         match *self {
             Empty => fail!("Invalid index %u", i),
             Vec(ref v) => &v[i]
         }
     }
 
-    fn is_empty(&self) -> bool {
+    pub fn is_empty(&self) -> bool {
         self.len() == 0
     }
 
-    fn len(&self) -> uint {
+    pub fn len(&self) -> uint {
         match *self {
             Empty => 0,
             Vec(ref v) => v.len()
@@ -83,7 +83,7 @@ impl<T> OptVec<T> {
     }
 
     #[inline]
-    fn iter<'r>(&'r self) -> OptVecIterator<'r, T> {
+    pub fn iter<'r>(&'r self) -> OptVecIterator<'r, T> {
         match *self {
             Empty => OptVecIterator{iter: None},
             Vec(ref v) => OptVecIterator{iter: Some(v.iter())}
@@ -91,11 +91,11 @@ impl<T> OptVec<T> {
     }
 
     #[inline]
-    fn map_to_vec<B>(&self, op: &fn(&T) -> B) -> ~[B] {
+    pub fn map_to_vec<B>(&self, op: &fn(&T) -> B) -> ~[B] {
         self.iter().map(op).collect()
     }
 
-    fn mapi_to_vec<B>(&self, op: &fn(uint, &T) -> B) -> ~[B] {
+    pub fn mapi_to_vec<B>(&self, op: &fn(uint, &T) -> B) -> ~[B] {
         let mut index = 0;
         self.map_to_vec(|a| {
             let i = index;
@@ -113,7 +113,7 @@ pub fn take_vec<T>(v: OptVec<T>) -> ~[T] {
 }
 
 impl<T:Clone> OptVec<T> {
-    fn prepend(&self, t: T) -> OptVec<T> {
+    pub fn prepend(&self, t: T) -> OptVec<T> {
         let mut v0 = ~[t];
         match *self {
             Empty => {}
@@ -124,7 +124,7 @@ impl<T:Clone> OptVec<T> {
 }
 
 impl<A:Eq> Eq for OptVec<A> {
-    fn eq(&self, other: &OptVec<A>) -> bool {
+    pub fn eq(&self, other: &OptVec<A>) -> bool {
         // Note: cannot use #[deriving(Eq)] here because
         // (Empty, Vec(~[])) ought to be equal.
         match (self, other) {
@@ -135,7 +135,7 @@ impl<A:Eq> Eq for OptVec<A> {
         }
     }
 
-    fn ne(&self, other: &OptVec<A>) -> bool {
+    pub fn ne(&self, other: &OptVec<A>) -> bool {
         !self.eq(other)
     }
 }
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 8cce5f15e67..f2489d80e1e 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -9,21 +9,17 @@
 // except according to those terms.
 
 use ast;
-use codemap::spanned;
+use codemap::{spanned, mk_sp};
 use codemap::BytePos;
 use parse::common::*; //resolve bug?
 use parse::token;
 use parse::parser::Parser;
+use parse::token::INTERPOLATED;
 
 // a parser that can parse attributes.
 pub trait parser_attr {
     fn parse_outer_attributes(&self) -> ~[ast::Attribute];
-    fn parse_attribute(&self, style: ast::AttrStyle) -> ast::Attribute;
-    fn parse_attribute_naked(
-        &self,
-        style: ast::AttrStyle,
-        lo: BytePos
-    ) -> ast::Attribute;
+    fn parse_attribute(&self, permit_inner: bool) -> ast::Attribute;
     fn parse_inner_attrs_and_next(&self) ->
         (~[ast::Attribute], ~[ast::Attribute]);
     fn parse_meta_item(&self) -> @ast::MetaItem;
@@ -37,12 +33,17 @@ impl parser_attr for Parser {
     fn parse_outer_attributes(&self) -> ~[ast::Attribute] {
         let mut attrs: ~[ast::Attribute] = ~[];
         loop {
+            debug!("parse_outer_attributes: self.token=%?",
+                   self.token);
             match *self.token {
+              token::INTERPOLATED(token::nt_attr(*)) => {
+                attrs.push(self.parse_attribute(false));
+              }
               token::POUND => {
                 if self.look_ahead(1, |t| *t != token::LBRACKET) {
                     break;
                 }
-                attrs.push(self.parse_attribute(ast::AttrOuter));
+                attrs.push(self.parse_attribute(false));
               }
               token::DOC_COMMENT(s) => {
                 let attr = ::attr::mk_sugared_doc_attr(
@@ -62,23 +63,49 @@ impl parser_attr for Parser {
         return attrs;
     }
 
-    // matches attribute = # attribute_naked
-    fn parse_attribute(&self, style: ast::AttrStyle) -> ast::Attribute {
-        let lo = self.span.lo;
-        self.expect(&token::POUND);
-        return self.parse_attribute_naked(style, lo);
+    // matches attribute = # [ meta_item ]
+    //
+    // if permit_inner is true, then a trailing `;` indicates an inner
+    // attribute
+    fn parse_attribute(&self, permit_inner: bool) -> ast::Attribute {
+        debug!("parse_attributes: permit_inner=%? self.token=%?",
+               permit_inner, self.token);
+        let (span, value) = match *self.token {
+            INTERPOLATED(token::nt_attr(attr)) => {
+                assert!(attr.node.style == ast::AttrOuter);
+                self.bump();
+                (attr.span, attr.node.value)
+            }
+            token::POUND => {
+                let lo = self.span.lo;
+                self.bump();
+                self.expect(&token::LBRACKET);
+                let meta_item = self.parse_meta_item();
+                self.expect(&token::RBRACKET);
+                let hi = self.span.hi;
+                (mk_sp(lo, hi), meta_item)
+            }
+            _ => {
+                self.fatal(fmt!("expected `#` but found `%s`",
+                                self.this_token_to_str()));
+            }
+        };
+        let style = if permit_inner && *self.token == token::SEMI {
+            self.bump();
+            ast::AttrInner
+        } else {
+            ast::AttrOuter
+        };
+        return spanned {
+            span: span,
+            node: ast::Attribute_ {
+                style: style,
+                value: value,
+                is_sugared_doc: false
+            }
+        };
     }
 
-    // matches attribute_naked = [ meta_item ]
-    fn parse_attribute_naked(&self, style: ast::AttrStyle, lo: BytePos) ->
-        ast::Attribute {
-        self.expect(&token::LBRACKET);
-        let meta_item = self.parse_meta_item();
-        self.expect(&token::RBRACKET);
-        let hi = self.span.hi;
-        return spanned(lo, hi, ast::Attribute_ { style: style,
-                                                 value: meta_item, is_sugared_doc: false }); }
-
     // Parse attributes that appear after the opening of an item, each
     // terminated by a semicolon. In addition to a vector of inner attributes,
     // this function also returns a vector that may contain the first outer
@@ -89,47 +116,37 @@ impl parser_attr for Parser {
     // matches inner_attrs* outer_attr?
     // you can make the 'next' field an Option, but the result is going to be
     // more useful as a vector.
-    fn parse_inner_attrs_and_next(&self) ->
-        (~[ast::Attribute], ~[ast::Attribute]) {
+    fn parse_inner_attrs_and_next(&self)
+                                  -> (~[ast::Attribute], ~[ast::Attribute]) {
         let mut inner_attrs: ~[ast::Attribute] = ~[];
         let mut next_outer_attrs: ~[ast::Attribute] = ~[];
         loop {
-            match *self.token {
-              token::POUND => {
-                if self.look_ahead(1, |t| *t != token::LBRACKET) {
-                    // This is an extension
-                    break;
+            let attr = match *self.token {
+                token::INTERPOLATED(token::nt_attr(*)) => {
+                    self.parse_attribute(true)
+                }
+                token::POUND => {
+                    if self.look_ahead(1, |t| *t != token::LBRACKET) {
+                        // This is an extension
+                        break;
+                    }
+                    self.parse_attribute(true)
                 }
-                let attr = self.parse_attribute(ast::AttrInner);
-                if *self.token == token::SEMI {
+                token::DOC_COMMENT(s) => {
                     self.bump();
-                    inner_attrs.push(attr);
-                } else {
-                    // It's not really an inner attribute
-                    let outer_attr =
-                        spanned(attr.span.lo, attr.span.hi,
-                            ast::Attribute_ { style: ast::AttrOuter,
-                                              value: attr.node.value,
-                                              is_sugared_doc: false });
-                    next_outer_attrs.push(outer_attr);
-                    break;
+                    ::attr::mk_sugared_doc_attr(self.id_to_str(s),
+                                                self.span.lo,
+                                                self.span.hi)
                 }
-              }
-              token::DOC_COMMENT(s) => {
-                let attr = ::attr::mk_sugared_doc_attr(
-                    self.id_to_str(s),
-                    self.span.lo,
-                    self.span.hi
-                );
-                self.bump();
-                if attr.node.style == ast::AttrInner {
-                  inner_attrs.push(attr);
-                } else {
-                  next_outer_attrs.push(attr);
-                  break;
+                _ => {
+                    break;
                 }
-              }
-              _ => break
+            };
+            if attr.node.style == ast::AttrInner {
+                inner_attrs.push(attr);
+            } else {
+                next_outer_attrs.push(attr);
+                break;
             }
         }
         (inner_attrs, next_outer_attrs)
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index 49deafeda40..bde568b2610 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -129,7 +129,11 @@ impl reader for StringReader {
 
 impl reader for TtReader {
     fn is_eof(@mut self) -> bool { self.cur_tok == token::EOF }
-    fn next_token(@mut self) -> TokenAndSpan { tt_next_token(self) }
+    fn next_token(@mut self) -> TokenAndSpan {
+        let r = tt_next_token(self);
+        debug!("TtReader: r=%?", r);
+        return r;
+    }
     fn fatal(@mut self, m: ~str) -> ! {
         self.sp_diag.span_fatal(self.cur_span, m);
     }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index d1916088a41..77c50a779c0 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[macro_escape];
+
 use abi;
 use abi::AbiSet;
 use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil};
@@ -4460,7 +4462,17 @@ impl Parser {
                                attrs: ~[Attribute],
                                macros_allowed: bool)
                                -> item_or_view_item {
-        maybe_whole!(iovi self, nt_item);
+        match *self.token {
+            INTERPOLATED(token::nt_item(item)) => {
+                self.bump();
+                let new_attrs = vec::append(attrs, item.attrs);
+                return iovi_item(@ast::item {
+                        attrs: new_attrs,
+                        ..(*item).clone()});
+            }
+            _ => {}
+        }
+
         let lo = self.span.lo;
 
         let visibility = self.parse_non_priv_visibility();
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index fd491c1e890..c554f111bf9 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -105,6 +105,7 @@ pub enum nonterminal {
     nt_expr(@ast::expr),
     nt_ty(   ast::Ty),
     nt_ident(ast::ident, bool),
+    nt_attr(@ast::Attribute),   // #[foo]
     nt_path( ast::Path),
     nt_tt(  @ast::token_tree), //needs @ed to break a circularity
     nt_matchers(~[ast::matcher])
@@ -205,6 +206,7 @@ pub fn to_str(input: @ident_interner, t: &Token) -> ~str {
       INTERPOLATED(ref nt) => {
         match nt {
             &nt_expr(e) => ::print::pprust::expr_to_str(e, input),
+            &nt_attr(e) => ::print::pprust::attribute_to_str(e, input),
             _ => {
                 ~"an interpolated " +
                     match (*nt) {
@@ -212,6 +214,7 @@ pub fn to_str(input: @ident_interner, t: &Token) -> ~str {
                       nt_block(*) => ~"block",
                       nt_stmt(*) => ~"statement",
                       nt_pat(*) => ~"pattern",
+                      nt_attr(*) => fail!("should have been handled"),
                       nt_expr(*) => fail!("should have been handled above"),
                       nt_ty(*) => ~"type",
                       nt_ident(*) => ~"identifier",
diff --git a/src/test/auxiliary/xc_private_method_lib.rs b/src/test/auxiliary/xc_private_method_lib.rs
index 05325c3b935..8290f62bada 100644
--- a/src/test/auxiliary/xc_private_method_lib.rs
+++ b/src/test/auxiliary/xc_private_method_lib.rs
@@ -1,9 +1,33 @@
 #[crate_type="lib"];
 
-pub struct Foo {
+pub struct Struct {
     x: int
 }
 
-impl Foo {
-    fn new() -> Foo { Foo { x: 1 } }
+impl Struct {
+    fn static_meth_struct() -> Struct {
+        Struct { x: 1 }
+    }
+
+    fn meth_struct(&self) -> int {
+        self.x
+    }
+}
+
+pub enum Enum {
+    Variant1(int),
+    Variant2(int)
+}
+
+impl Enum {
+    fn static_meth_enum() -> Enum {
+        Variant2(10)
+    }
+
+    fn meth_enum(&self) -> int {
+        match *self {
+            Variant1(x) |
+            Variant2(x) => x
+        }
+    }
 }
diff --git a/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs b/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs
index 39a0e585ad2..0f67d8a6d0c 100644
--- a/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs
+++ b/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs
@@ -6,7 +6,7 @@ struct Foo {
 }
 
 pub fn main() {
-    let x = [
+    let x = ~[
         Foo { string: ~"foo" },
         Foo { string: ~"bar" },
         Foo { string: ~"baz" }
diff --git a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
index 7f98eba5996..ca20d68e4cd 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
+++ b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
@@ -1,5 +1,5 @@
 fn a() -> &[int] {
-    let vec = [1, 2, 3, 4];
+    let vec = ~[1, 2, 3, 4];
     let tail = match vec {
         [_, ..tail] => tail, //~ ERROR does not live long enough
         _ => fail!("a")
@@ -8,7 +8,7 @@ fn a() -> &[int] {
 }
 
 fn b() -> &[int] {
-    let vec = [1, 2, 3, 4];
+    let vec = ~[1, 2, 3, 4];
     let init = match vec {
         [..init, _] => init, //~ ERROR does not live long enough
         _ => fail!("b")
@@ -17,7 +17,7 @@ fn b() -> &[int] {
 }
 
 fn c() -> &[int] {
-    let vec = [1, 2, 3, 4];
+    let vec = ~[1, 2, 3, 4];
     let slice = match vec {
         [_, ..slice, _] => slice, //~ ERROR does not live long enough
         _ => fail!("c")
diff --git a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs b/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
index 36ae5f88208..02ba1b9d2ff 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
+++ b/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
@@ -1,24 +1,24 @@
 fn a() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [~ref _a] => {
-            vec[0] = ~4; //~ ERROR cannot assign to `vec[]` because it is borrowed
+            vec[0] = ~4; //~ ERROR cannot assign to `(*vec)[]` because it is borrowed
         }
         _ => fail!("foo")
     }
 }
 
 fn b() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [.._b] => {
-            vec[0] = ~4; //~ ERROR cannot assign to `vec[]` because it is borrowed
+            vec[0] = ~4; //~ ERROR cannot assign to `(*vec)[]` because it is borrowed
         }
     }
 }
 
 fn c() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [_a, .._b] => {
             //~^ ERROR cannot move out
@@ -35,7 +35,7 @@ fn c() {
 }
 
 fn d() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [.._a, _b] => {
             //~^ ERROR cannot move out
@@ -46,7 +46,7 @@ fn d() {
 }
 
 fn e() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [_a, _b, _c] => {}
         _ => {}
diff --git a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
index e3e12a4a416..87511c34172 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
+++ b/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
@@ -1,5 +1,5 @@
 fn a() -> &int {
-    let vec = [1, 2, 3, 4];
+    let vec = ~[1, 2, 3, 4];
     let tail = match vec {
         [_a, ..tail] => &tail[0], //~ ERROR borrowed value does not live long enough
         _ => fail!("foo")
diff --git a/src/test/compile-fail/macro-inner-attributes.rs b/src/test/compile-fail/macro-inner-attributes.rs
new file mode 100644
index 00000000000..95000f4aa22
--- /dev/null
+++ b/src/test/compile-fail/macro-inner-attributes.rs
@@ -0,0 +1,21 @@
+macro_rules! test ( ($nm:ident,
+                     $a:attr,
+                     $i:item) => (mod $nm { $a; $i }); )
+
+test!(a,
+      #[cfg(qux)],
+      pub fn bar() { })
+
+test!(b,
+      #[cfg(not(qux))],
+      pub fn bar() { })
+
+#[qux]
+fn main() {
+    a::bar();
+    //~^ ERROR use of undeclared module `a`
+    //~^^ ERROR unresolved name
+    //~^^^ ERROR unresolved name `a::bar`
+    b::bar();
+}
+
diff --git a/src/test/compile-fail/macro-outer-attributes.rs b/src/test/compile-fail/macro-outer-attributes.rs
new file mode 100644
index 00000000000..23c3e80cd3b
--- /dev/null
+++ b/src/test/compile-fail/macro-outer-attributes.rs
@@ -0,0 +1,19 @@
+macro_rules! test ( ($nm:ident,
+                     $a:attr,
+                     $i:item) => (mod $nm { $a $i }); )
+
+test!(a,
+      #[cfg(qux)],
+      pub fn bar() { })
+
+test!(b,
+      #[cfg(not(qux))],
+      pub fn bar() { })
+
+// test1!(#[bar])
+#[qux]
+fn main() {
+    a::bar(); //~ ERROR unresolved name `a::bar`
+    b::bar();
+}
+
diff --git a/src/test/compile-fail/match-vec-fixed.rs b/src/test/compile-fail/match-vec-fixed.rs
new file mode 100644
index 00000000000..b3e139805a0
--- /dev/null
+++ b/src/test/compile-fail/match-vec-fixed.rs
@@ -0,0 +1,16 @@
+fn a() {
+    let v = [1, 2, 3];
+    match v {
+        [_, _, _] => {}
+        [_, _, _] => {} //~ ERROR unreachable pattern
+    }
+    match v {
+        [_, 1, _] => {}
+        [_, 1, _] => {} //~ ERROR unreachable pattern
+        _ => {}
+    }
+}
+
+fn main() {
+    a();
+}
diff --git a/src/test/compile-fail/match-vec-unreachable.rs b/src/test/compile-fail/match-vec-unreachable.rs
index 3930e7d2192..b557242af44 100644
--- a/src/test/compile-fail/match-vec-unreachable.rs
+++ b/src/test/compile-fail/match-vec-unreachable.rs
@@ -6,13 +6,13 @@ fn main() {
         _ => ()
     }
 
-    match [~"foo", ~"bar", ~"baz"] {
+    match ~[~"foo", ~"bar", ~"baz"] {
         [a, _, _, .._] => { println(a); }
         [~"foo", ~"bar", ~"baz", ~"foo", ~"bar"] => { } //~ ERROR unreachable pattern
         _ => { }
     }
 
-    match ['a', 'b', 'c'] {
+    match ~['a', 'b', 'c'] {
         ['a', 'b', 'c', .._tail] => {}
         ['a', 'b', 'c'] => {} //~ ERROR unreachable pattern
         _ => {}
diff --git a/src/test/compile-fail/xc-private-method.rs b/src/test/compile-fail/xc-private-method.rs
index e8777a0a9f2..8314755af3b 100644
--- a/src/test/compile-fail/xc-private-method.rs
+++ b/src/test/compile-fail/xc-private-method.rs
@@ -4,5 +4,13 @@
 extern mod xc_private_method_lib;
 
 fn main() {
-    let _ = xc_private_method_lib::Foo::new();  //~ ERROR function `new` is private
+    // normal method on struct
+    let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct();  //~ ERROR method `meth_struct` is private
+    // static method on struct
+    let _ = xc_private_method_lib::Struct::static_meth_struct();  //~ ERROR function `static_meth_struct` is private
+
+    // normal method on enum
+    let _ = xc_private_method_lib::Variant1(20).meth_enum();  //~ ERROR method `meth_enum` is private
+    // static method on enum
+    let _ = xc_private_method_lib::Enum::static_meth_enum();  //~ ERROR function `static_meth_enum` is private
 }
diff --git a/src/test/run-pass/issue-3121.rs b/src/test/run-pass/issue-3121.rs
index 522a68856b6..206dc383cb3 100644
--- a/src/test/run-pass/issue-3121.rs
+++ b/src/test/run-pass/issue-3121.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-test
 enum side { mayo, catsup, vinegar }
 enum order { hamburger, fries(side), shake }
 enum meal { to_go(order), for_here(order) }
diff --git a/src/test/run-pass/vec-matching-autoslice.rs b/src/test/run-pass/vec-matching-autoslice.rs
index d04deeac52e..13a8e324d43 100644
--- a/src/test/run-pass/vec-matching-autoslice.rs
+++ b/src/test/run-pass/vec-matching-autoslice.rs
@@ -1,22 +1,22 @@
 pub fn main() {
     let x = @[1, 2, 3];
     match x {
-        [2, .._] => ::std::util::unreachable(),
+        [2, .._] => fail!(),
         [1, ..tail] => {
             assert_eq!(tail, [2, 3]);
         }
-        [_] => ::std::util::unreachable(),
-        [] => ::std::util::unreachable()
+        [_] => fail!(),
+        [] => fail!()
     }
 
     let y = (~[(1, true), (2, false)], 0.5);
     match y {
-        ([_, _, _], 0.5) => ::std::util::unreachable(),
+        ([_, _, _], 0.5) => fail!(),
         ([(1, a), (b, false), ..tail], _) => {
             assert_eq!(a, true);
             assert_eq!(b, 2);
             assert!(tail.is_empty());
         }
-        ([..tail], _) => ::std::util::unreachable()
+        ([..tail], _) => fail!()
     }
 }
diff --git a/src/test/run-pass/vec-matching-fixed.rs b/src/test/run-pass/vec-matching-fixed.rs
new file mode 100644
index 00000000000..234311dec33
--- /dev/null
+++ b/src/test/run-pass/vec-matching-fixed.rs
@@ -0,0 +1,28 @@
+fn a() {
+    let x = [1, 2, 3];
+    match x {
+        [1, 2, 4] => ::std::util::unreachable(),
+        [0, 2, 3, .._] => ::std::util::unreachable(),
+        [0, .._, 3] => ::std::util::unreachable(),
+        [0, .._] => ::std::util::unreachable(),
+        [1, 2, 3] => (),
+        [_, _, _] => ::std::util::unreachable(),
+    }
+    match x {
+        [.._] => (),
+    }
+    match x {
+        [_, _, _, .._] => (),
+    }
+    match x {
+        [a, b, c] => {
+            assert_eq!(1, a);
+            assert_eq!(2, b);
+            assert_eq!(3, c);
+        }
+    }
+}
+
+pub fn main() {
+    a();
+}
diff --git a/src/test/run-pass/vec-matching.rs b/src/test/run-pass/vec-matching.rs
index 5e906fa2659..c09fb8d6bc7 100644
--- a/src/test/run-pass/vec-matching.rs
+++ b/src/test/run-pass/vec-matching.rs
@@ -1,19 +1,19 @@
 fn a() {
-    let x = [1];
+    let x = ~[1];
     match x {
-        [_, _, _, _, _, .._] => ::std::util::unreachable(),
-        [.._, _, _, _, _] => ::std::util::unreachable(),
-        [_, .._, _, _] => ::std::util::unreachable(),
-        [_, _] => ::std::util::unreachable(),
+        [_, _, _, _, _, .._] => fail!(),
+        [.._, _, _, _, _] => fail!(),
+        [_, .._, _, _] => fail!(),
+        [_, _] => fail!(),
         [a] => {
             assert_eq!(a, 1);
         }
-        [] => ::std::util::unreachable()
+        [] => fail!()
     }
 }
 
 fn b() {
-    let x = [1, 2, 3];
+    let x = ~[1, 2, 3];
     match x {
         [a, b, ..c] => {
             assert_eq!(a, 1);
@@ -48,7 +48,28 @@ fn b() {
     }
 }
 
+fn c() {
+    let x = [1];
+    match x {
+        [2, .. _] => fail!(),
+        [.. _] => ()
+    }
+}
+
+fn d() {
+    let x = [1, 2, 3];
+    let branch = match x {
+        [1, 1, .. _] => 0,
+        [1, 2, 3, .. _] => 1,
+        [1, 2, .. _] => 2,
+        _ => 3
+    };
+    assert_eq!(branch, 1);
+}
+
 pub fn main() {
     a();
     b();
+    c();
+    d();
 }
diff --git a/src/test/run-pass/vec-tail-matching.rs b/src/test/run-pass/vec-tail-matching.rs
index 27f4fc83351..6a60308f2e7 100644
--- a/src/test/run-pass/vec-tail-matching.rs
+++ b/src/test/run-pass/vec-tail-matching.rs
@@ -3,7 +3,7 @@ struct Foo {
 }
 
 pub fn main() {
-    let x = [
+    let x = ~[
         Foo { string: ~"foo" },
         Foo { string: ~"bar" },
         Foo { string: ~"baz" }