about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-08-14 15:27:06 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-08-15 16:20:31 -0700
commitfe9d07dda6e884df9873376c85941cc766dbd1dc (patch)
tree426406223615438c3ea72db0fe7130dfb9ded1d8
parentfd0f616ceb17ac283717322674e35b7589a27232 (diff)
downloadrust-fe9d07dda6e884df9873376c85941cc766dbd1dc.tar.gz
rust-fe9d07dda6e884df9873376c85941cc766dbd1dc.zip
rustc: "as Trait" can now be written "as @Trait".
There is also code for ~Trait and &Trait, but these are currently (incorrectly)
synonyms for "as @Trait" and "as &Trait".
-rw-r--r--src/fuzzer/fuzzer.rs6
-rw-r--r--src/libsyntax/ext/tt/earley_parser.rs4
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs6
-rw-r--r--src/libsyntax/parse.rs6
-rw-r--r--src/libsyntax/parse/comments.rs4
-rw-r--r--src/libsyntax/parse/common.rs2
-rw-r--r--src/libsyntax/parse/lexer.rs26
-rw-r--r--src/libsyntax/parse/parser.rs2
-rw-r--r--src/libsyntax/print/pprust.rs14
-rw-r--r--src/rustc/metadata/tydecode.rs3
-rw-r--r--src/rustc/metadata/tyencode.rs3
-rw-r--r--src/rustc/middle/kind.rs2
-rw-r--r--src/rustc/middle/trans/base.rs8
-rw-r--r--src/rustc/middle/trans/reflect.rs2
-rw-r--r--src/rustc/middle/trans/shape.rs2
-rw-r--r--src/rustc/middle/trans/type_of.rs2
-rw-r--r--src/rustc/middle/trans/type_use.rs2
-rw-r--r--src/rustc/middle/ty.rs38
-rw-r--r--src/rustc/middle/typeck/astconv.rs19
-rw-r--r--src/rustc/middle/typeck/check/method.rs4
-rw-r--r--src/rustc/middle/typeck/check/regionck.rs2
-rw-r--r--src/rustc/middle/typeck/check/vtable.rs14
-rw-r--r--src/rustc/middle/typeck/coherence.rs4
-rw-r--r--src/rustc/middle/typeck/collect.rs5
-rw-r--r--src/rustc/middle/typeck/infer.rs8
-rw-r--r--src/rustc/util/ppaux.rs5
-rw-r--r--src/test/run-pass/boxed-trait-with-vstore.rs15
27 files changed, 125 insertions, 83 deletions
diff --git a/src/fuzzer/fuzzer.rs b/src/fuzzer/fuzzer.rs
index 352831c86e6..c6dde67dd75 100644
--- a/src/fuzzer/fuzzer.rs
+++ b/src/fuzzer/fuzzer.rs
@@ -264,7 +264,7 @@ fn check_variants_T<T: copy>(
                     @as_str(|a|pprust::print_crate(
                         codemap,
                         // Assuming we're not generating any token_trees
-                        @syntax::util::interner::mk::<@~str>(
+                        syntax::util::interner::mk::<@~str>(
                             |x| str::hash(*x), |x,y| str::eq(*x,*y)),
                         diagnostic::mk_span_handler(handler, codemap),
                         crate2,
@@ -427,7 +427,7 @@ fn parse_and_print(code: @~str) -> ~str {
                pprust::print_crate(
                    sess.cm,
                    // Assuming there are no token_trees
-                   @syntax::util::interner::mk::<@~str>(
+                   syntax::util::interner::mk::<@~str>(
                        |x| str::hash(*x), |x,y| str::eq(*x,*y)),
                    sess.span_diagnostic,
                    crate,
@@ -576,7 +576,7 @@ fn check_variants(files: ~[~str], cx: context) {
                    as_str(|a| pprust::print_crate(
                        sess.cm,
                        // Assuming no token_trees
-                       @syntax::util::interner::mk::<@~str>(
+                       syntax::util::interner::mk::<@~str>(
                             |x| str::hash(*x), |x,y| str::eq(*x,*y)),
                        sess.span_diagnostic,
                        crate,
diff --git a/src/libsyntax/ext/tt/earley_parser.rs b/src/libsyntax/ext/tt/earley_parser.rs
index b6dc1c05a2c..77ba941015b 100644
--- a/src/libsyntax/ext/tt/earley_parser.rs
+++ b/src/libsyntax/ext/tt/earley_parser.rs
@@ -284,7 +284,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher])
                     nts, next_eis.len()});
             } else if (bb_eis.len() == 0u && next_eis.len() == 0u) {
                 return failure(sp, ~"No rules expected the token "
-                            + to_str(*rdr.interner(), tok));
+                            + to_str(rdr.interner(), tok));
             } else if (next_eis.len() > 0u) {
                 /* Now process the next token */
                 while(next_eis.len() > 0u) {
@@ -334,7 +334,7 @@ fn parse_nt(p: parser, name: ~str) -> nonterminal {
       ~"ident" => match copy p.token {
         token::IDENT(sn,b) => { p.bump(); token::nt_ident(sn,b) }
         _ => p.fatal(~"expected ident, found "
-                     + token::to_str(*p.reader.interner(), copy p.token))
+                     + token::to_str(p.reader.interner(), copy p.token))
       },
       ~"path" => token::nt_path(p.parse_path_with_tps(false)),
       ~"tt" => {
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index 693b538ec6d..8acf0e8ec6d 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -25,7 +25,7 @@ type tt_frame = @{
 
 type tt_reader = @{
     sp_diag: span_handler,
-    interner: @interner<@~str>,
+    interner: interner<@~str>,
     mut cur: tt_frame,
     /* for MBE-style macro transcription */
     interpolations: std::map::hashmap<ident, @named_match>,
@@ -39,7 +39,7 @@ type tt_reader = @{
 /** This can do Macro-By-Example transcription. On the other hand, if
  *  `src` contains no `tt_seq`s and `tt_nonterminal`s, `interp` can (and
  *  should) be none. */
-fn new_tt_reader(sp_diag: span_handler, itr: @interner<@~str>,
+fn new_tt_reader(sp_diag: span_handler, itr: interner<@~str>,
                  interp: option<std::map::hashmap<ident,@named_match>>,
                  src: ~[ast::token_tree])
     -> tt_reader {
@@ -237,4 +237,4 @@ fn tt_next_token(&&r: tt_reader) -> {tok: token, sp: span} {
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/src/libsyntax/parse.rs b/src/libsyntax/parse.rs
index 6936eeed8f9..deaaaf69b1c 100644
--- a/src/libsyntax/parse.rs
+++ b/src/libsyntax/parse.rs
@@ -24,7 +24,7 @@ type parse_sess = @{
     cm: codemap::codemap,
     mut next_id: node_id,
     span_diagnostic: span_handler,
-    interner: @interner::interner<@~str>,
+    interner: interner::interner<@~str>,
     // these two must be kept up to date
     mut chpos: uint,
     mut byte_pos: uint
@@ -35,7 +35,7 @@ fn new_parse_sess(demitter: option<emitter>) -> parse_sess {
     return @{cm: cm,
           mut next_id: 1,
           span_diagnostic: mk_span_handler(mk_handler(demitter), cm),
-          interner: @interner::mk::<@~str>(|x| str::hash(*x),
+          interner: interner::mk::<@~str>(|x| str::hash(*x),
                                           |x,y| str::eq(*x, *y)),
           mut chpos: 0u, mut byte_pos: 0u};
 }
@@ -45,7 +45,7 @@ fn new_parse_sess_special_handler(sh: span_handler, cm: codemap::codemap)
     return @{cm: cm,
           mut next_id: 1,
           span_diagnostic: sh,
-          interner: @interner::mk::<@~str>(|x| str::hash(*x),
+          interner: interner::mk::<@~str>(|x| str::hash(*x),
                                           |x,y| str::eq(*x, *y)),
           mut chpos: 0u, mut byte_pos: 0u};
 }
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs
index 2da34539321..701dd9301ca 100644
--- a/src/libsyntax/parse/comments.rs
+++ b/src/libsyntax/parse/comments.rs
@@ -276,7 +276,7 @@ fn gather_comments_and_literals(span_diagnostic: diagnostic::span_handler,
                                 srdr: io::Reader) ->
    {cmnts: ~[cmnt], lits: ~[lit]} {
     let src = @str::from_bytes(srdr.read_whole_stream());
-    let itr = @interner::mk::<@~str>(
+    let itr = interner::mk::<@~str>(
         |x| str::hash(*x),
         |x,y| str::eq(*x, *y)
     );
@@ -311,7 +311,7 @@ fn gather_comments_and_literals(span_diagnostic: diagnostic::span_handler,
             vec::push(literals, {lit: s, pos: sp.lo});
             log(debug, ~"tok lit: " + s);
         } else {
-            log(debug, ~"tok: " + token::to_str(*rdr.interner, tok));
+            log(debug, ~"tok: " + token::to_str(rdr.interner, tok));
         }
         first_read = false;
     }
diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs
index 4038578d3f8..59dad16dc44 100644
--- a/src/libsyntax/parse/common.rs
+++ b/src/libsyntax/parse/common.rs
@@ -19,7 +19,7 @@ fn seq_sep_none() -> seq_sep {
 }
 
 fn token_to_str(reader: reader, ++token: token::token) -> ~str {
-    token::to_str(*reader.interner(), token)
+    token::to_str(reader.interner(), token)
 }
 
 trait parser_common {
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index 99768d558ab..aaafe958efb 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -14,7 +14,7 @@ trait reader {
     fn next_token() -> {tok: token::token, sp: span};
     fn fatal(~str) -> !;
     fn span_diag() -> span_handler;
-    pure fn interner() -> @interner<@~str>;
+    pure fn interner() -> interner<@~str>;
     fn peek() -> {tok: token::token, sp: span};
     fn dup() -> reader;
 }
@@ -27,7 +27,7 @@ type string_reader = @{
     mut curr: char,
     mut chpos: uint,
     filemap: codemap::filemap,
-    interner: @interner<@~str>,
+    interner: interner<@~str>,
     /* cached: */
     mut peek_tok: token::token,
     mut peek_span: span
@@ -35,7 +35,7 @@ type string_reader = @{
 
 fn new_string_reader(span_diagnostic: span_handler,
                      filemap: codemap::filemap,
-                     itr: @interner<@~str>) -> string_reader {
+                     itr: interner<@~str>) -> string_reader {
     let r = new_low_level_string_reader(span_diagnostic, filemap, itr);
     string_advance_token(r); /* fill in peek_* */
     return r;
@@ -44,7 +44,7 @@ fn new_string_reader(span_diagnostic: span_handler,
 /* For comments.rs, which hackily pokes into 'pos' and 'curr' */
 fn new_low_level_string_reader(span_diagnostic: span_handler,
                                filemap: codemap::filemap,
-                               itr: @interner<@~str>)
+                               itr: interner<@~str>)
     -> string_reader {
     let r = @{span_diagnostic: span_diagnostic, src: filemap.src,
               mut col: 0u, mut pos: 0u, mut curr: -1 as char,
@@ -79,7 +79,7 @@ impl string_reader: reader {
         self.span_diagnostic.span_fatal(copy self.peek_span, m)
     }
     fn span_diag() -> span_handler { self.span_diagnostic }
-    pure fn interner() -> @interner<@~str> { self.interner }
+    pure fn interner() -> interner<@~str> { self.interner }
     fn peek() -> {tok: token::token, sp: span} {
         {tok: self.peek_tok, sp: self.peek_span}
     }
@@ -101,7 +101,7 @@ impl tt_reader: reader {
         self.sp_diag.span_fatal(copy self.cur_span, m);
     }
     fn span_diag() -> span_handler { self.sp_diag }
-    pure fn interner() -> @interner<@~str> { self.interner }
+    pure fn interner() -> interner<@~str> { self.interner }
     fn peek() -> {tok: token::token, sp: span} {
         { tok: self.cur_tok, sp: self.cur_span }
     }
@@ -219,7 +219,7 @@ fn consume_any_line_comment(rdr: string_reader)
                     bump(rdr);
                 }
                 return some({
-                    tok: token::DOC_COMMENT((*rdr.interner).intern(@acc)),
+                    tok: token::DOC_COMMENT(rdr.interner.intern(@acc)),
                     sp: ast_util::mk_sp(start_chpos, rdr.chpos)
                 });
             } else {
@@ -264,7 +264,7 @@ fn consume_block_comment(rdr: string_reader)
             bump(rdr);
             bump(rdr);
             return some({
-                tok: token::DOC_COMMENT((*rdr.interner).intern(@acc)),
+                tok: token::DOC_COMMENT(rdr.interner.intern(@acc)),
                 sp: ast_util::mk_sp(start_chpos, rdr.chpos)
             });
         }
@@ -398,12 +398,12 @@ fn scan_number(c: char, rdr: string_reader) -> token::token {
         if c == '3' && n == '2' {
             bump(rdr);
             bump(rdr);
-            return token::LIT_FLOAT((*rdr.interner).intern(@num_str),
+            return token::LIT_FLOAT(rdr.interner.intern(@num_str),
                                  ast::ty_f32);
         } else if c == '6' && n == '4' {
             bump(rdr);
             bump(rdr);
-            return token::LIT_FLOAT((*rdr.interner).intern(@num_str),
+            return token::LIT_FLOAT(rdr.interner.intern(@num_str),
                                  ast::ty_f64);
             /* FIXME (#2252): if this is out of range for either a
             32-bit or 64-bit float, it won't be noticed till the
@@ -413,7 +413,7 @@ fn scan_number(c: char, rdr: string_reader) -> token::token {
         }
     }
     if is_float {
-        return token::LIT_FLOAT((*rdr.interner).intern(@num_str), ast::ty_f);
+        return token::LIT_FLOAT(rdr.interner.intern(@num_str), ast::ty_f);
     } else {
         if str::len(num_str) == 0u {
             rdr.fatal(~"no valid digits found for number");
@@ -461,7 +461,7 @@ fn next_token_inner(rdr: string_reader) -> token::token {
         let is_mod_name = c == ':' && nextch(rdr) == ':';
 
         // FIXME: perform NFKC normalization here. (Issue #2253)
-        return token::IDENT((*rdr.interner).intern(@accum_str), is_mod_name);
+        return token::IDENT(rdr.interner.intern(@accum_str), is_mod_name);
     }
     if is_dec_digit(c) {
         return scan_number(c, rdr);
@@ -630,7 +630,7 @@ fn next_token_inner(rdr: string_reader) -> token::token {
             }
         }
         bump(rdr);
-        return token::LIT_STR((*rdr.interner).intern(@accum_str));
+        return token::LIT_STR(rdr.interner.intern(@accum_str));
       }
       '-' => {
         if nextch(rdr) == '>' {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index f894f6fae82..642cdaa8fab 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -263,7 +263,7 @@ class parser {
         self.sess.span_diagnostic.span_warn(copy self.span, m)
     }
     pure fn get_str(i: token::str_num) -> @~str {
-        (*self.reader.interner()).get(i)
+        self.reader.interner().get(i)
     }
     fn get_id() -> node_id { next_node_id(self.sess) }
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index de1cd2c3df0..39bc18529c9 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -11,7 +11,7 @@ import dvec::{DVec, dvec};
 import parse::classify::*;
 import util::interner;
 
-type ident_interner = @interner::interner<@~str>;
+type ident_interner = interner::interner<@~str>;
 
 // The ps is stored here to prevent recursive type.
 enum ann_node {
@@ -30,7 +30,7 @@ fn no_ann() -> pp_ann {
 type ps =
     @{s: pp::printer,
       cm: option<codemap>,
-      intr: @interner::interner<@~str>,
+      intr: interner::interner<@~str>,
       comments: option<~[comments::cmnt]>,
       literals: option<~[comments::lit]>,
       mut cur_cmnt: uint,
@@ -51,8 +51,8 @@ fn end(s: ps) {
 fn rust_printer(writer: io::Writer) -> ps {
     return @{s: pp::mk_printer(writer, default_columns),
              cm: none::<codemap>,
-             intr: @interner::mk::<@~str>(|x| str::hash(*x),
-                                          |x,y| str::eq(*x, *y)),
+             intr: interner::mk::<@~str>(|x| str::hash(*x),
+                                         |x,y| str::eq(*x, *y)),
              comments: none::<~[comments::cmnt]>,
              literals: none::<~[comments::lit]>,
              mut cur_cmnt: 0u,
@@ -81,7 +81,7 @@ const default_columns: uint = 78u;
 // Requires you to pass an input filename and reader so that
 // it can scan the input text for comments and literals to
 // copy forward.
-fn print_crate(cm: codemap, intr: @interner::interner<@~str>,
+fn print_crate(cm: codemap, intr: interner::interner<@~str>,
                span_diagnostic: diagnostic::span_handler,
                crate: @ast::crate, filename: ~str, in: io::Reader,
                out: io::Writer, ann: pp_ann, is_expanded: bool) {
@@ -690,14 +690,14 @@ fn print_tt(s: ps, tt: ast::token_tree) {
           }
           _ => { s.s.token_tree_last_was_ident = false; }
         }
-        word(s.s, parse::token::to_str(*s.intr, tk));
+        word(s.s, parse::token::to_str(s.intr, tk));
       }
       ast::tt_seq(_, tts, sep, zerok) => {
         word(s.s, ~"$(");
         for tts.each() |tt_elt| { print_tt(s, tt_elt); }
         word(s.s, ~")");
         match sep {
-          some(tk) => word(s.s, parse::token::to_str(*s.intr, tk)),
+          some(tk) => word(s.s, parse::token::to_str(s.intr, tk)),
           none => ()
         }
         word(s.s, if zerok { ~"*" } else { ~"+" });
diff --git a/src/rustc/metadata/tydecode.rs b/src/rustc/metadata/tydecode.rs
index 80c64430ec3..90be808b229 100644
--- a/src/rustc/metadata/tydecode.rs
+++ b/src/rustc/metadata/tydecode.rs
@@ -212,8 +212,9 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
         assert next(st) == '[';
         let def = parse_def(st, conv);
         let substs = parse_substs(st, conv);
+        let vstore = parse_vstore(st);
         assert next(st) == ']';
-        return ty::mk_trait(st.tcx, def, substs);
+        return ty::mk_trait(st.tcx, def, substs, vstore);
       }
       'p' => {
         let did = parse_def(st, conv);
diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs
index f26ccff1806..5a24b9af8d9 100644
--- a/src/rustc/metadata/tyencode.rs
+++ b/src/rustc/metadata/tyencode.rs
@@ -227,11 +227,12 @@ fn enc_sty(w: io::Writer, cx: @ctxt, st: ty::sty) {
         enc_substs(w, cx, substs);
         w.write_char(']');
       }
-      ty::ty_trait(def, substs) => {
+      ty::ty_trait(def, substs, vstore) => {
         w.write_str(&"x[");
         w.write_str(cx.ds(def));
         w.write_char('|');
         enc_substs(w, cx, substs);
+        enc_vstore(w, cx, vstore);
         w.write_char(']');
       }
       ty::ty_tup(ts) => {
diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs
index 9968318292c..e960e21c752 100644
--- a/src/rustc/middle/kind.rs
+++ b/src/rustc/middle/kind.rs
@@ -498,7 +498,7 @@ fn check_cast_for_escaping_regions(
     // worries.
     let target_ty = ty::expr_ty(cx.tcx, target);
     let target_substs = match ty::get(target_ty).struct {
-      ty::ty_trait(_, substs) => {substs}
+      ty::ty_trait(_, substs, _) => {substs}
       _ => { return; /* not a cast to a trait */ }
     };
 
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 23f5c69caa1..83bdb941f46 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -668,7 +668,7 @@ fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
       ty::ty_fn(_) => {
         closure::make_fn_glue(bcx, v, t, take_ty)
       }
-      ty::ty_trait(_, _) => {
+      ty::ty_trait(_, _, _) => {
         let llbox = Load(bcx, GEPi(bcx, v, ~[0u, 1u]));
         incr_refcnt_of_boxed(bcx, llbox);
         bcx
@@ -819,7 +819,7 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
       ty::ty_fn(_) => {
         closure::make_fn_glue(bcx, v0, t, drop_ty)
       }
-      ty::ty_trait(_, _) => {
+      ty::ty_trait(_, _, _) => {
         let llbox = Load(bcx, GEPi(bcx, v0, ~[0u, 1u]));
         decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx))
       }
@@ -2041,7 +2041,7 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> option<ty::t> {
                              output: ty::mk_nil(tcx),
                              ret_style: ast::return_val}))
       }
-      ty::ty_trait(_, _) => {
+      ty::ty_trait(_, _, _) => {
         some(ty::mk_fn(tcx, {purity: ast::impure_fn,
                              proto: ty::proto_vstore(ty::vstore_box),
                              bounds: @~[],
@@ -2819,7 +2819,7 @@ fn trans_cast(cx: block, e: @ast::expr, id: ast::node_id,
     let ccx = cx.ccx();
     let t_out = node_id_type(cx, id);
     match ty::get(t_out).struct {
-      ty::ty_trait(_, _) => return impl::trans_cast(cx, e, id, dest),
+      ty::ty_trait(_, _, _) => return impl::trans_cast(cx, e, id, dest),
       _ => ()
     }
     let e_res = trans_temp_expr(cx, e);
diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs
index ccb3bf3429b..5829041a54a 100644
--- a/src/rustc/middle/trans/reflect.rs
+++ b/src/rustc/middle/trans/reflect.rs
@@ -268,7 +268,7 @@ impl reflector {
           }
 
           // Miscallaneous extra types
-          ty::ty_trait(_, _) => self.leaf(~"trait"),
+          ty::ty_trait(_, _, _) => self.leaf(~"trait"),
           ty::ty_var(_) => self.leaf(~"var"),
           ty::ty_var_integral(_) => self.leaf(~"var_integral"),
           ty::ty_param(p) => self.visit(~"param", ~[self.c_uint(p.idx)]),
diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs
index 78eb527b785..5209b6f61f0 100644
--- a/src/rustc/middle/trans/shape.rs
+++ b/src/rustc/middle/trans/shape.rs
@@ -323,7 +323,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> ~[u8] {
         add_substr(s, sub);
         s
       }
-      ty::ty_trait(_, _) => ~[shape_box_fn],
+      ty::ty_trait(_, _, _) => ~[shape_box_fn],
       ty::ty_class(did, ref substs) => {
         // same as records, unless there's a dtor
         let tps = substs.tps;
diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs
index d06862262f2..f48fa782683 100644
--- a/src/rustc/middle/trans/type_of.rs
+++ b/src/rustc/middle/trans/type_of.rs
@@ -147,7 +147,7 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
         T_struct(tys)
       }
       ty::ty_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
-      ty::ty_trait(_, _) => T_opaque_trait(cx),
+      ty::ty_trait(_, _, _) => T_opaque_trait(cx),
       ty::ty_type => T_ptr(cx.tydesc_type),
       ty::ty_tup(elts) => {
         let mut tys = ~[];
diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs
index d630653ef27..880c6c546f2 100644
--- a/src/rustc/middle/trans/type_use.rs
+++ b/src/rustc/middle/trans/type_use.rs
@@ -134,7 +134,7 @@ fn type_needs_inner(cx: ctx, use: uint, ty: ty::t,
                  right tydesc into the result)
                  */
               ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _)
-               | ty::ty_trait(_, _) => false,
+               | ty::ty_trait(_, _, _) => false,
               ty::ty_enum(did, substs) => {
                 if option::is_none(list::find(enums_seen, |id| id == did)) {
                     let seen = @cons(did, enums_seen);
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index 2d85a0fd296..72cfbca1af0 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -172,7 +172,7 @@ export terr_regions_does_not_outlive, terr_mutability, terr_purity_mismatch;
 export terr_regions_not_same, terr_regions_no_overlap;
 export terr_proto_mismatch;
 export terr_ret_style_mismatch;
-export terr_fn;
+export terr_fn, terr_trait;
 export purity_to_str;
 export param_tys_in_type;
 export eval_repeat_count;
@@ -434,7 +434,7 @@ enum sty {
     ty_rptr(region, mt),
     ty_rec(~[field]),
     ty_fn(fn_ty),
-    ty_trait(def_id, substs),
+    ty_trait(def_id, substs, vstore),
     ty_class(def_id, substs),
     ty_tup(~[t]),
 
@@ -452,7 +452,7 @@ enum sty {
 }
 
 enum terr_vstore_kind {
-    terr_vec, terr_str, terr_fn
+    terr_vec, terr_str, terr_fn, terr_trait
 }
 
 // Data structures used in type unification
@@ -670,7 +670,7 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: option<ast::def_id>) -> t {
       ty_var(_) | ty_var_integral(_) => flags |= needs_infer as uint,
       ty_self => flags |= has_self as uint,
       ty_enum(_, ref substs) | ty_class(_, ref substs)
-      | ty_trait(_, ref substs) => {
+      | ty_trait(_, ref substs, _) => {
         flags |= sflags(substs);
       }
       ty_box(m) | ty_uniq(m) | ty_evec(m, _) |
@@ -787,9 +787,10 @@ fn mk_tup(cx: ctxt, ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) }
 // take a copy because we want to own the various vectors inside
 fn mk_fn(cx: ctxt, +fty: fn_ty) -> t { mk_t(cx, ty_fn(fty)) }
 
-fn mk_trait(cx: ctxt, did: ast::def_id, +substs: substs) -> t {
+fn mk_trait(cx: ctxt, did: ast::def_id, +substs: substs, vstore: vstore)
+         -> t {
     // take a copy of substs so that we own the vectors inside
-    mk_t(cx, ty_trait(did, substs))
+    mk_t(cx, ty_trait(did, substs, vstore))
 }
 
 fn mk_class(cx: ctxt, class_id: ast::def_id, +substs: substs) -> t {
@@ -862,7 +863,7 @@ fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
         maybe_walk_ty(tm.ty, f);
       }
       ty_enum(_, substs) | ty_class(_, substs) |
-      ty_trait(_, substs) => {
+      ty_trait(_, substs, _) => {
         for substs.tps.each |subty| { maybe_walk_ty(subty, f); }
       }
       ty_rec(fields) => {
@@ -907,8 +908,8 @@ fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty {
       ty_enum(tid, ref substs) => {
         ty_enum(tid, fold_substs(substs, fldop))
       }
-      ty_trait(did, ref substs) => {
-        ty_trait(did, fold_substs(substs, fldop))
+      ty_trait(did, ref substs, vst) => {
+        ty_trait(did, fold_substs(substs, fldop), vst)
       }
       ty_rec(fields) => {
         let new_fields = do vec::map(fields) |fl| {
@@ -1005,8 +1006,8 @@ fn fold_regions_and_ty(
       ty_class(def_id, ref substs) => {
         ty::mk_class(cx, def_id, fold_substs(substs, fldr, fldt))
       }
-      ty_trait(def_id, ref substs) => {
-        ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt))
+      ty_trait(def_id, ref substs, vst) => {
+        ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst)
       }
       ref sty @ ty_fn(f) => {
         let new_proto;
@@ -1664,7 +1665,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
       }
 
       // Trait instances are (for now) like shared boxes, basically
-      ty_trait(_, _) => kind_safe_for_default_mode() | kind_owned(),
+      ty_trait(_, _, _) => kind_safe_for_default_mode() | kind_owned(),
 
       // Region pointers are copyable but NOT owned nor sendable
       ty_rptr(_, _) => kind_safe_for_default_mode(),
@@ -1911,7 +1912,7 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
             }
           }
 
-          ty_trait(_, _) => {
+          ty_trait(_, _, _) => {
             false
           }
 
@@ -2053,7 +2054,7 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
       ty_box(_) | ty_uniq(_) | ty_fn(_) |
       ty_estr(vstore_uniq) | ty_estr(vstore_box) |
       ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
-      ty_trait(_, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
+      ty_trait(_, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
       // Structural types
       ty_enum(did, ref substs) => {
         let variants = enum_variants(cx, did);
@@ -2273,7 +2274,7 @@ pure fn hash_type_structure(st: &sty) -> uint {
       ty_bot => 34u,
       ty_ptr(mt) => hash_subty(35u, mt.ty),
       ty_uniq(mt) => hash_subty(37u, mt.ty),
-      ty_trait(did, ref substs) => {
+      ty_trait(did, ref substs, _) => {
         let mut h = hash_def(40u, did);
         hash_substs(h, substs)
       }
@@ -2590,7 +2591,7 @@ fn ty_sort_str(cx: ctxt, t: t) -> ~str {
       ty_rptr(_, _) => ~"&-ptr",
       ty_rec(_) => ~"record",
       ty_fn(_) => ~"fn",
-      ty_trait(id, _) => fmt!{"trait %s", item_path_str(cx, id)},
+      ty_trait(id, _, _) => fmt!{"trait %s", item_path_str(cx, id)},
       ty_class(id, _) => fmt!{"class %s", item_path_str(cx, id)},
       ty_tup(_) => ~"tuple",
       ty_var(_) => ~"variable",
@@ -2605,7 +2606,8 @@ fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
         match k {
             terr_vec => ~"[]",
             terr_str => ~"str",
-            terr_fn => ~"fn"
+            terr_fn => ~"fn",
+            terr_trait => ~"trait"
         }
     }
 
@@ -2769,7 +2771,7 @@ fn impl_traits(cx: ctxt, id: ast::def_id) -> ~[t] {
 
 fn ty_to_def_id(ty: t) -> option<ast::def_id> {
     match get(ty).struct {
-      ty_trait(id, _) | ty_class(id, _) | ty_enum(id, _) => some(id),
+      ty_trait(id, _, _) | ty_class(id, _) | ty_enum(id, _) => some(id),
       _ => none
     }
 }
diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs
index 9a1eba46f2e..64d4cdbd979 100644
--- a/src/rustc/middle/typeck/astconv.rs
+++ b/src/rustc/middle/typeck/astconv.rs
@@ -162,7 +162,7 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy owned>(
 
     // Handle @, ~, and & being able to mean estrs and evecs.
     // If a_seq_ty is a str or a vec, make it an estr/evec.
-    // Also handle function sigils.
+    // Also handle function sigils and first-class trait types.
     fn mk_maybe_vstore<AC: ast_conv, RS: region_scope copy owned>(
         self: AC, rscope: RS, a_seq_ty: ast::mt, vst: ty::vstore,
         span: span, constr: fn(ty::mt) -> ty::t) -> ty::t {
@@ -181,6 +181,23 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy owned>(
                 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
                 return ty::mk_estr(tcx, vst);
               }
+              some(ast::def_ty(type_def_id)) => {
+                let result = ast_path_to_substs_and_ty(self, rscope,
+                                                       type_def_id, path);
+                match ty::get(result.ty).struct {
+                    ty::ty_trait(trait_def_id, substs, _) => {
+                        if vst != ty::vstore_box {
+                            tcx.sess.span_unimpl(path.span,
+                                                 ~"`~trait` and `&trait` are \
+                                                   unimplemented; use \
+                                                   `@trait` instead for now");
+                        }
+                        return ty::mk_trait(tcx, trait_def_id, substs, vst);
+                    }
+                    _ =>
+                        {}
+                }
+              }
               _ => ()
             }
           }
diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs
index 9de5aa98e5f..3bb0e566dc6 100644
--- a/src/rustc/middle/typeck/check/method.rs
+++ b/src/rustc/middle/typeck/check/method.rs
@@ -126,7 +126,7 @@ class lookup {
                 self.add_candidates_from_param(p.idx, p.def_id);
               }
 
-              ty::ty_trait(did, substs) => {
+              ty::ty_trait(did, substs, _) => {
                 self.add_candidates_from_trait(did, substs);
               }
               ty::ty_class(did, substs) => {
@@ -238,7 +238,7 @@ class lookup {
               }
               ty::bound_trait(bound_t) => {
                 match check ty::get(bound_t).struct {
-                  ty::ty_trait(i, substs) => (i, substs)
+                  ty::ty_trait(i, substs, _) => (i, substs)
                 }
               }
             };
diff --git a/src/rustc/middle/typeck/check/regionck.rs b/src/rustc/middle/typeck/check/regionck.rs
index 34a0bfc41a5..c4127eb2e48 100644
--- a/src/rustc/middle/typeck/check/regionck.rs
+++ b/src/rustc/middle/typeck/check/regionck.rs
@@ -158,7 +158,7 @@ fn visit_expr(e: @ast::expr, &&rcx: @rcx, v: rvt) {
           result::err(_) => { return; /* typeck will fail anyhow */ }
           result::ok(target_ty) => {
             match ty::get(target_ty).struct {
-              ty::ty_trait(_, substs) => {
+              ty::ty_trait(_, substs, _) => {
                 let trait_region = match substs.self_r {
                   some(r) => {r}
                   none => {ty::re_static}
diff --git a/src/rustc/middle/typeck/check/vtable.rs b/src/rustc/middle/typeck/check/vtable.rs
index d509b26b841..a0218f3e9b5 100644
--- a/src/rustc/middle/typeck/check/vtable.rs
+++ b/src/rustc/middle/typeck/check/vtable.rs
@@ -37,10 +37,10 @@ fn fixup_substs(fcx: @fn_ctxt, sp: span,
                 id: ast::def_id, substs: ty::substs) -> ty::substs {
     let tcx = fcx.ccx.tcx;
     // use a dummy type just to package up the substs that need fixing up
-    let t = ty::mk_trait(tcx, id, substs);
+    let t = ty::mk_trait(tcx, id, substs, ty::vstore_slice(ty::re_static));
     let t_f = fixup_ty(fcx, sp, t);
     match check ty::get(t_f).struct {
-      ty::ty_trait(_, substs_f) => substs_f,
+      ty::ty_trait(_, substs_f, _) => substs_f,
     }
 }
 
@@ -63,7 +63,7 @@ fn lookup_vtable(fcx: @fn_ctxt, sp: span, ty: ty::t, trait_ty: ty::t,
 
     let tcx = fcx.ccx.tcx;
     let (trait_id, trait_substs) = match check ty::get(trait_ty).struct {
-      ty::ty_trait(did, substs) => (did, substs)
+      ty::ty_trait(did, substs, _) => (did, substs)
     };
     let ty = fixup_ty(fcx, sp, ty);
     match ty::get(ty).struct {
@@ -77,7 +77,7 @@ fn lookup_vtable(fcx: @fn_ctxt, sp: span, ty: ty::t, trait_ty: ty::t,
               }
               ty::bound_trait(ity) => {
                 match check ty::get(ity).struct {
-                  ty::ty_trait(idid, substs) => {
+                  ty::ty_trait(idid, substs, _) => {
                     if trait_id == idid {
                         debug!{"(checking vtable) @0 relating ty to trait ty
                                 with did %?", idid};
@@ -92,7 +92,7 @@ fn lookup_vtable(fcx: @fn_ctxt, sp: span, ty: ty::t, trait_ty: ty::t,
         }
       }
 
-      ty::ty_trait(did, substs) if trait_id == did => {
+      ty::ty_trait(did, substs, _) if trait_id == did => {
         debug!{"(checking vtable) @1 relating ty to trait ty with did %?",
                did};
 
@@ -139,7 +139,7 @@ fn lookup_vtable(fcx: @fn_ctxt, sp: span, ty: ty::t, trait_ty: ty::t,
                     for vec::each(ty::impl_traits(tcx, im.did)) |of_ty| {
                         // it must have the same id as the expected one
                         match ty::get(of_ty).struct {
-                          ty::ty_trait(id, _) if id != trait_id => again,
+                          ty::ty_trait(id, _, _) if id != trait_id => again,
                           _ => { /* ok */ }
                         }
 
@@ -219,7 +219,7 @@ fn connect_trait_tps(fcx: @fn_ctxt, sp: span, impl_tys: ~[ty::t],
     debug!{"(connect trait tps) trait type is %?, impl did is %?",
            ty::get(trait_ty).struct, impl_did};
     match check ty::get(trait_ty).struct {
-      ty::ty_trait(_, substs) => {
+      ty::ty_trait(_, substs, _) => {
         vec::iter2(substs.tps, trait_tys,
                    |a, b| demand::suptype(fcx, sp, a, b));
       }
diff --git a/src/rustc/middle/typeck/coherence.rs b/src/rustc/middle/typeck/coherence.rs
index bc6342dbce1..24e80b13744 100644
--- a/src/rustc/middle/typeck/coherence.rs
+++ b/src/rustc/middle/typeck/coherence.rs
@@ -96,7 +96,7 @@ fn get_base_type_def_id(inference_context: infer_ctxt,
             match get(base_type).struct {
                 ty_enum(def_id, _) |
                 ty_class(def_id, _) |
-                ty_trait(def_id, _) => {
+                ty_trait(def_id, _, _) => {
                     return some(def_id);
                 }
                 _ => {
@@ -735,7 +735,7 @@ class CoherenceChecker {
             // Record all the trait methods.
             for associated_traits.each |trait_type| {
                 match get(trait_type).struct {
-                    ty_trait(trait_id, _) => {
+                    ty_trait(trait_id, _, _) => {
                         self.add_trait_method(trait_id, implementation);
                     }
                     _ => {
diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs
index 12d996777cb..0394813746d 100644
--- a/src/rustc/middle/typeck/collect.rs
+++ b/src/rustc/middle/typeck/collect.rs
@@ -40,7 +40,8 @@ fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) {
 
                     match intrinsic_item.node {
                       ast::item_trait(*) => {
-                        let ty = ty::mk_trait(ccx.tcx, def_id, substs);
+                        let ty = ty::mk_trait(ccx.tcx, def_id, substs,
+                                              ty::vstore_box);
                         ccx.tcx.intrinsic_defs.insert
                             (intrinsic_item.ident, (def_id, ty));
                       }
@@ -648,7 +649,7 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
       }
       ast::item_trait(tps, _, ms) => {
         let {bounds, substs} = mk_substs(ccx, tps, rp);
-        let t = ty::mk_trait(tcx, local_def(it.id), substs);
+        let t = ty::mk_trait(tcx, local_def(it.id), substs, ty::vstore_box);
         let tpt = {bounds: bounds, rp: rp, ty: t};
         tcx.tcache.insert(local_def(it.id), tpt);
         return tpt;
diff --git a/src/rustc/middle/typeck/infer.rs b/src/rustc/middle/typeck/infer.rs
index 36461b44b75..d2f799ff4f7 100644
--- a/src/rustc/middle/typeck/infer.rs
+++ b/src/rustc/middle/typeck/infer.rs
@@ -1902,10 +1902,14 @@ fn super_tys<C:combine>(
         }
       }
 
-      (ty::ty_trait(a_id, ref a_substs), ty::ty_trait(b_id, ref b_substs))
+      (ty::ty_trait(a_id, ref a_substs, a_vstore),
+       ty::ty_trait(b_id, ref b_substs, b_vstore))
       if a_id == b_id => {
         do self.substs(a_substs, b_substs).chain |substs| {
-            ok(ty::mk_trait(tcx, a_id, substs))
+            do self.vstores(ty::terr_trait, a_vstore,
+                            b_vstore).chain |vstores| {
+                ok(ty::mk_trait(tcx, a_id, substs, vstores))
+            }
         }
       }
 
diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs
index d471abbd4b6..a347fdddb79 100644
--- a/src/rustc/util/ppaux.rs
+++ b/src/rustc/util/ppaux.rs
@@ -314,10 +314,11 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str {
         let base = ast_map::path_to_str(path);
         parameterized(cx, base, substs.self_r, substs.tps)
       }
-      ty_trait(did, substs) => {
+      ty_trait(did, substs, vs) => {
         let path = ty::item_path(cx, did);
         let base = ast_map::path_to_str(path);
-        parameterized(cx, base, substs.self_r, substs.tps)
+        let result = parameterized(cx, base, substs.self_r, substs.tps);
+        vstore_ty_to_str(cx, result, vs)
       }
       ty_evec(mt, vs) => {
         vstore_ty_to_str(cx, fmt!{"[%s]", mt_to_str(cx, mt)}, vs)
diff --git a/src/test/run-pass/boxed-trait-with-vstore.rs b/src/test/run-pass/boxed-trait-with-vstore.rs
new file mode 100644
index 00000000000..8e94d222746
--- /dev/null
+++ b/src/test/run-pass/boxed-trait-with-vstore.rs
@@ -0,0 +1,15 @@
+trait Foo {
+    fn foo() {}
+}
+
+impl int : Foo {
+    fn foo() {
+        io::println("Hello world!");
+    }
+}
+
+fn main() {
+    let x = 3 as @Foo;
+    x.foo();
+}
+