about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-08-11 14:17:09 -0700
committerbors <bors@rust-lang.org>2013-08-11 14:17:09 -0700
commitb285f1e6c90332188bb720bf320c507fc4156fdc (patch)
treeb1b5657b028f7a1c5253ae3bc8d87b806e464a6e
parent63c62bea3ac2782ae421d5bd211f2e7393bad7a2 (diff)
parent7343478d67ba3eb0c62dcc37db65d82d12b8e140 (diff)
downloadrust-b285f1e6c90332188bb720bf320c507fc4156fdc.tar.gz
rust-b285f1e6c90332188bb720bf320c507fc4156fdc.zip
auto merge of #8455 : nikomatsakis/rust/issue-5762-objects-dralston-d, r=graydon
Fix #5762 and various other aspects of object invocation.

r? @graydon
-rw-r--r--src/librustc/back/abi.rs3
-rw-r--r--src/librustc/driver/driver.rs2
-rw-r--r--src/librustc/driver/session.rs4
-rw-r--r--src/librustc/metadata/creader.rs6
-rw-r--r--src/librustc/metadata/encoder.rs4
-rw-r--r--src/librustc/metadata/loader.rs4
-rw-r--r--src/librustc/metadata/tyencode.rs2
-rw-r--r--src/librustc/middle/astencode.rs4
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs2
-rw-r--r--src/librustc/middle/borrowck/gather_loans/gather_moves.rs2
-rw-r--r--src/librustc/middle/borrowck/gather_loans/lifetime.rs6
-rw-r--r--src/librustc/middle/borrowck/gather_loans/mod.rs10
-rw-r--r--src/librustc/middle/borrowck/gather_loans/restrictions.rs4
-rw-r--r--src/librustc/middle/lint.rs6
-rw-r--r--src/librustc/middle/mem_categorization.rs93
-rw-r--r--src/librustc/middle/privacy.rs2
-rw-r--r--src/librustc/middle/trans/base.rs7
-rw-r--r--src/librustc/middle/trans/callee.rs1
-rw-r--r--src/librustc/middle/trans/common.rs2
-rw-r--r--src/librustc/middle/trans/context.rs35
-rw-r--r--src/librustc/middle/trans/expr.rs101
-rw-r--r--src/librustc/middle/trans/foreign.rs2
-rw-r--r--src/librustc/middle/trans/glue.rs30
-rw-r--r--src/librustc/middle/trans/meth.rs146
-rw-r--r--src/librustc/middle/trans/reflect.rs6
-rw-r--r--src/librustc/middle/trans/type_.rs22
-rw-r--r--src/librustc/middle/ty.rs47
-rw-r--r--src/librustc/middle/typeck/check/method.rs456
-rw-r--r--src/librustc/middle/typeck/check/mod.rs3
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs6
-rw-r--r--src/librustc/middle/typeck/infer/coercion.rs42
-rw-r--r--src/librustc/middle/typeck/mod.rs2
-rw-r--r--src/librustc/util/ppaux.rs5
-rw-r--r--src/libstd/repr.rs24
-rw-r--r--src/libstd/unstable/intrinsics.rs24
-rw-r--r--src/libsyntax/ast_map.rs50
-rw-r--r--src/libsyntax/ast_util.rs50
-rw-r--r--src/libsyntax/attr.rs2
-rw-r--r--src/libsyntax/diagnostic.rs18
-rw-r--r--src/libsyntax/ext/expand.rs40
-rw-r--r--src/libsyntax/ext/trace_macros.rs2
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs4
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs6
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs4
-rw-r--r--src/libsyntax/parse/comments.rs4
-rw-r--r--src/libsyntax/parse/lexer.rs21
-rw-r--r--src/libsyntax/parse/mod.rs8
-rw-r--r--src/libsyntax/parse/parser.rs4
-rw-r--r--src/libsyntax/print/pprust.rs2
-rw-r--r--src/libsyntax/visit.rs96
-rw-r--r--src/rt/rust_type.h1
-rw-r--r--src/rt/rust_util.cpp1
-rw-r--r--src/test/compile-fail/borrowck-borrow-mut-object-twice.rs (renamed from src/test/run-pass/unique-object.rs)23
-rw-r--r--src/test/compile-fail/borrowck-object-lifetime.rs42
-rw-r--r--src/test/compile-fail/borrowck-object-mutability.rs47
-rw-r--r--src/test/compile-fail/kindck-owned-trait-contains.rs1
-rw-r--r--src/test/compile-fail/object-pointer-types.rs64
-rw-r--r--src/test/compile-fail/selftype-traittype.rs2
-rw-r--r--src/test/run-fail/borrowck-wg-fail-object.rs21
-rw-r--r--src/test/run-pass/class-cast-to-trait.rs2
-rw-r--r--src/test/run-pass/objects-owned-object-borrowed-method-header.rs39
-rw-r--r--src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs (renamed from src/test/run-pass/owned-trait-objects.rs)4
-rw-r--r--src/test/run-pass/objects-owned-object-owned-method.rs32
-rw-r--r--src/test/run-pass/reflect-visit-data.rs4
-rw-r--r--src/test/run-pass/reflect-visit-type.rs6
65 files changed, 1155 insertions, 560 deletions
diff --git a/src/librustc/back/abi.rs b/src/librustc/back/abi.rs
index 05b6e90c682..dae0ceed22d 100644
--- a/src/librustc/back/abi.rs
+++ b/src/librustc/back/abi.rs
@@ -46,7 +46,8 @@ pub static tydesc_field_take_glue: uint = 2u;
 pub static tydesc_field_drop_glue: uint = 3u;
 pub static tydesc_field_free_glue: uint = 4u;
 pub static tydesc_field_visit_glue: uint = 5u;
-pub static n_tydesc_fields: uint = 6u;
+pub static tydesc_field_borrow_offset: uint = 6u;
+pub static n_tydesc_fields: uint = 7u;
 
 // The two halves of a closure: code and environment.
 pub static fn_field_code: uint = 0u;
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index fdf88757469..0e7dc3b2fcd 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -785,7 +785,7 @@ pub fn build_session(sopts: @session::options,
 pub fn build_session_(sopts: @session::options,
                       cm: @codemap::CodeMap,
                       demitter: diagnostic::Emitter,
-                      span_diagnostic_handler: @diagnostic::span_handler)
+                      span_diagnostic_handler: @mut diagnostic::span_handler)
                    -> Session {
     let target_cfg = build_target_config(sopts, demitter);
     let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler,
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index d725e2db1eb..cf62e35488b 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -192,7 +192,7 @@ pub struct Session_ {
     // For a library crate, this is always none
     entry_fn: @mut Option<(NodeId, codemap::span)>,
     entry_type: @mut Option<EntryFnType>,
-    span_diagnostic: @diagnostic::span_handler,
+    span_diagnostic: @mut diagnostic::span_handler,
     filesearch: @filesearch::FileSearch,
     building_library: @mut bool,
     working_dir: Path,
@@ -261,7 +261,7 @@ impl Session_ {
     pub fn next_node_id(@self) -> ast::NodeId {
         return syntax::parse::next_node_id(self.parse_sess);
     }
-    pub fn diagnostic(@self) -> @diagnostic::span_handler {
+    pub fn diagnostic(@self) -> @mut diagnostic::span_handler {
         self.span_diagnostic
     }
     pub fn debugging_opt(@self, opt: uint) -> bool {
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 82f5c4f8843..eaf01241c81 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -29,7 +29,7 @@ use syntax::oldvisit;
 
 // Traverses an AST, reading all the information about use'd crates and extern
 // libraries necessary for later resolving, typechecking, linking, etc.
-pub fn read_crates(diag: @span_handler,
+pub fn read_crates(diag: @mut span_handler,
                    crate: &ast::Crate,
                    cstore: @mut cstore::CStore,
                    filesearch: @FileSearch,
@@ -74,7 +74,7 @@ fn dump_crates(crate_cache: &[cache_entry]) {
 }
 
 fn warn_if_multiple_versions(e: @mut Env,
-                             diag: @span_handler,
+                             diag: @mut span_handler,
                              crate_cache: &[cache_entry]) {
     use std::either::*;
 
@@ -113,7 +113,7 @@ fn warn_if_multiple_versions(e: @mut Env,
 }
 
 struct Env {
-    diag: @span_handler,
+    diag: @mut span_handler,
     filesearch: @FileSearch,
     cstore: @mut cstore::CStore,
     os: loader::os,
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index c4919e7f263..9366d757dd4 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -55,7 +55,7 @@ pub type encode_inlined_item<'self> = &'self fn(ecx: &EncodeContext,
                                    ii: ast::inlined_item);
 
 pub struct EncodeParams<'self> {
-    diag: @span_handler,
+    diag: @mut span_handler,
     tcx: ty::ctxt,
     reexports2: middle::resolve::ExportMap2,
     item_symbols: &'self HashMap<ast::NodeId, ~str>,
@@ -82,7 +82,7 @@ struct Stats {
 }
 
 pub struct EncodeContext<'self> {
-    diag: @span_handler,
+    diag: @mut span_handler,
     tcx: ty::ctxt,
     stats: @mut Stats,
     reexports2: middle::resolve::ExportMap2,
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index 704a22ec979..554cdf4b2b4 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -43,7 +43,7 @@ pub enum os {
 }
 
 pub struct Context {
-    diag: @span_handler,
+    diag: @mut span_handler,
     filesearch: @FileSearch,
     span: span,
     ident: @str,
@@ -163,7 +163,7 @@ pub fn package_id_from_metas(metas: &[@ast::MetaItem]) -> Option<@str> {
 }
 
 pub fn note_linkage_attrs(intr: @ident_interner,
-                          diag: @span_handler,
+                          diag: @mut span_handler,
                           attrs: ~[ast::Attribute]) {
     let r = attr::find_linkage_metas(attrs);
     for mi in r.iter() {
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index ffd79433b76..915729d254f 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -25,7 +25,7 @@ use syntax::diagnostic::span_handler;
 use syntax::print::pprust::*;
 
 pub struct ctxt {
-    diag: @span_handler,
+    diag: @mut span_handler,
     // Def -> str Callback:
     ds: @fn(def_id) -> ~str,
     // The type context.
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 8a7894efb91..d6342c582f0 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -586,8 +586,8 @@ impl tr for method_origin {
                 }
             )
           }
-          typeck::method_trait(did, m, vstore) => {
-              typeck::method_trait(did.tr(xcx), m, vstore)
+          typeck::method_trait(did, m) => {
+              typeck::method_trait(did.tr(xcx), m)
           }
         }
     }
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index 88e168db558..620a1e9efe3 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -362,7 +362,7 @@ impl<'self> CheckLoanCtxt<'self> {
                     }
 
                     mc::cat_discr(b, _) |
-                    mc::cat_deref(b, _, mc::uniq_ptr(*)) => {
+                    mc::cat_deref(b, _, mc::uniq_ptr) => {
                         assert_eq!(cmt.mutbl, mc::McInherited);
                         cmt = b;
                     }
diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
index 54a5c09a0e9..24a6e5b6e0b 100644
--- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
@@ -173,7 +173,7 @@ fn check_is_legal_to_move_from(bccx: @BorrowckCtxt,
             }
         }
 
-        mc::cat_deref(b, _, mc::uniq_ptr(*)) |
+        mc::cat_deref(b, _, mc::uniq_ptr) |
         mc::cat_discr(b, _) => {
             check_is_legal_to_move_from(bccx, cmt0, b)
         }
diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
index ddcc5fe56d0..b315a7a2e72 100644
--- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
@@ -74,7 +74,7 @@ impl GuaranteeLifetimeContext {
             mc::cat_arg(*) |                           // L-Local
             mc::cat_self(*) |                          // L-Local
             mc::cat_deref(_, _, mc::region_ptr(*)) |   // L-Deref-Borrowed
-            mc::cat_deref(_, _, mc::unsafe_ptr) => {
+            mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
                 let scope = self.scope(cmt);
                 self.check_scope(scope)
             }
@@ -108,7 +108,7 @@ impl GuaranteeLifetimeContext {
             }
 
             mc::cat_downcast(base) |
-            mc::cat_deref(base, _, mc::uniq_ptr(*)) |  // L-Deref-Send
+            mc::cat_deref(base, _, mc::uniq_ptr) |     // L-Deref-Send
             mc::cat_interior(base, _) => {             // L-Field
                 self.check(base, discr_scope)
             }
@@ -347,7 +347,7 @@ impl GuaranteeLifetimeContext {
                 r
             }
             mc::cat_downcast(cmt) |
-            mc::cat_deref(cmt, _, mc::uniq_ptr(*)) |
+            mc::cat_deref(cmt, _, mc::uniq_ptr) |
             mc::cat_deref(cmt, _, mc::gc_ptr(*)) |
             mc::cat_interior(cmt, _) |
             mc::cat_stack_upvar(cmt) |
diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs
index b970a6585f6..6ebc4b49b37 100644
--- a/src/librustc/middle/borrowck/gather_loans/mod.rs
+++ b/src/librustc/middle/borrowck/gather_loans/mod.rs
@@ -352,13 +352,21 @@ impl GatherLoanCtxt {
                                              r)
                     }
                     ty::AutoBorrowFn(r) => {
-                        let cmt_deref = mcx.cat_deref_fn(expr, cmt, 0);
+                        let cmt_deref = mcx.cat_deref_fn_or_obj(expr, cmt, 0);
                         self.guarantee_valid(expr.id,
                                              expr.span,
                                              cmt_deref,
                                              m_imm,
                                              r)
                     }
+                    ty::AutoBorrowObj(r, m) => {
+                        let cmt_deref = mcx.cat_deref_fn_or_obj(expr, cmt, 0);
+                        self.guarantee_valid(expr.id,
+                                             expr.span,
+                                             cmt_deref,
+                                             m,
+                                             r)
+                    }
                     ty::AutoUnsafe(_) => {}
                 }
             }
diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
index ad32eb0c805..46bb23e400e 100644
--- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
@@ -101,7 +101,7 @@ impl RestrictionsContext {
                 self.extend(result, cmt.mutbl, LpInterior(i), restrictions)
             }
 
-            mc::cat_deref(cmt_base, _, mc::uniq_ptr(*)) => {
+            mc::cat_deref(cmt_base, _, mc::uniq_ptr) => {
                 // R-Deref-Send-Pointer
                 //
                 // When we borrow the interior of an owned pointer, we
@@ -194,7 +194,7 @@ impl RestrictionsContext {
                 }
             }
 
-            mc::cat_deref(_, _, mc::unsafe_ptr) => {
+            mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
                 // We are very trusting when working with unsafe pointers.
                 Safe
             }
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 3a15cbe0f52..76532b5cd22 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -301,7 +301,7 @@ enum AnyVisitor {
     // recursive call can use the original visitor's method, although the
     // recursing visitor supplied to the method is the item stopping visitor.
     OldVisitor(oldvisit::vt<@mut Context>, oldvisit::vt<@mut Context>),
-    NewVisitor(@visit::Visitor<()>),
+    NewVisitor(@mut visit::Visitor<()>),
 }
 
 struct Context {
@@ -465,7 +465,7 @@ impl Context {
         self.visitors.push(OldVisitor(v, item_stopping_visitor(v)));
     }
 
-    fn add_lint(&mut self, v: @visit::Visitor<()>) {
+    fn add_lint(&mut self, v: @mut visit::Visitor<()>) {
         self.visitors.push(NewVisitor(v));
     }
 
@@ -989,7 +989,7 @@ fn lint_unused_mut() -> oldvisit::vt<@mut Context> {
     })
 }
 
-fn lint_session(cx: @mut Context) -> @visit::Visitor<()> {
+fn lint_session(cx: @mut Context) -> @mut visit::Visitor<()> {
     ast_util::id_visitor(|id| {
         match cx.tcx.sess.lints.pop(&id) {
             None => {},
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 6c5209cf504..283724447f8 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -84,10 +84,10 @@ pub struct CopiedUpvar {
 // different kinds of pointers:
 #[deriving(Eq)]
 pub enum ptr_kind {
-    uniq_ptr(ast::mutability),
+    uniq_ptr,
     gc_ptr(ast::mutability),
     region_ptr(ast::mutability, ty::Region),
-    unsafe_ptr
+    unsafe_ptr(ast::mutability)
 }
 
 // We use the term "interior" to mean "something reachable from the
@@ -156,14 +156,12 @@ pub enum deref_kind {
 // pointer adjustment).
 pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
     match ty::get(t).sty {
-        ty::ty_uniq(mt) => {
-            Some(deref_ptr(uniq_ptr(mt.mutbl)))
-        }
-
+        ty::ty_uniq(_) |
+        ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
         ty::ty_evec(_, ty::vstore_uniq) |
         ty::ty_estr(ty::vstore_uniq) |
         ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
-            Some(deref_ptr(uniq_ptr(m_imm)))
+            Some(deref_ptr(uniq_ptr))
         }
 
         ty::ty_rptr(r, mt) |
@@ -171,24 +169,32 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
             Some(deref_ptr(region_ptr(mt.mutbl, r)))
         }
 
+        ty::ty_trait(_, _, ty::RegionTraitStore(r), m, _) => {
+            Some(deref_ptr(region_ptr(m, r)))
+        }
+
         ty::ty_estr(ty::vstore_slice(r)) |
         ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil,
                                       region: r, _}) => {
             Some(deref_ptr(region_ptr(ast::m_imm, r)))
         }
 
-        ty::ty_box(mt) |
-        ty::ty_evec(mt, ty::vstore_box) => {
+        ty::ty_box(ref mt) |
+        ty::ty_evec(ref mt, ty::vstore_box) => {
             Some(deref_ptr(gc_ptr(mt.mutbl)))
         }
 
+        ty::ty_trait(_, _, ty::BoxTraitStore, m, _) => {
+            Some(deref_ptr(gc_ptr(m)))
+        }
+
         ty::ty_estr(ty::vstore_box) |
         ty::ty_closure(ty::ClosureTy {sigil: ast::ManagedSigil, _}) => {
             Some(deref_ptr(gc_ptr(ast::m_imm)))
         }
 
-        ty::ty_ptr(*) => {
-            Some(deref_ptr(unsafe_ptr))
+        ty::ty_ptr(ref mt) => {
+            Some(deref_ptr(unsafe_ptr(mt.mutbl)))
         }
 
         ty::ty_enum(*) |
@@ -631,20 +637,19 @@ impl mem_categorization_ctxt {
         }
     }
 
-    pub fn cat_deref_fn<N:ast_node>(&self,
-                                    node: N,
-                                    base_cmt: cmt,
-                                    deref_cnt: uint)
-                                    -> cmt {
+    pub fn cat_deref_fn_or_obj<N:ast_node>(&self,
+                                           node: N,
+                                           base_cmt: cmt,
+                                           deref_cnt: uint)
+                                           -> cmt {
         // Bit of a hack: the "dereference" of a function pointer like
         // `@fn()` is a mere logical concept. We interpret it as
         // dereferencing the environment pointer; of course, we don't
         // know what type lies at the other end, so we just call it
         // `()` (the empty tuple).
 
-        let mt = ty::mt {ty: ty::mk_tup(self.tcx, ~[]),
-                         mutbl: m_imm};
-        return self.cat_deref_common(node, base_cmt, deref_cnt, mt);
+        let opaque_ty = ty::mk_tup(self.tcx, ~[]);
+        return self.cat_deref_common(node, base_cmt, deref_cnt, opaque_ty);
     }
 
     pub fn cat_deref<N:ast_node>(&self,
@@ -662,25 +667,25 @@ impl mem_categorization_ctxt {
             }
         };
 
-        return self.cat_deref_common(node, base_cmt, deref_cnt, mt);
+        return self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty);
     }
 
     pub fn cat_deref_common<N:ast_node>(&self,
                                         node: N,
                                         base_cmt: cmt,
                                         deref_cnt: uint,
-                                        mt: ty::mt)
+                                        deref_ty: ty::t)
                                         -> cmt {
         match deref_kind(self.tcx, base_cmt.ty) {
             deref_ptr(ptr) => {
                 // for unique ptrs, we inherit mutability from the
                 // owning reference.
                 let m = match ptr {
-                    uniq_ptr(*) => {
-                        self.inherited_mutability(base_cmt.mutbl, mt.mutbl)
+                    uniq_ptr => {
+                        base_cmt.mutbl.inherit()
                     }
-                    gc_ptr(*) | region_ptr(_, _) | unsafe_ptr => {
-                        MutabilityCategory::from_mutbl(mt.mutbl)
+                    gc_ptr(m) | region_ptr(m, _) | unsafe_ptr(m) => {
+                        MutabilityCategory::from_mutbl(m)
                     }
                 };
 
@@ -689,18 +694,18 @@ impl mem_categorization_ctxt {
                     span:node.span(),
                     cat:cat_deref(base_cmt, deref_cnt, ptr),
                     mutbl:m,
-                    ty:mt.ty
+                    ty:deref_ty
                 }
             }
 
             deref_interior(interior) => {
-                let m = self.inherited_mutability(base_cmt.mutbl, mt.mutbl);
+                let m = base_cmt.mutbl.inherit();
                 @cmt_ {
                     id:node.id(),
                     span:node.span(),
                     cat:cat_interior(base_cmt, interior),
                     mutbl:m,
-                    ty:mt.ty
+                    ty:deref_ty
                 }
             }
         }
@@ -742,8 +747,8 @@ impl mem_categorization_ctxt {
         //! - `derefs`: the deref number to be used for
         //!   the implicit index deref, if any (see above)
 
-        let mt = match ty::index(base_cmt.ty) {
-          Some(mt) => mt,
+        let element_ty = match ty::index(base_cmt.ty) {
+          Some(ref mt) => mt.ty,
           None => {
             self.tcx.sess.span_bug(
                 elt.span(),
@@ -757,11 +762,11 @@ impl mem_categorization_ctxt {
             // for unique ptrs, we inherit mutability from the
             // owning reference.
             let m = match ptr {
-              uniq_ptr(*) => {
-                self.inherited_mutability(base_cmt.mutbl, mt.mutbl)
+              uniq_ptr => {
+                base_cmt.mutbl.inherit()
               }
-              gc_ptr(_) | region_ptr(_, _) | unsafe_ptr => {
-                MutabilityCategory::from_mutbl(mt.mutbl)
+              gc_ptr(m) | region_ptr(m, _) | unsafe_ptr(m) => {
+                MutabilityCategory::from_mutbl(m)
               }
             };
 
@@ -771,16 +776,16 @@ impl mem_categorization_ctxt {
                 span:elt.span(),
                 cat:cat_deref(base_cmt, derefs, ptr),
                 mutbl:m,
-                ty:mt.ty
+                ty:element_ty
             };
 
-            interior(elt, deref_cmt, base_cmt.ty, m, mt)
+            interior(elt, deref_cmt, base_cmt.ty, m, element_ty)
           }
 
           deref_interior(_) => {
             // fixed-length vectors have no deref
-            let m = self.inherited_mutability(base_cmt.mutbl, mt.mutbl);
-            interior(elt, base_cmt, base_cmt.ty, m, mt)
+            let m = base_cmt.mutbl.inherit();
+            interior(elt, base_cmt, base_cmt.ty, m, element_ty)
           }
         };
 
@@ -788,14 +793,14 @@ impl mem_categorization_ctxt {
                                  of_cmt: cmt,
                                  vec_ty: ty::t,
                                  mutbl: MutabilityCategory,
-                                 mt: ty::mt) -> cmt
+                                 element_ty: ty::t) -> cmt
         {
             @cmt_ {
                 id:elt.id(),
                 span:elt.span(),
                 cat:cat_interior(of_cmt, InteriorElement(element_kind(vec_ty))),
                 mutbl:mutbl,
-                ty:mt.ty
+                ty:element_ty
             }
         }
     }
@@ -1130,7 +1135,7 @@ impl cmt_ {
             cat_stack_upvar(b) |
             cat_discr(b, _) |
             cat_interior(b, _) |
-            cat_deref(b, _, uniq_ptr(*)) => {
+            cat_deref(b, _, uniq_ptr) => {
                 b.guarantor()
             }
         }
@@ -1177,7 +1182,7 @@ impl cmt_ {
 
             cat_downcast(b) |
             cat_stack_upvar(b) |
-            cat_deref(b, _, uniq_ptr(*)) |
+            cat_deref(b, _, uniq_ptr) |
             cat_interior(b, _) |
             cat_discr(b, _) => {
                 b.freely_aliasable()
@@ -1230,10 +1235,10 @@ impl Repr for categorization {
 
 pub fn ptr_sigil(ptr: ptr_kind) -> ~str {
     match ptr {
-        uniq_ptr(_) => ~"~",
+        uniq_ptr => ~"~",
         gc_ptr(_) => ~"@",
         region_ptr(_, _) => ~"&",
-        unsafe_ptr => ~"*"
+        unsafe_ptr(_) => ~"*"
     }
 }
 
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index a4b88870b97..aa7b2e55cdc 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -290,7 +290,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                  method_num: method_num,
                  _
             }) |
-            method_trait(trait_id, method_num, _) => {
+            method_trait(trait_id, method_num) => {
                 if trait_id.crate == LOCAL_CRATE {
                     match tcx.items.find(&trait_id.node) {
                         Some(&node_item(item, _)) => {
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 4a2cefd2685..1291a586682 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -2405,12 +2405,7 @@ pub fn fill_fn_pair(bcx: @mut Block, pair: ValueRef, llfn: ValueRef,
 }
 
 pub fn item_path(ccx: &CrateContext, id: &ast::NodeId) -> path {
-    match ccx.tcx.items.get_copy(id) {
-        ast_map::node_item(i, p) =>
-            vec::append((*p).clone(), [path_name(i.ident)]),
-        // separate map for paths?
-        _ => fail!("item_path")
-    }
+    ty::item_path(ccx.tcx, ast_util::local_def(*id))
 }
 
 fn exported_name(ccx: @mut CrateContext, path: path, ty: ty::t, attrs: &[ast::Attribute]) -> ~str {
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index a0e71bc2272..4caaf384873 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -60,7 +60,6 @@ pub struct MethodData {
     llfn: ValueRef,
     llself: ValueRef,
     temp_cleanup: Option<ValueRef>,
-    self_ty: ty::t,
     self_mode: ty::SelfMode,
 }
 
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 96616cbe533..3253e24ae88 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -54,6 +54,7 @@ pub struct tydesc_info {
     tydesc: ValueRef,
     size: ValueRef,
     align: ValueRef,
+    borrow_offset: ValueRef,
     take_glue: Option<ValueRef>,
     drop_glue: Option<ValueRef>,
     free_glue: Option<ValueRef>,
@@ -686,7 +687,6 @@ pub fn tuplify_box_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
                          t]);
 }
 
-
 // LLVM constant constructors.
 pub fn C_null(t: Type) -> ValueRef {
     unsafe {
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index a644174731a..187c121bbd3 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -13,7 +13,7 @@ use back::{upcall};
 use driver::session;
 use lib::llvm::{ContextRef, ModuleRef, ValueRef};
 use lib::llvm::{llvm, TargetData, TypeNames};
-use lib::llvm::{mk_target_data};
+use lib::llvm::{mk_target_data, False};
 use metadata::common::LinkMeta;
 use middle::astencode;
 use middle::resolve;
@@ -22,6 +22,7 @@ use middle::trans::base;
 use middle::trans::builder::Builder;
 use middle::trans::debuginfo;
 use middle::trans::type_use;
+use middle::trans::common::{C_i32, C_null};
 use middle::ty;
 
 use middle::trans::type_::Type;
@@ -30,6 +31,8 @@ use std::c_str::ToCStr;
 use std::hash;
 use std::hashmap::{HashMap, HashSet};
 use std::local_data;
+use std::vec;
+use std::libc::c_uint;
 use syntax::ast;
 
 use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats};
@@ -236,6 +239,36 @@ impl CrateContext {
     pub fn builder(@mut self) -> Builder {
         Builder::new(self)
     }
+
+    pub fn const_inbounds_gepi(&self,
+                               pointer: ValueRef,
+                               indices: &[uint]) -> ValueRef {
+        debug!("const_inbounds_gepi: pointer=%s indices=%?",
+               self.tn.val_to_str(pointer), indices);
+        let v: ~[ValueRef] =
+            indices.iter().map(|i| C_i32(*i as i32)).collect();
+        unsafe {
+            llvm::LLVMConstInBoundsGEP(pointer,
+                                       vec::raw::to_ptr(v),
+                                       indices.len() as c_uint)
+        }
+    }
+
+    pub fn offsetof_gep(&self,
+                        llptr_ty: Type,
+                        indices: &[uint]) -> ValueRef {
+        /*!
+         * Returns the offset of applying the given GEP indices
+         * to an instance of `llptr_ty`. Similar to `offsetof` in C,
+         * except that `llptr_ty` must be a pointer type.
+         */
+
+        unsafe {
+            let null = C_null(llptr_ty);
+            llvm::LLVMConstPtrToInt(self.const_inbounds_gepi(null, indices),
+                                    self.int_type.to_ref())
+        }
+    }
 }
 
 #[unsafe_destructor]
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 5931b54342f..cb4a7f364da 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -137,9 +137,8 @@ use middle::trans::meth;
 use middle::trans::tvec;
 use middle::trans::type_of;
 use middle::ty::struct_fields;
-use middle::ty::{AutoDerefRef, AutoAddEnv};
-use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn,
-                 AutoUnsafe};
+use middle::ty::{AutoBorrowObj, AutoDerefRef, AutoAddEnv, AutoUnsafe};
+use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn};
 use middle::ty;
 use util::common::indenter;
 use util::ppaux::Repr;
@@ -223,6 +222,10 @@ pub fn trans_to_datum(bcx: @mut Block, expr: @ast::expr) -> DatumBlock {
                                                     datum.ty, Some(adjustment));
                     unpack_datum!(bcx, auto_borrow_fn(bcx, adjusted_ty, datum))
                 }
+                Some(AutoBorrowObj(*)) => {
+                    unpack_datum!(bcx, auto_borrow_obj(
+                        bcx, adj.autoderefs, expr, datum))
+                }
             };
         }
     }
@@ -298,6 +301,98 @@ pub fn trans_to_datum(bcx: @mut Block, expr: @ast::expr) -> DatumBlock {
         let DatumBlock { bcx, datum } = auto_slice(bcx, autoderefs, expr, datum);
         auto_ref(bcx, datum)
     }
+
+    fn auto_borrow_obj(mut bcx: @mut Block,
+                       autoderefs: uint,
+                       expr: @ast::expr,
+                       source_datum: Datum) -> DatumBlock {
+        let tcx = bcx.tcx();
+        let target_obj_ty = expr_ty_adjusted(bcx, expr);
+        debug!("auto_borrow_obj(target=%s)",
+               target_obj_ty.repr(tcx));
+        let scratch = scratch_datum(bcx, target_obj_ty,
+                                    "__auto_borrow_obj", false);
+
+        // Convert a @Object, ~Object, or &Object pair into an &Object pair.
+
+        // Get a pointer to the source object, which is represented as
+        // a (vtable, data) pair.
+        let source_llval = source_datum.to_ref_llval(bcx);
+
+        // Set the vtable field of the new pair
+        let vtable_ptr = GEPi(bcx, source_llval, [0u, abi::trt_field_vtable]);
+        let vtable = Load(bcx, vtable_ptr);
+        Store(bcx, vtable, GEPi(bcx, scratch.val, [0u, abi::trt_field_vtable]));
+
+        // Load the data for the source, which is either an @T,
+        // ~T, or &T, depending on source_obj_ty.
+        let source_data_ptr = GEPi(bcx, source_llval, [0u, abi::trt_field_box]);
+        let source_data = Load(bcx, source_data_ptr); // always a ptr
+        let (source_store, source_mutbl) = match ty::get(source_datum.ty).sty {
+            ty::ty_trait(_, _, s, m, _) => (s, m),
+            _ => {
+                bcx.sess().span_bug(
+                    expr.span,
+                    fmt!("auto_borrow_trait_obj expected a trait, found %s",
+                         source_datum.ty.repr(bcx.tcx())));
+            }
+        };
+        let target_data = match source_store {
+            ty::BoxTraitStore(*) => {
+                // For deref of @T or @mut T, create a dummy datum and
+                // use the datum's deref method. This is more work
+                // than just calling GEPi ourselves, but it ensures
+                // that any write guards will be appropriate
+                // processed.  Note that we don't know the type T, so
+                // just substitute `i8`-- it doesn't really matter for
+                // our purposes right now.
+                let source_ty =
+                    ty::mk_box(tcx,
+                               ty::mt {
+                                   ty: ty::mk_i8(),
+                                   mutbl: source_mutbl});
+                let source_datum =
+                    Datum {val: source_data,
+                           ty: source_ty,
+                           mode: ByValue};
+                let derefd_datum =
+                    unpack_datum!(bcx,
+                                  source_datum.deref(bcx,
+                                                     expr,
+                                                     autoderefs));
+                derefd_datum.to_rptr(bcx).to_value_llval(bcx)
+            }
+            ty::UniqTraitStore(*) => {
+                // For a ~T box, there may or may not be a header,
+                // depending on whether the type T references managed
+                // boxes. However, since we do not *know* the type T
+                // for objects, this presents a hurdle. Our solution is
+                // to load the "borrow offset" from the type descriptor;
+                // this value will either be 0 or sizeof(BoxHeader), depending
+                // on the type T.
+                let llopaque =
+                    PointerCast(bcx, source_data, Type::opaque().ptr_to());
+                let lltydesc_ptr_ptr =
+                    PointerCast(bcx, vtable,
+                                bcx.ccx().tydesc_type.ptr_to().ptr_to());
+                let lltydesc_ptr =
+                    Load(bcx, lltydesc_ptr_ptr);
+                let borrow_offset_ptr =
+                    GEPi(bcx, lltydesc_ptr,
+                         [0, abi::tydesc_field_borrow_offset]);
+                let borrow_offset =
+                    Load(bcx, borrow_offset_ptr);
+                InBoundsGEP(bcx, llopaque, [borrow_offset])
+            }
+            ty::RegionTraitStore(*) => {
+                source_data
+            }
+        };
+        Store(bcx, target_data,
+              GEPi(bcx, scratch.val, [0u, abi::trt_field_box]));
+
+        DatumBlock { bcx: bcx, datum: scratch }
+    }
 }
 
 pub fn trans_into(bcx: @mut Block, expr: @ast::expr, dest: Dest) -> @mut Block {
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 2bf483ee3a0..7694f690286 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -857,8 +857,6 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
         "visit_tydesc" => {
             let td = get_param(decl, first_real_arg);
             let visitor = get_param(decl, first_real_arg + 1u);
-            //let llvisitorptr = alloca(bcx, val_ty(visitor));
-            //Store(bcx, visitor, llvisitorptr);
             let td = PointerCast(bcx, td, ccx.tydesc_type.ptr_to());
             glue::call_tydesc_glue_full(bcx, visitor, td,
                                         abi::tydesc_field_visit_glue, None);
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index a70b907f262..4f894deb1a1 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -348,7 +348,8 @@ pub fn make_visit_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
     let _icx = push_ctxt("make_visit_glue");
     do with_scope(bcx, None, "visitor cleanup") |bcx| {
         let mut bcx = bcx;
-        let (visitor_trait, object_ty) = match ty::visitor_object_ty(bcx.tcx()){
+        let (visitor_trait, object_ty) = match ty::visitor_object_ty(bcx.tcx(),
+                                                                     ty::re_static) {
             Ok(pair) => pair,
             Err(s) => {
                 bcx.tcx().sess.fatal(s);
@@ -655,6 +656,18 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
                   ppaux::ty_to_str(ccx.tcx, t));
     }
 
+    let has_header = match ty::get(t).sty {
+        ty::ty_box(*) => true,
+        ty::ty_uniq(*) => ty::type_contents(ccx.tcx, t).contains_managed(),
+        _ => false
+    };
+
+    let borrow_offset = if has_header {
+        ccx.offsetof_gep(llty, [0u, abi::box_field_body])
+    } else {
+        C_uint(ccx, 0)
+    };
+
     let llsize = llsize_of(ccx, llty);
     let llalign = llalign_of(ccx, llty);
     let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc").to_managed();
@@ -670,6 +683,7 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
         tydesc: gvar,
         size: llsize,
         align: llalign,
+        borrow_offset: borrow_offset,
         take_glue: None,
         drop_glue: None,
         free_glue: None,
@@ -785,13 +799,17 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
               }
             };
 
+        debug!("ti.borrow_offset: %s",
+               ccx.tn.val_to_str(ti.borrow_offset));
+
         let tydesc = C_named_struct(ccx.tydesc_type,
                                     [ti.size, // size
-                                    ti.align, // align
-                                    take_glue, // take_glue
-                                    drop_glue, // drop_glue
-                                    free_glue, // free_glue
-                                    visit_glue]); // visit_glue
+                                     ti.align, // align
+                                     take_glue, // take_glue
+                                     drop_glue, // drop_glue
+                                     free_glue, // free_glue
+                                     visit_glue, // visit_glue
+                                     ti.borrow_offset]); // borrow_offset
 
         unsafe {
             let gvar = ti.tydesc;
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 4cc4f8fa696..f5b2ff75596 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -164,7 +164,6 @@ pub fn trans_method_callee(bcx: @mut Block,
                     llfn: callee_fn.llfn,
                     llself: val,
                     temp_cleanup: temp_cleanups.head_opt().map_move(|v| *v),
-                    self_ty: node_id_type(bcx, this.id),
                     self_mode: mentry.self_mode,
                 })
             }
@@ -187,13 +186,11 @@ pub fn trans_method_callee(bcx: @mut Block,
             }
         }
 
-        typeck::method_trait(_, off, store) => {
+        typeck::method_trait(_, off) => {
             trans_trait_callee(bcx,
                                callee_id,
                                off,
-                               this,
-                               store,
-                               mentry.explicit_self)
+                               this)
         }
     }
 }
@@ -341,7 +338,6 @@ pub fn trans_monomorphized_callee(bcx: @mut Block,
                   llfn: llfn_val,
                   llself: llself_val,
                   temp_cleanup: temp_cleanups.head_opt().map_move(|v| *v),
-                  self_ty: node_id_type(bcx, base.id),
                   self_mode: mentry.self_mode,
               })
           }
@@ -406,142 +402,78 @@ pub fn combine_impl_and_methods_tps(bcx: @mut Block,
 pub fn trans_trait_callee(bcx: @mut Block,
                           callee_id: ast::NodeId,
                           n_method: uint,
-                          self_expr: @ast::expr,
-                          store: ty::TraitStore,
-                          explicit_self: ast::explicit_self_)
+                          self_expr: @ast::expr)
                           -> Callee {
-    //!
-    //
-    // Create a method callee where the method is coming from a trait
-    // instance (e.g., @Trait type).  In this case, we must pull the
-    // fn pointer out of the vtable that is packaged up with the
-    // @/~/&Trait instance.  @/~/&Traits are represented as a pair, so we
-    // first evaluate the self expression (expected a by-ref result) and then
-    // extract the self data and vtable out of the pair.
+    /*!
+     * Create a method callee where the method is coming from a trait
+     * object (e.g., @Trait type).  In this case, we must pull the fn
+     * pointer out of the vtable that is packaged up with the object.
+     * Objects are represented as a pair, so we first evaluate the self
+     * expression and then extract the self data and vtable out of the
+     * pair.
+     */
 
     let _icx = push_ctxt("impl::trans_trait_callee");
     let mut bcx = bcx;
-    let self_datum = unpack_datum!(bcx,
-        expr::trans_to_datum(bcx, self_expr));
-    let llpair = self_datum.to_ref_llval(bcx);
-
-    let llpair = match explicit_self {
-        ast::sty_region(*) => Load(bcx, llpair),
-        ast::sty_static | ast::sty_value |
-        ast::sty_box(_) | ast::sty_uniq => llpair
-    };
+
+    let self_ty = expr_ty_adjusted(bcx, self_expr);
+    let self_scratch = scratch_datum(bcx, self_ty, "__trait_callee", false);
+    bcx = expr::trans_into(bcx, self_expr, expr::SaveIn(self_scratch.val));
+
+    // Arrange a temporary cleanup for the object in case something
+    // should go wrong before the method is actually *invoked*.
+    self_scratch.add_clean(bcx);
 
     let callee_ty = node_id_type(bcx, callee_id);
     trans_trait_callee_from_llval(bcx,
                                   callee_ty,
                                   n_method,
-                                  llpair,
-                                  store,
-                                  explicit_self)
+                                  self_scratch.val,
+                                  Some(self_scratch.val))
 }
 
 pub fn trans_trait_callee_from_llval(bcx: @mut Block,
                                      callee_ty: ty::t,
                                      n_method: uint,
                                      llpair: ValueRef,
-                                     store: ty::TraitStore,
-                                     explicit_self: ast::explicit_self_)
+                                     temp_cleanup: Option<ValueRef>)
                                   -> Callee {
-    //!
-    //
-    // Same as `trans_trait_callee()` above, except that it is given
-    // a by-ref pointer to the @Trait pair.
+    /*!
+     * Same as `trans_trait_callee()` above, except that it is given
+     * a by-ref pointer to the object pair.
+     */
 
     let _icx = push_ctxt("impl::trans_trait_callee");
     let ccx = bcx.ccx();
 
-    // Load the vtable from the @Trait pair
-    debug!("(translating trait callee) loading vtable from pair %s",
-           bcx.val_to_str(llpair));
-    let llvtable = Load(bcx,
-                      PointerCast(bcx,
-                                  GEPi(bcx, llpair,
-                                       [0u, abi::trt_field_vtable]),
-                                  Type::vtable().ptr_to().ptr_to()));
-
-    // Load the box from the @Trait pair and GEP over the box header if
-    // necessary:
-    let mut llself;
+    // Load the data pointer from the object.
     debug!("(translating trait callee) loading second index from pair");
     let llboxptr = GEPi(bcx, llpair, [0u, abi::trt_field_box]);
     let llbox = Load(bcx, llboxptr);
-
-    // Munge `llself` appropriately for the type of `self` in the method.
-    match explicit_self {
-        ast::sty_static => {
-            bcx.tcx().sess.bug("shouldn't see static method here");
-        }
-        ast::sty_value => {
-            bcx.tcx().sess.bug("methods with by-value self should not be \
-                                called on objects");
-        }
-        ast::sty_region(*) => {
-            match store {
-                ty::UniqTraitStore
-                    if !ty::type_contents(bcx.tcx(), callee_ty).contains_managed() => {
-                    llself = llbox;
-                }
-                ty::BoxTraitStore |
-                ty::UniqTraitStore => {
-                    llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
-                }
-                ty::RegionTraitStore(_) => {
-                    llself = llbox;
-                }
-            }
-        }
-        ast::sty_box(_) => {
-            // Bump the reference count on the box.
-            debug!("(translating trait callee) callee type is `%s`",
-                   bcx.ty_to_str(callee_ty));
-            glue::incr_refcnt_of_boxed(bcx, llbox);
-
-            // Pass a pointer to the box.
-            match store {
-                ty::BoxTraitStore => llself = llbox,
-                _ => bcx.tcx().sess.bug("@self receiver with non-@Trait")
-            }
-        }
-        ast::sty_uniq => {
-            // Pass the unique pointer.
-            match store {
-                ty::UniqTraitStore => llself = llbox,
-                _ => bcx.tcx().sess.bug("~self receiver with non-~Trait")
-            }
-
-            zero_mem(bcx, llboxptr, ty::mk_opaque_box(bcx.tcx()));
-        }
-    }
-
-    llself = PointerCast(bcx, llself, Type::opaque_box(ccx).ptr_to());
-    let scratch = scratch_datum(bcx, ty::mk_opaque_box(bcx.tcx()),
-                                "__trait_callee", false);
-    Store(bcx, llself, scratch.val);
-    scratch.add_clean(bcx);
+    let llself = PointerCast(bcx, llbox, Type::opaque_box(ccx).ptr_to());
 
     // Load the function from the vtable and cast it to the expected type.
     debug!("(translating trait callee) loading method");
     let llcallee_ty = type_of_fn_from_ty(ccx, callee_ty);
-
-    // Plus one in order to skip past the type descriptor.
+    let llvtable = Load(bcx,
+                        PointerCast(bcx,
+                                    GEPi(bcx, llpair,
+                                         [0u, abi::trt_field_vtable]),
+                                    Type::vtable().ptr_to().ptr_to()));
     let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method + 1]));
-
     let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to());
 
     return Callee {
         bcx: bcx,
         data: Method(MethodData {
             llfn: mptr,
-            llself: scratch.to_value_llval(bcx),
-            temp_cleanup: Some(scratch.val),
-            self_ty: scratch.ty,
+            llself: llself,
+            temp_cleanup: temp_cleanup,
+
+                // We know that the func declaration is &self, ~self,
+                // or @self, and such functions are always by-copy
+                // (right now, at least).
             self_mode: ty::ByCopy,
-            /* XXX: Some(llbox) */
         })
     };
 }
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index e0403ac9ad7..fe5f8cd70ef 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -100,17 +100,13 @@ impl Reflector {
             debug!("arg %u: %s", i, bcx.val_to_str(*a));
         }
         let bool_ty = ty::mk_bool();
-        // XXX: Should not be BoxTraitStore!
         let result = unpack_result!(bcx, callee::trans_call_inner(
             self.bcx, None, mth_ty, bool_ty,
             |bcx| meth::trans_trait_callee_from_llval(bcx,
                                                       mth_ty,
                                                       mth_idx,
                                                       v,
-                                                      ty::BoxTraitStore,
-                                                      ast::sty_region(
-                                                        None,
-                                                        ast::m_imm)),
+                                                      None),
             ArgVals(args), None, DontAutorefArg));
         let result = bool_to_i1(bcx, result);
         let next_bcx = sub_block(bcx, "next");
diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs
index 110febfcc9f..8d94a0d10d6 100644
--- a/src/librustc/middle/trans/type_.rs
+++ b/src/librustc/middle/trans/type_.rs
@@ -205,10 +205,18 @@ impl Type {
 
         let int_ty = Type::int(arch);
 
-        let elems = [
-            int_ty, int_ty,
-            glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty
-        ];
+        // Must mirror:
+        //
+        // std::unstable::intrinsics::TyDesc
+        // type_desc in rt
+
+        let elems = [int_ty,     // size
+                     int_ty,     // align
+                     glue_fn_ty, // take
+                     glue_fn_ty, // drop
+                     glue_fn_ty, // free
+                     glue_fn_ty, // visit
+                     int_ty];    // borrow_offset
 
         tydesc.set_struct_body(elems, false);
 
@@ -249,8 +257,12 @@ impl Type {
         Type::struct_(Type::box_header_fields(ctx) + &[*ty], false)
     }
 
+    pub fn opaque() -> Type {
+        Type::i8()
+    }
+
     pub fn opaque_box(ctx: &CrateContext) -> Type {
-        Type::box(ctx, &Type::i8())
+        Type::box(ctx, &Type::opaque())
     }
 
     pub fn unique(ctx: &CrateContext, ty: &Type) -> Type {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index bba5d85083b..2ba6930d9c5 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -226,13 +226,16 @@ pub enum AutoRef {
     AutoBorrowFn(Region),
 
     /// Convert from T to *T
-    AutoUnsafe(ast::mutability)
+    AutoUnsafe(ast::mutability),
+
+    /// Convert from @Trait/~Trait/&Trait to &Trait
+    AutoBorrowObj(Region, ast::mutability),
 }
 
 pub type ctxt = @ctxt_;
 
 struct ctxt_ {
-    diag: @syntax::diagnostic::span_handler,
+    diag: @mut syntax::diagnostic::span_handler,
     interner: @mut HashMap<intern_key, ~t_box_>,
     next_id: @mut uint,
     cstore: @mut metadata::cstore::CStore,
@@ -1004,7 +1007,13 @@ fn mk_t(cx: ctxt, st: sty) -> t {
       &ty_self(_) => flags |= has_self as uint,
       &ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
       &ty_trait(_, ref substs, _, _, _) => {
-        flags |= sflags(substs);
+          flags |= sflags(substs);
+          match st {
+              ty_trait(_, _, RegionTraitStore(r), _, _) => {
+                    flags |= rflags(r);
+                }
+              _ => {}
+          }
       }
       &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
       &ty_ptr(ref m) | &ty_unboxed_vec(ref m) => {
@@ -3009,6 +3018,10 @@ pub fn adjust_ty(cx: ctxt,
                         AutoUnsafe(m) => {
                             mk_ptr(cx, mt {ty: adjusted_ty, mutbl: m})
                         }
+
+                        AutoBorrowObj(r, m) => {
+                            borrow_obj(cx, span, r, m, adjusted_ty)
+                        }
                     }
                 }
             }
@@ -3054,6 +3067,22 @@ pub fn adjust_ty(cx: ctxt,
             }
         }
     }
+
+    fn borrow_obj(cx: ctxt, span: span, r: Region,
+                  m: ast::mutability, ty: ty::t) -> ty::t {
+        match get(ty).sty {
+            ty_trait(trt_did, ref trt_substs, _, _, b) => {
+                ty::mk_trait(cx, trt_did, trt_substs.clone(),
+                             RegionTraitStore(r), m, b)
+            }
+            ref s => {
+                cx.sess.span_bug(
+                    span,
+                    fmt!("borrow-trait-obj associated with bad sty: %?",
+                         s));
+            }
+        }
+    }
 }
 
 impl AutoRef {
@@ -3064,6 +3093,7 @@ impl AutoRef {
             ty::AutoBorrowVecRef(r, m) => ty::AutoBorrowVecRef(f(r), m),
             ty::AutoBorrowFn(r) => ty::AutoBorrowFn(f(r)),
             ty::AutoUnsafe(m) => ty::AutoUnsafe(m),
+            ty::AutoBorrowObj(r, m) => ty::AutoBorrowObj(f(r), m),
         }
     }
 }
@@ -3101,7 +3131,7 @@ pub fn method_call_type_param_defs(tcx: ctxt,
           typeck::method_param(typeck::method_param {
               trait_id: trt_id,
               method_num: n_mth, _}) |
-          typeck::method_trait(trt_id, n_mth, _) => {
+          typeck::method_trait(trt_id, n_mth) => {
             // ...trait methods bounds, in contrast, include only the
             // method bounds, so we must preprend the tps from the
             // trait itself.  This ought to be harmonized.
@@ -4457,7 +4487,8 @@ pub fn get_opaque_ty(tcx: ctxt) -> Result<t, ~str> {
     }
 }
 
-pub fn visitor_object_ty(tcx: ctxt) -> Result<(@TraitRef, t), ~str> {
+pub fn visitor_object_ty(tcx: ctxt,
+                         region: ty::Region) -> Result<(@TraitRef, t), ~str> {
     let trait_lang_item = match tcx.lang_items.require(TyVisitorTraitLangItem) {
         Ok(id) => id,
         Err(s) => { return Err(s); }
@@ -4468,13 +4499,11 @@ pub fn visitor_object_ty(tcx: ctxt) -> Result<(@TraitRef, t), ~str> {
         tps: ~[]
     };
     let trait_ref = @TraitRef { def_id: trait_lang_item, substs: substs };
-    let mut static_trait_bound = EmptyBuiltinBounds();
-    static_trait_bound.add(BoundStatic);
     Ok((trait_ref,
         mk_trait(tcx,
                  trait_ref.def_id,
                  trait_ref.substs.clone(),
-                 BoxTraitStore,
+                 RegionTraitStore(region),
                  ast::m_imm,
-                 static_trait_bound)))
+                 EmptyBuiltinBounds())))
 }
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 84e5d8f9bf7..352836d81e4 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -94,6 +94,7 @@ use middle::typeck::{method_static, method_trait};
 use middle::typeck::{param_numbered, param_self, param_index};
 use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
 use util::common::indenter;
+use util::ppaux::Repr;
 
 use std::hashmap::HashSet;
 use std::result;
@@ -147,9 +148,24 @@ pub fn lookup(
         check_traits: check_traits,
         autoderef_receiver: autoderef_receiver,
     };
-    let mme = lcx.do_lookup(self_ty);
-    debug!("method lookup for %s yielded %?", expr.repr(fcx.tcx()), mme);
-    return mme;
+
+    let self_ty = structurally_resolved_type(fcx, self_expr.span, self_ty);
+    debug!("method lookup(self_ty=%s, expr=%s, self_expr=%s)",
+           self_ty.repr(fcx.tcx()), expr.repr(fcx.tcx()),
+           self_expr.repr(fcx.tcx()));
+
+    debug!("searching inherent candidates");
+    lcx.push_inherent_candidates(self_ty);
+    let mme = lcx.search(self_ty);
+    if mme.is_some() {
+        return mme;
+    }
+
+    debug!("searching extension candidates");
+    lcx.reset_candidates();
+    lcx.push_bound_candidates(self_ty);
+    lcx.push_extension_candidates();
+    return lcx.search(self_ty);
 }
 
 pub struct LookupContext<'self> {
@@ -173,27 +189,28 @@ pub struct LookupContext<'self> {
  */
 #[deriving(Clone)]
 pub struct Candidate {
-    rcvr_ty: ty::t,
+    rcvr_match_condition: RcvrMatchCondition,
     rcvr_substs: ty::substs,
     method_ty: @ty::Method,
     origin: method_origin,
 }
 
-impl<'self> LookupContext<'self> {
-    pub fn do_lookup(&self, self_ty: ty::t) -> Option<method_map_entry> {
-        let self_ty = structurally_resolved_type(self.fcx,
-                                                     self.self_expr.span,
-                                                     self_ty);
-
-        debug!("do_lookup(self_ty=%s, expr=%s, self_expr=%s)",
-               self.ty_to_str(self_ty),
-               self.expr.repr(self.tcx()),
-               self.self_expr.repr(self.tcx()));
-
-        // Prepare the list of candidates
-        self.push_inherent_candidates(self_ty);
-        self.push_extension_candidates();
+/// This type represents the conditions under which the receiver is
+/// considered to "match" a given method candidate. Typically the test
+/// is whether the receiver is of a particular type. However, this
+/// type is the type of the receiver *after accounting for the
+/// method's self type* (e.g., if the method is an `@self` method, we
+/// have *already verified* that the receiver is of some type `@T` and
+/// now we must check that the type `T` is correct).  Unfortunately,
+/// because traits are not types, this is a pain to do.
+#[deriving(Clone)]
+enum RcvrMatchCondition {
+    RcvrMatchesIfObject(ast::def_id),
+    RcvrMatchesIfSubtype(ty::t)
+}
 
+impl<'self> LookupContext<'self> {
+    fn search(&self, self_ty: ty::t) -> Option<method_map_entry> {
         let mut self_ty = self_ty;
         let mut autoderefs = 0;
         loop {
@@ -247,7 +264,7 @@ impl<'self> LookupContext<'self> {
         self.search_for_autosliced_method(self_ty, autoderefs)
     }
 
-    pub fn deref(&self, ty: ty::t)
+    fn deref(&self, ty: ty::t)
                  -> Option<ty::t> {
         match ty::deref(self.tcx(), ty, false) {
             None => None,
@@ -262,7 +279,12 @@ impl<'self> LookupContext<'self> {
     // ______________________________________________________________________
     // Candidate collection (see comment at start of file)
 
-    pub fn push_inherent_candidates(&self, self_ty: ty::t) {
+    fn reset_candidates(&self) {
+        *self.inherent_candidates = ~[];
+        *self.extension_candidates = ~[];
+    }
+
+    fn push_inherent_candidates(&self, self_ty: ty::t) {
         /*!
          * Collect all inherent candidates into
          * `self.inherent_candidates`.  See comment at the start of
@@ -275,20 +297,10 @@ impl<'self> LookupContext<'self> {
         let mut self_ty = self_ty;
         loop {
             match get(self_ty).sty {
-                ty_param(p) => {
-                    self.push_inherent_candidates_from_param(self_ty, p);
-                }
-                ty_trait(did, ref substs, store, _, _) => {
-                    self.push_inherent_candidates_from_trait(
-                        self_ty, did, substs, store);
+                ty_trait(did, ref substs, _, _, _) => {
+                    self.push_inherent_candidates_from_trait(did, substs);
                     self.push_inherent_impl_candidates_for_type(did);
                 }
-                ty_self(self_did) => {
-                    // Call is of the form "self.foo()" and appears in one
-                    // of a trait's default method implementations.
-                    self.push_inherent_candidates_from_self(
-                        self_ty, self_did);
-                }
                 ty_enum(did, _) | ty_struct(did, _) => {
                     if self.check_traits == CheckTraitsAndInherentMethods {
                         self.push_inherent_impl_candidates_for_type(did);
@@ -307,7 +319,30 @@ impl<'self> LookupContext<'self> {
         }
     }
 
-    pub fn push_extension_candidates(&self) {
+    fn push_bound_candidates(&self, self_ty: ty::t) {
+        let mut self_ty = self_ty;
+        loop {
+            match get(self_ty).sty {
+                ty_param(p) => {
+                    self.push_inherent_candidates_from_param(self_ty, p);
+                }
+                ty_self(self_did) => {
+                    // Call is of the form "self.foo()" and appears in one
+                    // of a trait's default method implementations.
+                    self.push_inherent_candidates_from_self(
+                        self_ty, self_did);
+                }
+                _ => { /* No bound methods in these types */ }
+            }
+
+            self_ty = match self.deref(self_ty) {
+                None => { return; }
+                Some(ty) => { ty }
+            }
+        }
+    }
+
+    fn push_extension_candidates(&self) {
         // If the method being called is associated with a trait, then
         // find all the impls of that trait.  Each of those are
         // candidates.
@@ -328,11 +363,9 @@ impl<'self> LookupContext<'self> {
         }
     }
 
-    pub fn push_inherent_candidates_from_trait(&self,
-                                               self_ty: ty::t,
+    fn push_inherent_candidates_from_trait(&self,
                                                did: def_id,
-                                               substs: &ty::substs,
-                                               store: ty::TraitStore) {
+                                               substs: &ty::substs) {
         debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)",
                self.did_to_str(did),
                substs_to_str(self.tcx(), substs));
@@ -346,41 +379,35 @@ impl<'self> LookupContext<'self> {
         };
         let method = ms[index];
 
-        /* FIXME(#5762) we should transform the vstore in accordance
-           with the self type
-
-        match method.self_type {
-            ast::sty_region(_) => {
-                return; // inapplicable
+        match method.explicit_self {
+            ast::sty_static => {
+                return; // not a method we can call with dot notation
             }
-            ast::sty_region(_) => vstore_slice(r)
-            ast::sty_box(_) => vstore_box, // NDM mutability, as per #5762
-            ast::sty_uniq(_) => vstore_uniq
+            _ => {}
         }
-        */
 
         // It is illegal to invoke a method on a trait instance that
-        // refers to the `self` type.  Nonetheless, we substitute
-        // `trait_ty` for `self` here, because it allows the compiler
-        // to soldier on.  An error will be reported should this
-        // candidate be selected if the method refers to `self`.
+        // refers to the `self` type. An error will be reported by
+        // `enforce_object_limitations()` if the method refers
+        // to the `Self` type. Substituting ty_err here allows
+        // compiler to soldier on.
         //
-        // NB: `confirm_candidate()` also relies upon this substitution
-        // for Self.
+        // NOTE: `confirm_candidate()` also relies upon this substitution
+        // for Self. (fix)
         let rcvr_substs = substs {
-            self_ty: Some(self_ty),
+            self_ty: Some(ty::mk_err()),
             ..(*substs).clone()
         };
 
         self.inherent_candidates.push(Candidate {
-            rcvr_ty: self_ty,
+            rcvr_match_condition: RcvrMatchesIfObject(did),
             rcvr_substs: rcvr_substs,
             method_ty: method,
-            origin: method_trait(did, index, store)
+            origin: method_trait(did, index)
         });
     }
 
-    pub fn push_inherent_candidates_from_param(&self,
+    fn push_inherent_candidates_from_param(&self,
                                                rcvr_ty: ty::t,
                                                param_ty: param_ty) {
         debug!("push_inherent_candidates_from_param(param_ty=%?)",
@@ -403,7 +430,7 @@ impl<'self> LookupContext<'self> {
     }
 
 
-    pub fn push_inherent_candidates_from_self(&self,
+    fn push_inherent_candidates_from_self(&self,
                                               self_ty: ty::t,
                                               did: def_id) {
         let tcx = self.tcx();
@@ -413,7 +440,7 @@ impl<'self> LookupContext<'self> {
             self_ty, &[trait_ref], param_self);
     }
 
-    pub fn push_inherent_candidates_from_bounds(&self,
+    fn push_inherent_candidates_from_bounds(&self,
                                                 self_ty: ty::t,
                                                 bounds: &[@TraitRef],
                                                 param: param_index) {
@@ -433,11 +460,11 @@ impl<'self> LookupContext<'self> {
                     let method = trait_methods[pos];
 
                     let cand = Candidate {
-                        rcvr_ty: self_ty,
+                        rcvr_match_condition: RcvrMatchesIfSubtype(self_ty),
                         rcvr_substs: bound_trait_ref.substs.clone(),
                         method_ty: method,
                         origin: method_param(
-                            method_param {
+                                             method_param {
                                 trait_id: bound_trait_ref.def_id,
                                 method_num: pos,
                                 param_num: param,
@@ -459,7 +486,7 @@ impl<'self> LookupContext<'self> {
     }
 
 
-    pub fn push_inherent_impl_candidates_for_type(&self, did: def_id) {
+    fn push_inherent_impl_candidates_for_type(&self, did: def_id) {
         let opt_impl_infos = self.tcx().inherent_impls.find(&did);
         for impl_infos in opt_impl_infos.iter() {
             for impl_info in impl_infos.iter() {
@@ -469,7 +496,7 @@ impl<'self> LookupContext<'self> {
         }
     }
 
-    pub fn push_candidates_from_impl(&self,
+    fn push_candidates_from_impl(&self,
                                      candidates: &mut ~[Candidate],
                                      impl_info: &ty::Impl) {
         if !self.impl_dups.insert(impl_info.did) {
@@ -502,7 +529,7 @@ impl<'self> LookupContext<'self> {
         } = impl_self_ty(&vcx, location_info, impl_info.did);
 
         candidates.push(Candidate {
-            rcvr_ty: impl_ty,
+            rcvr_match_condition: RcvrMatchesIfSubtype(impl_ty),
             rcvr_substs: impl_substs,
             method_ty: method,
             origin: method_static(method.def_id)
@@ -512,7 +539,7 @@ impl<'self> LookupContext<'self> {
     // ______________________________________________________________________
     // Candidate selection (see comment at start of file)
 
-    pub fn search_for_autoderefd_method(&self,
+    fn search_for_autoderefd_method(&self,
                                         self_ty: ty::t,
                                         autoderefs: uint)
                                         -> Option<method_map_entry> {
@@ -531,12 +558,11 @@ impl<'self> LookupContext<'self> {
         }
     }
 
-    pub fn consider_reborrow(&self,
+    fn consider_reborrow(&self,
                              self_ty: ty::t,
                              autoderefs: uint)
                              -> (ty::t, ty::AutoAdjustment) {
         /*!
-         *
          * In the event that we are invoking a method with a receiver
          * of a borrowed type like `&T`, `&mut T`, or `&mut [T]`,
          * we will "reborrow" the receiver implicitly.  For example, if
@@ -579,6 +605,17 @@ impl<'self> LookupContext<'self> {
                      autoderefs: autoderefs,
                      autoref: Some(ty::AutoBorrowVec(region, self_mt.mutbl))}))
             }
+            ty_trait(did, ref substs, ty::RegionTraitStore(_), mutbl, bounds) => {
+                let region =
+                    self.infcx().next_region_var(
+                        infer::Autoref(self.expr.span));
+                (ty::mk_trait(tcx, did, substs.clone(),
+                              ty::RegionTraitStore(region),
+                              mutbl, bounds),
+                 ty::AutoDerefRef(ty::AutoDerefRef {
+                     autoderefs: autoderefs,
+                     autoref: Some(ty::AutoBorrowObj(region, mutbl))}))
+            }
             _ => {
                 (self_ty,
                  ty::AutoDerefRef(ty::AutoDerefRef {
@@ -598,7 +635,7 @@ impl<'self> LookupContext<'self> {
         }
     }
 
-    pub fn search_for_autosliced_method(&self,
+    fn search_for_autosliced_method(&self,
                                         self_ty: ty::t,
                                         autoderefs: uint)
                                         -> Option<method_map_entry> {
@@ -608,7 +645,8 @@ impl<'self> LookupContext<'self> {
          * `~[]` to `&[]`. */
 
         let tcx = self.tcx();
-        match ty::get(self_ty).sty {
+        let sty = ty::get(self_ty).sty.clone();
+        match sty {
             ty_evec(mt, vstore_box) |
             ty_evec(mt, vstore_uniq) |
             ty_evec(mt, vstore_slice(_)) | // NDM(#3148)
@@ -655,8 +693,20 @@ impl<'self> LookupContext<'self> {
                     })
             }
 
-            ty_trait(*) | ty_closure(*) => {
-                // NDM---eventually these should be some variant of autoref
+            ty_trait(trt_did, trt_substs, _, _, b) => {
+                // Coerce ~/@/&Trait instances to &Trait.
+
+                self.search_for_some_kind_of_autorefd_method(
+                    AutoBorrowObj, autoderefs, [m_const, m_imm, m_mutbl],
+                    |trt_mut, reg| {
+                        ty::mk_trait(tcx, trt_did, trt_substs.clone(),
+                                     RegionTraitStore(reg), trt_mut, b)
+                    })
+            }
+
+            ty_closure(*) => {
+                // This case should probably be handled similarly to
+                // Trait instances.
                 None
             }
 
@@ -664,7 +714,7 @@ impl<'self> LookupContext<'self> {
         }
     }
 
-    pub fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
+    fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
                                       -> Option<method_map_entry> {
         /*!
          *
@@ -696,7 +746,7 @@ impl<'self> LookupContext<'self> {
         }
     }
 
-    pub fn search_for_some_kind_of_autorefd_method(
+    fn search_for_some_kind_of_autorefd_method(
         &self,
         kind: &fn(Region, ast::mutability) -> ty::AutoRef,
         autoderefs: uint,
@@ -725,7 +775,7 @@ impl<'self> LookupContext<'self> {
         return None;
     }
 
-    pub fn search_for_method(&self, rcvr_ty: ty::t)
+    fn search_for_method(&self, rcvr_ty: ty::t)
                              -> Option<method_map_entry> {
         debug!("search_for_method(rcvr_ty=%s)", self.ty_to_str(rcvr_ty));
         let _indenter = indenter();
@@ -753,7 +803,7 @@ impl<'self> LookupContext<'self> {
         }
     }
 
-    pub fn consider_candidates(&self,
+    fn consider_candidates(&self,
                                rcvr_ty: ty::t,
                                candidates: &mut ~[Candidate])
                                -> Option<method_map_entry> {
@@ -780,7 +830,7 @@ impl<'self> LookupContext<'self> {
         Some(self.confirm_candidate(rcvr_ty, &relevant_candidates[0]))
     }
 
-    pub fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] {
+    fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] {
         let mut merged = ~[];
         let mut i = 0;
         while i < candidates.len() {
@@ -826,7 +876,7 @@ impl<'self> LookupContext<'self> {
         return merged;
     }
 
-    pub fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
+    fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
                              -> method_map_entry {
         let tcx = self.tcx();
         let fty = self.fn_ty_from_origin(&candidate.origin);
@@ -836,31 +886,16 @@ impl<'self> LookupContext<'self> {
                self.cand_to_str(candidate),
                self.ty_to_str(fty));
 
-        self.enforce_trait_instance_limitations(fty, candidate);
+        self.enforce_object_limitations(fty, candidate);
         self.enforce_drop_trait_limitations(candidate);
 
         // static methods should never have gotten this far:
         assert!(candidate.method_ty.explicit_self != sty_static);
 
         let transformed_self_ty = match candidate.origin {
-            method_trait(*) => {
-                match candidate.method_ty.explicit_self {
-                    sty_region(*) => {
-                        // FIXME(#5762) again, preserving existing
-                        // behavior here which (for &self) desires
-                        // &@Trait where @Trait is the type of the
-                        // receiver.  Here we fetch the method's
-                        // transformed_self_ty which will be something
-                        // like &'a Self.  We then perform a
-                        // substitution which will replace Self with
-                        // @Trait.
-                        let t = candidate.method_ty.transformed_self_ty.unwrap();
-                        ty::subst(tcx, &candidate.rcvr_substs, t)
-                    }
-                    _ => {
-                        candidate.rcvr_ty
-                    }
-                }
+            method_trait(trait_def_id, _) => {
+                self.construct_transformed_self_ty_for_object(
+                    trait_def_id, candidate)
             }
             _ => {
                 let t = candidate.method_ty.transformed_self_ty.unwrap();
@@ -950,23 +985,88 @@ impl<'self> LookupContext<'self> {
         self.fcx.write_ty(self.callee_id, fty);
         self.fcx.write_substs(self.callee_id, all_substs);
         method_map_entry {
-            self_ty: rcvr_ty,
+            self_ty: transformed_self_ty,
             self_mode: self_mode,
             explicit_self: candidate.method_ty.explicit_self,
             origin: candidate.origin,
         }
     }
 
-    pub fn enforce_trait_instance_limitations(&self,
-                                              method_fty: ty::t,
-                                              candidate: &Candidate) {
+    fn construct_transformed_self_ty_for_object(&self,
+                                                trait_def_id: ast::def_id,
+                                                candidate: &Candidate) -> ty::t
+    {
         /*!
+         * This is a bit tricky. We have a match against a trait method
+         * being invoked on an object, and we want to generate the
+         * self-type. As an example, consider a trait
+         *
+         *     trait Foo {
+         *         fn r_method<'a>(&'a self);
+         *         fn m_method(@mut self);
+         *     }
          *
-         * There are some limitations to calling functions through a
-         * trait instance, because (a) the self type is not known
+         * Now, assuming that `r_method` is being called, we want the
+         * result to be `&'a Foo`. Assuming that `m_method` is being
+         * called, we want the result to be `@mut Foo`. Of course,
+         * this transformation has already been done as part of
+         * `candidate.method_ty.transformed_self_ty`, but there the
+         * type is expressed in terms of `Self` (i.e., `&'a Self`, `@mut Self`).
+         * Because objects are not standalone types, we can't just substitute
+         * `s/Self/Foo/`, so we must instead perform this kind of hokey
+         * match below.
+         */
+
+        let substs = ty::substs {regions: candidate.rcvr_substs.regions.clone(),
+                                 self_ty: None,
+                                 tps: candidate.rcvr_substs.tps.clone()};
+        match candidate.method_ty.explicit_self {
+            ast::sty_static => {
+                self.bug(~"static method for object type receiver");
+            }
+            ast::sty_value => {
+                ty::mk_err() // error reported in `enforce_object_limitations()`
+            }
+            ast::sty_region(*) | ast::sty_box(*) | ast::sty_uniq(*) => {
+                let transformed_self_ty =
+                    candidate.method_ty.transformed_self_ty.clone().unwrap();
+                match ty::get(transformed_self_ty).sty {
+                    ty::ty_rptr(r, mt) => { // must be sty_region
+                        ty::mk_trait(self.tcx(), trait_def_id,
+                                     substs, RegionTraitStore(r), mt.mutbl,
+                                     ty::EmptyBuiltinBounds())
+                    }
+                    ty::ty_box(mt) => { // must be sty_box
+                        ty::mk_trait(self.tcx(), trait_def_id,
+                                     substs, BoxTraitStore, mt.mutbl,
+                                     ty::EmptyBuiltinBounds())
+                    }
+                    ty::ty_uniq(mt) => { // must be sty_uniq
+                        ty::mk_trait(self.tcx(), trait_def_id,
+                                     substs, UniqTraitStore, mt.mutbl,
+                                     ty::EmptyBuiltinBounds())
+                    }
+                    _ => {
+                        self.bug(
+                            fmt!("'impossible' transformed_self_ty: %s",
+                                 transformed_self_ty.repr(self.tcx())));
+                    }
+                }
+            }
+        }
+    }
+
+    fn enforce_object_limitations(&self,
+                                  method_fty: ty::t,
+                                  candidate: &Candidate)
+    {
+        /*!
+         * There are some limitations to calling functions through an
+         * object, because (a) the self type is not known
          * (that's the whole point of a trait instance, after all, to
          * obscure the self type) and (b) the call must go through a
-         * vtable and hence cannot be monomorphized. */
+         * vtable and hence cannot be monomorphized.
+         */
 
         match candidate.origin {
             method_static(*) | method_param(*) => {
@@ -975,21 +1075,39 @@ impl<'self> LookupContext<'self> {
             method_trait(*) => {}
         }
 
-        if ty::type_has_self(method_fty) {
+        match candidate.method_ty.explicit_self {
+            ast::sty_static => { // reason (a) above
+                self.tcx().sess.span_err(
+                    self.expr.span,
+                    "cannot call a method without a receiver \
+                     through an object");
+            }
+
+            ast::sty_value => { // reason (a) above
+                self.tcx().sess.span_err(
+                    self.expr.span,
+                    "cannot call a method with a by-value receiver \
+                     through an object");
+            }
+
+            ast::sty_region(*) | ast::sty_box(*) | ast::sty_uniq(*) => {}
+        }
+
+        if ty::type_has_self(method_fty) { // reason (a) above
             self.tcx().sess.span_err(
                 self.expr.span,
                 "cannot call a method whose type contains a \
-                 self-type through a boxed trait");
+                 self-type through an object");
         }
 
-        if candidate.method_ty.generics.has_type_params() {
+        if candidate.method_ty.generics.has_type_params() { // reason (b) above
             self.tcx().sess.span_err(
                 self.expr.span,
-                "cannot call a generic method through a boxed trait");
+                "cannot call a generic method through an object");
         }
     }
 
-    pub fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
+    fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
         // No code can call the finalize method explicitly.
         let bad;
         match candidate.origin {
@@ -999,7 +1117,7 @@ impl<'self> LookupContext<'self> {
             // XXX: does this properly enforce this on everything now
             // that self has been merged in? -sully
             method_param(method_param { trait_id: trait_id, _ }) |
-            method_trait(trait_id, _, _) => {
+            method_trait(trait_id, _) => {
                 bad = self.tcx().destructor_for_type.contains_key(&trait_id);
             }
         }
@@ -1012,43 +1130,18 @@ impl<'self> LookupContext<'self> {
 
     // `rcvr_ty` is the type of the expression. It may be a subtype of a
     // candidate method's `self_ty`.
-    pub fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
+    fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
         debug!("is_relevant(rcvr_ty=%s, candidate=%s)",
                self.ty_to_str(rcvr_ty), self.cand_to_str(candidate));
 
-        // Check for calls to object methods.  We resolve these differently.
-        //
-        // FIXME(#5762)---we don't check that an @self method is only called
-        // on an @Trait object here and so forth
-        match candidate.origin {
-            method_trait(*) => {
-                match candidate.method_ty.explicit_self {
-                    sty_static | sty_value => {
-                        return false;
-                    }
-                    sty_region(*) => {
-                        // just echoing current behavior here, which treats
-                        // an &self method on an @Trait object as requiring
-                        // an &@Trait receiver (wacky)
-                    }
-                    sty_box(*) | sty_uniq(*) => {
-                        return self.fcx.can_mk_subty(rcvr_ty,
-                                                     candidate.rcvr_ty).is_ok();
-                    }
-                };
-            }
-            _ => {}
-        }
-
-        let result = match candidate.method_ty.explicit_self {
+        return match candidate.method_ty.explicit_self {
             sty_static => {
                 debug!("(is relevant?) explicit self is static");
                 false
             }
 
             sty_value => {
-                debug!("(is relevant?) explicit self is by-value");
-                self.fcx.can_mk_subty(rcvr_ty, candidate.rcvr_ty).is_ok()
+                rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
             }
 
             sty_region(_, m) => {
@@ -1056,7 +1149,12 @@ impl<'self> LookupContext<'self> {
                 match ty::get(rcvr_ty).sty {
                     ty::ty_rptr(_, mt) => {
                         mutability_matches(mt.mutbl, m) &&
-                        self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
+                        rcvr_matches_ty(self.fcx, mt.ty, candidate)
+                    }
+
+                    ty::ty_trait(self_did, _, RegionTraitStore(_), self_m, _) => {
+                        mutability_matches(self_m, m) &&
+                        rcvr_matches_object(self_did, candidate)
                     }
 
                     _ => false
@@ -1068,7 +1166,12 @@ impl<'self> LookupContext<'self> {
                 match ty::get(rcvr_ty).sty {
                     ty::ty_box(mt) => {
                         mutability_matches(mt.mutbl, m) &&
-                        self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
+                        rcvr_matches_ty(self.fcx, mt.ty, candidate)
+                    }
+
+                    ty::ty_trait(self_did, _, BoxTraitStore, self_m, _) => {
+                        mutability_matches(self_m, m) &&
+                        rcvr_matches_object(self_did, candidate)
                     }
 
                     _ => false
@@ -1079,8 +1182,11 @@ impl<'self> LookupContext<'self> {
                 debug!("(is relevant?) explicit self is a unique pointer");
                 match ty::get(rcvr_ty).sty {
                     ty::ty_uniq(mt) => {
-                        mutability_matches(mt.mutbl, ast::m_imm) &&
-                        self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
+                        rcvr_matches_ty(self.fcx, mt.ty, candidate)
+                    }
+
+                    ty::ty_trait(self_did, _, UniqTraitStore, _, _) => {
+                        rcvr_matches_object(self_did, candidate)
                     }
 
                     _ => false
@@ -1088,9 +1194,30 @@ impl<'self> LookupContext<'self> {
             }
         };
 
-        debug!("(is relevant?) %s", if result { "yes" } else { "no" });
+        fn rcvr_matches_object(self_did: ast::def_id,
+                               candidate: &Candidate) -> bool {
+            match candidate.rcvr_match_condition {
+                RcvrMatchesIfObject(desired_did) => {
+                    self_did == desired_did
+                }
+                RcvrMatchesIfSubtype(_) => {
+                    false
+                }
+            }
+        }
 
-        return result;
+        fn rcvr_matches_ty(fcx: @mut FnCtxt,
+                           rcvr_ty: ty::t,
+                           candidate: &Candidate) -> bool {
+            match candidate.rcvr_match_condition {
+                RcvrMatchesIfObject(_) => {
+                    false
+                }
+                RcvrMatchesIfSubtype(of_type) => {
+                    fcx.can_mk_subty(rcvr_ty, of_type).is_ok()
+                }
+            }
+        }
 
         fn mutability_matches(self_mutbl: ast::mutability,
                               candidate_mutbl: ast::mutability) -> bool {
@@ -1108,7 +1235,7 @@ impl<'self> LookupContext<'self> {
         }
     }
 
-    pub fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t {
+    fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t {
         return match *origin {
             method_static(did) => {
                 ty::lookup_item_type(self.tcx(), did).ty
@@ -1116,7 +1243,7 @@ impl<'self> LookupContext<'self> {
             method_param(ref mp) => {
                 type_of_trait_method(self.tcx(), mp.trait_id, mp.method_num)
             }
-            method_trait(did, idx, _) => {
+            method_trait(did, idx) => {
                 type_of_trait_method(self.tcx(), did, idx)
             }
         };
@@ -1129,7 +1256,7 @@ impl<'self> LookupContext<'self> {
         }
     }
 
-    pub fn report_candidate(&self, idx: uint, origin: &method_origin) {
+    fn report_candidate(&self, idx: uint, origin: &method_origin) {
         match *origin {
             method_static(impl_did) => {
                 self.report_static_candidate(idx, impl_did)
@@ -1137,13 +1264,13 @@ impl<'self> LookupContext<'self> {
             method_param(ref mp) => {
                 self.report_param_candidate(idx, (*mp).trait_id)
             }
-            method_trait(trait_did, _, _) => {
+            method_trait(trait_did, _) => {
                 self.report_trait_candidate(idx, trait_did)
             }
         }
     }
 
-    pub fn report_static_candidate(&self, idx: uint, did: def_id) {
+    fn report_static_candidate(&self, idx: uint, did: def_id) {
         let span = if did.crate == ast::LOCAL_CRATE {
             match self.tcx().items.find(&did.node) {
               Some(&ast_map::node_method(m, _, _)) => m.span,
@@ -1159,7 +1286,7 @@ impl<'self> LookupContext<'self> {
                  ty::item_path_str(self.tcx(), did)));
     }
 
-    pub fn report_param_candidate(&self, idx: uint, did: def_id) {
+    fn report_param_candidate(&self, idx: uint, did: def_id) {
         self.tcx().sess.span_note(
             self.expr.span,
             fmt!("candidate #%u derives from the bound `%s`",
@@ -1167,7 +1294,7 @@ impl<'self> LookupContext<'self> {
                  ty::item_path_str(self.tcx(), did)));
     }
 
-    pub fn report_trait_candidate(&self, idx: uint, did: def_id) {
+    fn report_trait_candidate(&self, idx: uint, did: def_id) {
         self.tcx().sess.span_note(
             self.expr.span,
             fmt!("candidate #%u derives from the type of the receiver, \
@@ -1176,31 +1303,31 @@ impl<'self> LookupContext<'self> {
                  ty::item_path_str(self.tcx(), did)));
     }
 
-    pub fn infcx(&self) -> @mut infer::InferCtxt {
+    fn infcx(&self) -> @mut infer::InferCtxt {
         self.fcx.inh.infcx
     }
 
-    pub fn tcx(&self) -> ty::ctxt {
+    fn tcx(&self) -> ty::ctxt {
         self.fcx.tcx()
     }
 
-    pub fn ty_to_str(&self, t: ty::t) -> ~str {
+    fn ty_to_str(&self, t: ty::t) -> ~str {
         self.fcx.infcx().ty_to_str(t)
     }
 
-    pub fn cand_to_str(&self, cand: &Candidate) -> ~str {
+    fn cand_to_str(&self, cand: &Candidate) -> ~str {
         fmt!("Candidate(rcvr_ty=%s, rcvr_substs=%s, origin=%?)",
-             self.ty_to_str(cand.rcvr_ty),
+             cand.rcvr_match_condition.repr(self.tcx()),
              ty::substs_to_str(self.tcx(), &cand.rcvr_substs),
              cand.origin)
     }
 
-    pub fn did_to_str(&self, did: def_id) -> ~str {
+    fn did_to_str(&self, did: def_id) -> ~str {
         ty::item_path_str(self.tcx(), did)
     }
 
-    pub fn bug(&self, s: ~str) -> ! {
-        self.tcx().sess.bug(s)
+    fn bug(&self, s: ~str) -> ! {
+        self.tcx().sess.span_bug(self.self_expr.span, s)
     }
 }
 
@@ -1210,3 +1337,16 @@ pub fn get_mode_from_explicit_self(explicit_self: ast::explicit_self_) -> SelfMo
         _ => ty::ByCopy,
     }
 }
+
+impl Repr for RcvrMatchCondition {
+    fn repr(&self, tcx: ty::ctxt) -> ~str {
+        match *self {
+            RcvrMatchesIfObject(d) => {
+                fmt!("RcvrMatchesIfObject(%s)", d.repr(tcx))
+            }
+            RcvrMatchesIfSubtype(t) => {
+                fmt!("RcvrMatchesIfSubtype(%s)", t.repr(tcx))
+            }
+        }
+    }
+}
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 1b4d3ccbb34..e7ef30c4576 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -3437,7 +3437,8 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
                   Ok(t) => t,
                   Err(s) => { tcx.sess.span_fatal(it.span, s); }
               };
-              let visitor_object_ty = match ty::visitor_object_ty(tcx) {
+              let region = ty::re_bound(ty::br_anon(0));
+              let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
                   Ok((_, vot)) => vot,
                   Err(s) => { tcx.sess.span_fatal(it.span, s); }
               };
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 18e7295d61a..d034277d44a 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -863,7 +863,8 @@ pub mod guarantor {
 
             ty::AutoBorrowVec(r, _) |
             ty::AutoBorrowVecRef(r, _) |
-            ty::AutoBorrowFn(r) => {
+            ty::AutoBorrowFn(r) |
+            ty::AutoBorrowObj(r, _) => {
                 // In each of these cases, what is being borrowed is
                 // not the (autoderef'd) expr itself but rather the
                 // contents of the autoderef'd expression (i.e., what
@@ -1072,7 +1073,8 @@ pub mod guarantor {
                     Some(ty::AutoPtr(r, _)) |
                     Some(ty::AutoBorrowVec(r, _)) |
                     Some(ty::AutoBorrowVecRef(r, _)) |
-                    Some(ty::AutoBorrowFn(r)) => {
+                    Some(ty::AutoBorrowFn(r)) |
+                    Some(ty::AutoBorrowObj(r, _)) => {
                         // If there is an autoref, then the result of this
                         // expression will be some sort of borrowed pointer.
                         expr_ct.cat.guarantor = None;
diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs
index a6899d7150e..f2bde146ea7 100644
--- a/src/librustc/middle/typeck/infer/coercion.rs
+++ b/src/librustc/middle/typeck/infer/coercion.rs
@@ -65,7 +65,7 @@ we may want to adjust precisely when coercions occur.
 */
 
 
-use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowFn};
+use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowFn, AutoBorrowObj};
 use middle::ty::{AutoDerefRef};
 use middle::ty::{vstore_slice, vstore_box, vstore_uniq};
 use middle::ty::{mt};
@@ -121,6 +121,12 @@ impl Coerce {
                 };
             }
 
+            ty::ty_trait(_, _, ty::RegionTraitStore(*), _, _) => {
+                return do self.unpack_actual_value(a) |sty_a| {
+                    self.coerce_borrowed_object(a, sty_a, b)
+                };
+            }
+
             ty::ty_ptr(mt_b) => {
                 return do self.unpack_actual_value(a) |sty_a| {
                     self.coerce_unsafe_ptr(a, sty_a, b, mt_b)
@@ -265,6 +271,40 @@ impl Coerce {
         })))
     }
 
+    fn coerce_borrowed_object(&self,
+                              a: ty::t,
+                              sty_a: &ty::sty,
+                              b: ty::t) -> CoerceResult
+    {
+        debug!("coerce_borrowed_object(a=%s, sty_a=%?, b=%s)",
+               a.inf_str(self.infcx), sty_a,
+               b.inf_str(self.infcx));
+
+        let tcx = self.infcx.tcx;
+        let r_a = self.infcx.next_region_var(Coercion(self.trace));
+        let trt_mut;
+
+        let a_borrowed = match *sty_a {
+            ty::ty_trait(_, _, ty::RegionTraitStore(_), _, _) => {
+                return self.subtype(a, b);
+            }
+            ty::ty_trait(did, ref substs, _, m, b) => {
+                trt_mut = m;
+                ty::mk_trait(tcx, did, substs.clone(),
+                             ty::RegionTraitStore(r_a), m, b)
+            }
+            _ => {
+                return self.subtype(a, b);
+            }
+        };
+
+        if_ok!(self.tys(a_borrowed, b));
+        Ok(Some(@AutoDerefRef(AutoDerefRef {
+            autoderefs: 0,
+            autoref: Some(AutoBorrowObj(r_a, trt_mut))
+        })))
+    }
+
     pub fn coerce_borrowed_fn(&self,
                               a: ty::t,
                               sty_a: &ty::sty,
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index b1356ffb2d5..53ae80f19fa 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -88,7 +88,7 @@ pub enum method_origin {
     method_param(method_param),
 
     // method invoked on a trait instance
-    method_trait(ast::def_id, uint, ty::TraitStore),
+    method_trait(ast::def_id, uint),
 
 }
 
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 1bea3003c63..3bc0a7167e9 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -747,9 +747,8 @@ impl Repr for typeck::method_origin {
             &typeck::method_param(ref p) => {
                 p.repr(tcx)
             }
-            &typeck::method_trait(def_id, n, st) => {
-                fmt!("method_trait(%s, %?, %s)", def_id.repr(tcx), n,
-                     st.repr(tcx))
+            &typeck::method_trait(def_id, n) => {
+                fmt!("method_trait(%s, %?)", def_id.repr(tcx), n)
             }
         }
     }
diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs
index a53e3e796a7..d0970f1b6b7 100644
--- a/src/libstd/repr.rs
+++ b/src/libstd/repr.rs
@@ -158,6 +158,7 @@ impl ReprVisitor {
     }
 
     #[inline]
+    #[cfg(stage0)]
     pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool {
         unsafe {
             let u = ReprVisitor(ptr, self.writer);
@@ -168,6 +169,17 @@ impl ReprVisitor {
     }
 
     #[inline]
+    #[cfg(not(stage0))]
+    pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool {
+        unsafe {
+            let u = ReprVisitor(ptr, self.writer);
+            let v = reflect::MovePtrAdaptor(u);
+            visit_tydesc(inner, &v as &TyVisitor);
+            true
+        }
+    }
+
+    #[inline]
     pub fn write<T:Repr>(&self) -> bool {
         do self.get |v:&T| {
             v.write_repr(self.writer);
@@ -556,6 +568,7 @@ impl TyVisitor for ReprVisitor {
     fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
 }
 
+#[cfg(stage0)]
 pub fn write_repr<T>(writer: @Writer, object: &T) {
     unsafe {
         let ptr = ptr::to_unsafe_ptr(object) as *c_void;
@@ -566,6 +579,17 @@ pub fn write_repr<T>(writer: @Writer, object: &T) {
     }
 }
 
+#[cfg(not(stage0))]
+pub fn write_repr<T>(writer: @Writer, object: &T) {
+    unsafe {
+        let ptr = ptr::to_unsafe_ptr(object) as *c_void;
+        let tydesc = get_tydesc::<T>();
+        let u = ReprVisitor(ptr, writer);
+        let v = reflect::MovePtrAdaptor(u);
+        visit_tydesc(tydesc, &v as &TyVisitor)
+    }
+}
+
 #[cfg(test)]
 struct P {a: int, b: float}
 
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index 9f69ee47e9b..92725fda705 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -38,16 +38,34 @@ pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor};
 
 pub type GlueFn = extern "Rust" fn(*i8);
 
-// NB: this has to be kept in sync with the Rust ABI.
+// NB: this has to be kept in sync with `type_desc` in `rt`
 #[lang="ty_desc"]
 #[cfg(not(test))]
 pub struct TyDesc {
+    // sizeof(T)
     size: uint,
+
+    // alignof(T)
     align: uint,
+
+    // Called on a copy of a value of type `T` *after* memcpy
     take_glue: GlueFn,
+
+    // Called when a value of type `T` is no longer needed
     drop_glue: GlueFn,
+
+    // Called by drop glue when a value of type `T` can be freed
     free_glue: GlueFn,
+
+    // Called by reflection visitor to visit a value of type `T`
     visit_glue: GlueFn,
+
+    // If T represents a box pointer (`@U` or `~U`), then
+    // `borrow_offset` is the amount that the pointer must be adjusted
+    // to find the payload.  This is always derivable from the type
+    // `U`, but in the case of `@Trait` or `~Trait` objects, the type
+    // `U` is unknown.
+    borrow_offset: uint,
 }
 
 #[lang="opaque"]
@@ -310,8 +328,12 @@ extern "rust-intrinsic" {
     /// Returns `true` if a type is managed (will be allocated on the local heap)
     pub fn contains_managed<T>() -> bool;
 
+    #[cfg(stage0)]
     pub fn visit_tydesc(td: *TyDesc, tv: @TyVisitor);
 
+    #[cfg(not(stage0))]
+    pub fn visit_tydesc(td: *TyDesc, tv: &TyVisitor);
+
     pub fn frame_address(f: &once fn(*u8));
 
     /// Get the address of the `__morestack` stack growth function.
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index 6b4da9671a9..1fea0c2e6f9 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -85,7 +85,7 @@ pub type map = @mut HashMap<NodeId, ast_node>;
 pub struct Ctx {
     map: map,
     path: path,
-    diag: @span_handler,
+    diag: @mut span_handler,
 }
 
 impl Ctx {
@@ -141,7 +141,7 @@ impl Ctx {
             }
         }
 
-        visit::visit_expr(self as @Visitor<()>, ex, ());
+        visit::visit_expr(self as @mut Visitor<()>, ex, ());
     }
 
     fn map_fn(@mut self,
@@ -153,18 +153,18 @@ impl Ctx {
         for a in decl.inputs.iter() {
             self.map.insert(a.id, node_arg);
         }
-        visit::visit_fn(self as @Visitor<()>, fk, decl, body, sp, id, ());
+        visit::visit_fn(self as @mut Visitor<()>, fk, decl, body, sp, id, ());
     }
 
     fn map_stmt(@mut self, stmt: @stmt) {
         self.map.insert(stmt_id(stmt), node_stmt(stmt));
-        visit::visit_stmt(self as @Visitor<()>, stmt, ());
+        visit::visit_stmt(self as @mut Visitor<()>, stmt, ());
     }
 
     fn map_block(@mut self, b: &Block) {
         // clone is FIXME #2543
         self.map.insert(b.id, node_block((*b).clone()));
-        visit::visit_block(self as @Visitor<()>, b, ());
+        visit::visit_block(self as @mut Visitor<()>, b, ());
     }
 
     fn map_pat(@mut self, pat: @pat) {
@@ -177,7 +177,7 @@ impl Ctx {
             _ => ()
         }
 
-        visit::visit_pat(self as @Visitor<()>, pat, ());
+        visit::visit_pat(self as @mut Visitor<()>, pat, ());
     }
 }
 
@@ -254,13 +254,13 @@ impl Visitor<()> for Ctx {
             }
             _ => self.path.push(path_name(i.ident))
         }
-        visit::visit_item(self as @Visitor<()>, i, ());
+        visit::visit_item(self as @mut Visitor<()>, i, ());
         self.path.pop();
     }
 
     fn visit_pat(@mut self, pat: @pat, _: ()) {
         self.map_pat(pat);
-        visit::visit_pat(self as @Visitor<()>, pat, ())
+        visit::visit_pat(self as @mut Visitor<()>, pat, ())
     }
 
     fn visit_expr(@mut self, expr: @expr, _: ()) {
@@ -288,27 +288,27 @@ impl Visitor<()> for Ctx {
     // XXX: Methods below can become default methods.
 
     fn visit_mod(@mut self, module: &_mod, _: span, _: NodeId, _: ()) {
-        visit::visit_mod(self as @Visitor<()>, module, ())
+        visit::visit_mod(self as @mut Visitor<()>, module, ())
     }
 
     fn visit_view_item(@mut self, view_item: &view_item, _: ()) {
-        visit::visit_view_item(self as @Visitor<()>, view_item, ())
+        visit::visit_view_item(self as @mut Visitor<()>, view_item, ())
     }
 
     fn visit_foreign_item(@mut self, foreign_item: @foreign_item, _: ()) {
-        visit::visit_foreign_item(self as @Visitor<()>, foreign_item, ())
+        visit::visit_foreign_item(self as @mut Visitor<()>, foreign_item, ())
     }
 
     fn visit_local(@mut self, local: @Local, _: ()) {
-        visit::visit_local(self as @Visitor<()>, local, ())
+        visit::visit_local(self as @mut Visitor<()>, local, ())
     }
 
     fn visit_arm(@mut self, arm: &arm, _: ()) {
-        visit::visit_arm(self as @Visitor<()>, arm, ())
+        visit::visit_arm(self as @mut Visitor<()>, arm, ())
     }
 
     fn visit_decl(@mut self, decl: @decl, _: ()) {
-        visit::visit_decl(self as @Visitor<()>, decl, ())
+        visit::visit_decl(self as @mut Visitor<()>, decl, ())
     }
 
     fn visit_expr_post(@mut self, _: @expr, _: ()) {
@@ -316,11 +316,11 @@ impl Visitor<()> for Ctx {
     }
 
     fn visit_ty(@mut self, typ: &Ty, _: ()) {
-        visit::visit_ty(self as @Visitor<()>, typ, ())
+        visit::visit_ty(self as @mut Visitor<()>, typ, ())
     }
 
     fn visit_generics(@mut self, generics: &Generics, _: ()) {
-        visit::visit_generics(self as @Visitor<()>, generics, ())
+        visit::visit_generics(self as @mut Visitor<()>, generics, ())
     }
 
     fn visit_fn(@mut self,
@@ -330,7 +330,7 @@ impl Visitor<()> for Ctx {
                 span: span,
                 node_id: NodeId,
                 _: ()) {
-        visit::visit_fn(self as @Visitor<()>,
+        visit::visit_fn(self as @mut Visitor<()>,
                         function_kind,
                         function_declaration,
                         block,
@@ -340,11 +340,11 @@ impl Visitor<()> for Ctx {
     }
 
     fn visit_ty_method(@mut self, ty_method: &TypeMethod, _: ()) {
-        visit::visit_ty_method(self as @Visitor<()>, ty_method, ())
+        visit::visit_ty_method(self as @mut Visitor<()>, ty_method, ())
     }
 
     fn visit_trait_method(@mut self, trait_method: &trait_method, _: ()) {
-        visit::visit_trait_method(self as @Visitor<()>, trait_method, ())
+        visit::visit_trait_method(self as @mut Visitor<()>, trait_method, ())
     }
 
     fn visit_struct_def(@mut self,
@@ -353,7 +353,7 @@ impl Visitor<()> for Ctx {
                         generics: &Generics,
                         node_id: NodeId,
                         _: ()) {
-        visit::visit_struct_def(self as @Visitor<()>,
+        visit::visit_struct_def(self as @mut Visitor<()>,
                                 struct_def,
                                 ident,
                                 generics,
@@ -362,24 +362,24 @@ impl Visitor<()> for Ctx {
     }
 
     fn visit_struct_field(@mut self, struct_field: @struct_field, _: ()) {
-        visit::visit_struct_field(self as @Visitor<()>, struct_field, ())
+        visit::visit_struct_field(self as @mut Visitor<()>, struct_field, ())
     }
 }
 
-pub fn map_crate(diag: @span_handler, c: &Crate) -> map {
+pub fn map_crate(diag: @mut span_handler, c: &Crate) -> map {
     let cx = @mut Ctx {
         map: @mut HashMap::new(),
         path: ~[],
         diag: diag,
     };
-    visit::visit_crate(cx as @Visitor<()>, c, ());
+    visit::visit_crate(cx as @mut Visitor<()>, c, ());
     cx.map
 }
 
 // Used for items loaded from external crate that are being inlined into this
 // crate.  The `path` should be the path to the item but should not include
 // the item itself.
-pub fn map_decoded_item(diag: @span_handler,
+pub fn map_decoded_item(diag: @mut span_handler,
                         map: map,
                         path: path,
                         ii: &inlined_item) {
@@ -409,7 +409,7 @@ pub fn map_decoded_item(diag: @span_handler,
     }
 
     // visit the item / method contents and add those to the map:
-    ii.accept((), cx as @Visitor<()>);
+    ii.accept((), cx as @mut Visitor<()>);
 }
 
 pub fn node_id_to_str(map: map, id: NodeId, itr: @ident_interner) -> ~str {
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 0005180ef50..d99f8cab493 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -298,7 +298,7 @@ pub fn struct_field_visibility(field: ast::struct_field) -> visibility {
 pub trait inlined_item_utils {
     fn ident(&self) -> ident;
     fn id(&self) -> ast::NodeId;
-    fn accept<E: Clone>(&self, e: E, v: @Visitor<E>);
+    fn accept<E: Clone>(&self, e: E, v: @mut Visitor<E>);
 }
 
 impl inlined_item_utils for inlined_item {
@@ -318,7 +318,7 @@ impl inlined_item_utils for inlined_item {
         }
     }
 
-    fn accept<E: Clone>(&self, e: E, v: @Visitor<E>) {
+    fn accept<E: Clone>(&self, e: E, v: @mut Visitor<E>) {
         match *self {
             ii_item(i) => v.visit_item(i, e),
             ii_foreign(i) => v.visit_foreign_item(i, e),
@@ -414,7 +414,7 @@ impl Visitor<()> for IdVisitor {
                  node_id: NodeId,
                  env: ()) {
         (self.visit_callback)(node_id);
-        visit::visit_mod(self as @Visitor<()>, module, env)
+        visit::visit_mod(self as @mut Visitor<()>, module, env)
     }
 
     fn visit_view_item(@mut self, view_item: &view_item, env: ()) {
@@ -439,12 +439,12 @@ impl Visitor<()> for IdVisitor {
                 }
             }
         }
-        visit::visit_view_item(self as @Visitor<()>, view_item, env)
+        visit::visit_view_item(self as @mut Visitor<()>, view_item, env)
     }
 
     fn visit_foreign_item(@mut self, foreign_item: @foreign_item, env: ()) {
         (self.visit_callback)(foreign_item.id);
-        visit::visit_foreign_item(self as @Visitor<()>, foreign_item, env)
+        visit::visit_foreign_item(self as @mut Visitor<()>, foreign_item, env)
     }
 
     fn visit_item(@mut self, item: @item, env: ()) {
@@ -466,39 +466,39 @@ impl Visitor<()> for IdVisitor {
             _ => {}
         }
 
-        visit::visit_item(self as @Visitor<()>, item, env);
+        visit::visit_item(self as @mut Visitor<()>, item, env);
 
         self.visited_outermost = false
     }
 
     fn visit_local(@mut self, local: @Local, env: ()) {
         (self.visit_callback)(local.id);
-        visit::visit_local(self as @Visitor<()>, local, env)
+        visit::visit_local(self as @mut Visitor<()>, local, env)
     }
 
     fn visit_block(@mut self, block: &Block, env: ()) {
         (self.visit_callback)(block.id);
-        visit::visit_block(self as @Visitor<()>, block, env)
+        visit::visit_block(self as @mut Visitor<()>, block, env)
     }
 
     fn visit_stmt(@mut self, statement: @stmt, env: ()) {
         (self.visit_callback)(ast_util::stmt_id(statement));
-        visit::visit_stmt(self as @Visitor<()>, statement, env)
+        visit::visit_stmt(self as @mut Visitor<()>, statement, env)
     }
 
     // XXX: Default
     fn visit_arm(@mut self, arm: &arm, env: ()) {
-        visit::visit_arm(self as @Visitor<()>, arm, env)
+        visit::visit_arm(self as @mut Visitor<()>, arm, env)
     }
 
     fn visit_pat(@mut self, pattern: @pat, env: ()) {
         (self.visit_callback)(pattern.id);
-        visit::visit_pat(self as @Visitor<()>, pattern, env)
+        visit::visit_pat(self as @mut Visitor<()>, pattern, env)
     }
 
     // XXX: Default
     fn visit_decl(@mut self, declaration: @decl, env: ()) {
-        visit::visit_decl(self as @Visitor<()>, declaration, env)
+        visit::visit_decl(self as @mut Visitor<()>, declaration, env)
     }
 
     fn visit_expr(@mut self, expression: @expr, env: ()) {
@@ -509,7 +509,7 @@ impl Visitor<()> for IdVisitor {
             }
         }
         (self.visit_callback)(expression.id);
-        visit::visit_expr(self as @Visitor<()>, expression, env)
+        visit::visit_expr(self as @mut Visitor<()>, expression, env)
     }
 
     // XXX: Default
@@ -523,12 +523,12 @@ impl Visitor<()> for IdVisitor {
             ty_path(_, _, id) => (self.visit_callback)(id),
             _ => {}
         }
-        visit::visit_ty(self as @Visitor<()>, typ, env)
+        visit::visit_ty(self as @mut Visitor<()>, typ, env)
     }
 
     fn visit_generics(@mut self, generics: &Generics, env: ()) {
         self.visit_generics_helper(generics);
-        visit::visit_generics(self as @Visitor<()>, generics, env)
+        visit::visit_generics(self as @mut Visitor<()>, generics, env)
     }
 
     fn visit_fn(@mut self,
@@ -563,7 +563,7 @@ impl Visitor<()> for IdVisitor {
             (self.visit_callback)(argument.id)
         }
 
-        visit::visit_fn(self as @Visitor<()>,
+        visit::visit_fn(self as @mut Visitor<()>,
                         function_kind,
                         function_declaration,
                         block,
@@ -581,12 +581,12 @@ impl Visitor<()> for IdVisitor {
 
     // XXX: Default
     fn visit_ty_method(@mut self, type_method: &TypeMethod, env: ()) {
-        visit::visit_ty_method(self as @Visitor<()>, type_method, env)
+        visit::visit_ty_method(self as @mut Visitor<()>, type_method, env)
     }
 
     // XXX: Default
     fn visit_trait_method(@mut self, trait_method: &trait_method, env: ()) {
-        visit::visit_trait_method(self as @Visitor<()>, trait_method, env)
+        visit::visit_trait_method(self as @mut Visitor<()>, trait_method, env)
     }
 
     // XXX: Default
@@ -596,7 +596,7 @@ impl Visitor<()> for IdVisitor {
                         generics: &Generics,
                         node_id: NodeId,
                         env: ()) {
-        visit::visit_struct_def(self as @Visitor<()>,
+        visit::visit_struct_def(self as @mut Visitor<()>,
                                 struct_definition,
                                 identifier,
                                 generics,
@@ -606,18 +606,18 @@ impl Visitor<()> for IdVisitor {
 
     fn visit_struct_field(@mut self, struct_field: @struct_field, env: ()) {
         (self.visit_callback)(struct_field.node.id);
-        visit::visit_struct_field(self as @Visitor<()>, struct_field, env)
+        visit::visit_struct_field(self as @mut Visitor<()>, struct_field, env)
     }
 }
 
 pub fn id_visitor(vfn: @fn(NodeId), pass_through_items: bool)
-                  -> @Visitor<()> {
-    let visitor = @IdVisitor {
+                  -> @mut Visitor<()> {
+    let visitor = @mut IdVisitor {
         visit_callback: vfn,
         pass_through_items: pass_through_items,
         visited_outermost: false,
     };
-    visitor as @Visitor<()>
+    visitor as @mut Visitor<()>
 }
 
 pub fn visit_ids_for_inlined_item(item: &inlined_item, vfn: @fn(NodeId)) {
@@ -757,9 +757,9 @@ impl EachViewItem for ast::Crate {
             callback: f,
         };
         let visitor = @mut SimpleVisitorVisitor {
-            simple_visitor: data as @SimpleVisitor,
+            simple_visitor: data as @mut SimpleVisitor,
         };
-        visit::visit_crate(visitor as @Visitor<()>, self, ());
+        visit::visit_crate(visitor as @mut Visitor<()>, self, ());
         true
     }
 }
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index b0dda2b7dc8..47d8ebecca0 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -313,7 +313,7 @@ pub fn test_cfg<AM: AttrMetaMethods, It: Iterator<AM>>
     no_cfgs || some_cfg_matches
 }
 
-pub fn require_unique_names(diagnostic: @span_handler,
+pub fn require_unique_names(diagnostic: @mut span_handler,
                             metas: &[@MetaItem]) {
     let mut set = HashSet::new();
     for meta in metas.iter() {
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index 2b6cb91a5df..5cdfe8e0f11 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -50,7 +50,7 @@ pub trait span_handler {
     fn span_note(@mut self, sp: span, msg: &str);
     fn span_bug(@mut self, sp: span, msg: &str) -> !;
     fn span_unimpl(@mut self, sp: span, msg: &str) -> !;
-    fn handler(@mut self) -> @handler;
+    fn handler(@mut self) -> @mut handler;
 }
 
 struct HandlerT {
@@ -59,7 +59,7 @@ struct HandlerT {
 }
 
 struct CodemapT {
-    handler: @handler,
+    handler: @mut handler,
     cm: @codemap::CodeMap,
 }
 
@@ -84,7 +84,7 @@ impl span_handler for CodemapT {
     fn span_unimpl(@mut self, sp: span, msg: &str) -> ! {
         self.span_bug(sp, ~"unimplemented " + msg);
     }
-    fn handler(@mut self) -> @handler {
+    fn handler(@mut self) -> @mut handler {
         self.handler
     }
 }
@@ -143,12 +143,12 @@ pub fn ice_msg(msg: &str) -> ~str {
     fmt!("internal compiler error: %s", msg)
 }
 
-pub fn mk_span_handler(handler: @handler, cm: @codemap::CodeMap)
-                    -> @span_handler {
-    @mut CodemapT { handler: handler, cm: cm } as @span_handler
+pub fn mk_span_handler(handler: @mut handler, cm: @codemap::CodeMap)
+                    -> @mut span_handler {
+    @mut CodemapT { handler: handler, cm: cm } as @mut span_handler
 }
 
-pub fn mk_handler(emitter: Option<Emitter>) -> @handler {
+pub fn mk_handler(emitter: Option<Emitter>) -> @mut handler {
     let emit: Emitter = match emitter {
         Some(e) => e,
         None => {
@@ -157,7 +157,7 @@ pub fn mk_handler(emitter: Option<Emitter>) -> @handler {
         }
     };
 
-    @mut HandlerT { err_count: 0, emit: emit } as @handler
+    @mut HandlerT { err_count: 0, emit: emit } as @mut handler
 }
 
 #[deriving(Eq)]
@@ -341,7 +341,7 @@ fn print_macro_backtrace(cm: @codemap::CodeMap, sp: span) {
     }
 }
 
-pub fn expect<T:Clone>(diag: @span_handler,
+pub fn expect<T:Clone>(diag: @mut span_handler,
                        opt: Option<T>,
                        msg: &fn() -> ~str) -> T {
     match opt {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 1963f3aef49..1547446957e 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -548,52 +548,52 @@ impl Visitor<()> for NewNameFinderContext {
                 }
             }
             // use the default traversal for non-pat_idents
-            _ => visit::visit_pat(self as @Visitor<()>, pattern, ())
+            _ => visit::visit_pat(self as @mut Visitor<()>, pattern, ())
         }
     }
 
     // XXX: Methods below can become default methods.
 
     fn visit_mod(@mut self, module: &ast::_mod, _: span, _: NodeId, _: ()) {
-        visit::visit_mod(self as @Visitor<()>, module, ())
+        visit::visit_mod(self as @mut Visitor<()>, module, ())
     }
 
     fn visit_view_item(@mut self, view_item: &ast::view_item, _: ()) {
-        visit::visit_view_item(self as @Visitor<()>, view_item, ())
+        visit::visit_view_item(self as @mut Visitor<()>, view_item, ())
     }
 
     fn visit_item(@mut self, item: @ast::item, _: ()) {
-        visit::visit_item(self as @Visitor<()>, item, ())
+        visit::visit_item(self as @mut Visitor<()>, item, ())
     }
 
     fn visit_foreign_item(@mut self,
                           foreign_item: @ast::foreign_item,
                           _: ()) {
-        visit::visit_foreign_item(self as @Visitor<()>, foreign_item, ())
+        visit::visit_foreign_item(self as @mut Visitor<()>, foreign_item, ())
     }
 
     fn visit_local(@mut self, local: @ast::Local, _: ()) {
-        visit::visit_local(self as @Visitor<()>, local, ())
+        visit::visit_local(self as @mut Visitor<()>, local, ())
     }
 
     fn visit_block(@mut self, block: &ast::Block, _: ()) {
-        visit::visit_block(self as @Visitor<()>, block, ())
+        visit::visit_block(self as @mut Visitor<()>, block, ())
     }
 
     fn visit_stmt(@mut self, stmt: @ast::stmt, _: ()) {
-        visit::visit_stmt(self as @Visitor<()>, stmt, ())
+        visit::visit_stmt(self as @mut Visitor<()>, stmt, ())
     }
 
     fn visit_arm(@mut self, arm: &ast::arm, _: ()) {
-        visit::visit_arm(self as @Visitor<()>, arm, ())
+        visit::visit_arm(self as @mut Visitor<()>, arm, ())
     }
 
     fn visit_decl(@mut self, decl: @ast::decl, _: ()) {
-        visit::visit_decl(self as @Visitor<()>, decl, ())
+        visit::visit_decl(self as @mut Visitor<()>, decl, ())
     }
 
     fn visit_expr(@mut self, expr: @ast::expr, _: ()) {
-        visit::visit_expr(self as @Visitor<()>, expr, ())
+        visit::visit_expr(self as @mut Visitor<()>, expr, ())
     }
 
     fn visit_expr_post(@mut self, _: @ast::expr, _: ()) {
@@ -601,11 +601,11 @@ impl Visitor<()> for NewNameFinderContext {
     }
 
     fn visit_ty(@mut self, typ: &ast::Ty, _: ()) {
-        visit::visit_ty(self as @Visitor<()>, typ, ())
+        visit::visit_ty(self as @mut Visitor<()>, typ, ())
     }
 
     fn visit_generics(@mut self, generics: &ast::Generics, _: ()) {
-        visit::visit_generics(self as @Visitor<()>, generics, ())
+        visit::visit_generics(self as @mut Visitor<()>, generics, ())
     }
 
     fn visit_fn(@mut self,
@@ -615,7 +615,7 @@ impl Visitor<()> for NewNameFinderContext {
                 span: span,
                 node_id: NodeId,
                 _: ()) {
-        visit::visit_fn(self as @Visitor<()>,
+        visit::visit_fn(self as @mut Visitor<()>,
                         function_kind,
                         function_declaration,
                         block,
@@ -625,13 +625,13 @@ impl Visitor<()> for NewNameFinderContext {
     }
 
     fn visit_ty_method(@mut self, ty_method: &ast::TypeMethod, _: ()) {
-        visit::visit_ty_method(self as @Visitor<()>, ty_method, ())
+        visit::visit_ty_method(self as @mut Visitor<()>, ty_method, ())
     }
 
     fn visit_trait_method(@mut self,
                           trait_method: &ast::trait_method,
                           _: ()) {
-        visit::visit_trait_method(self as @Visitor<()>, trait_method, ())
+        visit::visit_trait_method(self as @mut Visitor<()>, trait_method, ())
     }
 
     fn visit_struct_def(@mut self,
@@ -640,7 +640,7 @@ impl Visitor<()> for NewNameFinderContext {
                         generics: &ast::Generics,
                         node_id: NodeId,
                         _: ()) {
-        visit::visit_struct_def(self as @Visitor<()>,
+        visit::visit_struct_def(self as @mut Visitor<()>,
                                 struct_def,
                                 ident,
                                 generics,
@@ -651,18 +651,18 @@ impl Visitor<()> for NewNameFinderContext {
     fn visit_struct_field(@mut self,
                           struct_field: @ast::struct_field,
                           _: ()) {
-        visit::visit_struct_field(self as @Visitor<()>, struct_field, ())
+        visit::visit_struct_field(self as @mut Visitor<()>, struct_field, ())
     }
 }
 
 // return a visitor that extracts the pat_ident paths
 // from a given pattern and puts them in a mutable
 // array (passed in to the traversal)
-pub fn new_name_finder(idents: @mut ~[ast::ident]) -> @Visitor<()> {
+pub fn new_name_finder(idents: @mut ~[ast::ident]) -> @mut Visitor<()> {
     let context = @mut NewNameFinderContext {
         ident_accumulator: idents,
     };
-    context as @Visitor<()>
+    context as @mut Visitor<()>
 }
 
 pub fn expand_block(extsbox: @mut SyntaxEnv,
diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs
index f7f17d3ba64..f3e7613d96a 100644
--- a/src/libsyntax/ext/trace_macros.rs
+++ b/src/libsyntax/ext/trace_macros.rs
@@ -25,7 +25,7 @@ pub fn expand_trace_macros(cx: @ExtCtxt,
     let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic,
                                None,
                                tt.to_owned());
-    let rdr = tt_rdr as @reader;
+    let rdr = tt_rdr as @mut reader;
     let rust_parser = Parser(sess, cfg.clone(), rdr.dup());
 
     if rust_parser.is_keyword(keywords::True) {
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 29963a7b461..c208a7f7e3e 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -224,7 +224,7 @@ pub enum parse_result {
 pub fn parse_or_else(
     sess: @mut ParseSess,
     cfg: ast::CrateConfig,
-    rdr: @reader,
+    rdr: @mut reader,
     ms: ~[matcher]
 ) -> HashMap<ident, @named_match> {
     match parse(sess, cfg, rdr, ms) {
@@ -237,7 +237,7 @@ pub fn parse_or_else(
 pub fn parse(
     sess: @mut ParseSess,
     cfg: ast::CrateConfig,
-    rdr: @reader,
+    rdr: @mut reader,
     ms: &[matcher]
 ) -> parse_result {
     let mut cur_eis = ~[];
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 10735dad32f..54ac1f1e48f 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -59,7 +59,7 @@ pub fn add_new_extension(cx: @ExtCtxt,
                                    arg.clone());
     let argument_map = parse_or_else(cx.parse_sess(),
                                      cx.cfg(),
-                                     arg_reader as @reader,
+                                     arg_reader as @mut reader,
                                      argument_gram);
 
     // Extract the arguments:
@@ -101,7 +101,7 @@ pub fn add_new_extension(cx: @ExtCtxt,
                     s_d,
                     None,
                     arg.to_owned()
-                ) as @reader;
+                ) as @mut reader;
                 match parse(cx.parse_sess(), cx.cfg(), arg_rdr, *mtcs) {
                   success(named_matches) => {
                     let rhs = match rhses[i] {
@@ -123,7 +123,7 @@ pub fn add_new_extension(cx: @ExtCtxt,
                                                rhs);
                     let p = @Parser(cx.parse_sess(),
                                     cx.cfg(),
-                                    trncbr as @reader);
+                                    trncbr as @mut reader);
 
                     // Let the context choose how to interpret the result.
                     // Weird, but useful for X-macros.
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index 9d3e916b500..13bad252243 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -30,7 +30,7 @@ struct TtFrame {
 }
 
 pub struct TtReader {
-    sp_diag: @span_handler,
+    sp_diag: @mut span_handler,
     // the unzipped tree:
     stack: @mut TtFrame,
     /* for MBE-style macro transcription */
@@ -45,7 +45,7 @@ pub struct TtReader {
 /** 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. */
-pub fn new_tt_reader(sp_diag: @span_handler,
+pub fn new_tt_reader(sp_diag: @mut span_handler,
                      interp: Option<HashMap<ident,@named_match>>,
                      src: ~[ast::token_tree])
                   -> @mut TtReader {
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs
index 5b9725ec6a0..9a9164f5102 100644
--- a/src/libsyntax/parse/comments.rs
+++ b/src/libsyntax/parse/comments.rs
@@ -267,7 +267,7 @@ fn read_block_comment(rdr: @mut StringReader,
         while level > 0 {
             debug!("=== block comment level %d", level);
             if is_eof(rdr) {
-                (rdr as @reader).fatal(~"unterminated block comment");
+                (rdr as @mut reader).fatal(~"unterminated block comment");
             }
             if rdr.curr == '\n' {
                 trim_whitespace_prefix_and_push_line(&mut lines, curr_line,
@@ -334,7 +334,7 @@ pub struct lit {
 // it appears this function is called only from pprust... that's
 // probably not a good thing.
 pub fn gather_comments_and_literals(span_diagnostic:
-                                    @diagnostic::span_handler,
+                                    @mut diagnostic::span_handler,
                                     path: @str,
                                     srdr: @io::Reader)
                                  -> (~[cmnt], ~[lit]) {
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index bde568b2610..d0041021f7c 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -28,9 +28,9 @@ pub trait reader {
     fn is_eof(@mut self) -> bool;
     fn next_token(@mut self) -> TokenAndSpan;
     fn fatal(@mut self, ~str) -> !;
-    fn span_diag(@mut self) -> @span_handler;
+    fn span_diag(@mut self) -> @mut span_handler;
     fn peek(@mut self) -> TokenAndSpan;
-    fn dup(@mut self) -> @reader;
+    fn dup(@mut self) -> @mut reader;
 }
 
 #[deriving(Clone, Eq)]
@@ -40,7 +40,7 @@ pub struct TokenAndSpan {
 }
 
 pub struct StringReader {
-    span_diagnostic: @span_handler,
+    span_diagnostic: @mut span_handler,
     src: @str,
     // The absolute offset within the codemap of the next character to read
     pos: BytePos,
@@ -56,7 +56,7 @@ pub struct StringReader {
     peek_span: span
 }
 
-pub fn new_string_reader(span_diagnostic: @span_handler,
+pub fn new_string_reader(span_diagnostic: @mut span_handler,
                          filemap: @codemap::FileMap)
                       -> @mut StringReader {
     let r = new_low_level_string_reader(span_diagnostic, filemap);
@@ -65,13 +65,14 @@ pub fn new_string_reader(span_diagnostic: @span_handler,
 }
 
 /* For comments.rs, which hackily pokes into 'pos' and 'curr' */
-pub fn new_low_level_string_reader(span_diagnostic: @span_handler,
+pub fn new_low_level_string_reader(span_diagnostic: @mut span_handler,
                                    filemap: @codemap::FileMap)
                                 -> @mut StringReader {
     // Force the initial reader bump to start on a fresh line
     let initial_char = '\n';
     let r = @mut StringReader {
-        span_diagnostic: span_diagnostic, src: filemap.src,
+        span_diagnostic: span_diagnostic,
+        src: filemap.src,
         pos: filemap.start_pos,
         last_pos: filemap.start_pos,
         col: CharPos(0),
@@ -116,7 +117,7 @@ impl reader for StringReader {
     fn fatal(@mut self, m: ~str) -> ! {
         self.span_diagnostic.span_fatal(self.peek_span, m)
     }
-    fn span_diag(@mut self) -> @span_handler { self.span_diagnostic }
+    fn span_diag(@mut self) -> @mut span_handler { self.span_diagnostic }
     fn peek(@mut self) -> TokenAndSpan {
         // XXX(pcwalton): Bad copy!
         TokenAndSpan {
@@ -124,7 +125,7 @@ impl reader for StringReader {
             sp: self.peek_span,
         }
     }
-    fn dup(@mut self) -> @reader { dup_string_reader(self) as @reader }
+    fn dup(@mut self) -> @mut reader { dup_string_reader(self) as @mut reader }
 }
 
 impl reader for TtReader {
@@ -137,14 +138,14 @@ impl reader for TtReader {
     fn fatal(@mut self, m: ~str) -> ! {
         self.sp_diag.span_fatal(self.cur_span, m);
     }
-    fn span_diag(@mut self) -> @span_handler { self.sp_diag }
+    fn span_diag(@mut self) -> @mut span_handler { self.sp_diag }
     fn peek(@mut self) -> TokenAndSpan {
         TokenAndSpan {
             tok: self.cur_tok.clone(),
             sp: self.cur_span,
         }
     }
-    fn dup(@mut self) -> @reader { dup_tt_reader(self) as @reader }
+    fn dup(@mut self) -> @mut reader { dup_tt_reader(self) as @mut reader }
 }
 
 // EFFECT: advance peek_tok and peek_span to refer to the next token.
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 1731a587a8e..23c6a8b9720 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -43,7 +43,7 @@ pub mod obsolete;
 pub struct ParseSess {
     cm: @codemap::CodeMap, // better be the same as the one in the reader!
     next_id: NodeId,
-    span_diagnostic: @span_handler, // better be the same as the one in the reader!
+    span_diagnostic: @mut span_handler, // better be the same as the one in the reader!
     /// Used to determine and report recursive mod inclusions
     included_mod_stack: ~[Path],
 }
@@ -58,7 +58,7 @@ pub fn new_parse_sess(demitter: Option<Emitter>) -> @mut ParseSess {
     }
 }
 
-pub fn new_parse_sess_special_handler(sh: @span_handler,
+pub fn new_parse_sess_special_handler(sh: @mut span_handler,
                                       cm: @codemap::CodeMap)
                                    -> @mut ParseSess {
     @mut ParseSess {
@@ -306,7 +306,7 @@ pub fn filemap_to_tts(sess: @mut ParseSess, filemap: @FileMap)
     // parsing tt's probably shouldn't require a parser at all.
     let cfg = ~[];
     let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap);
-    let p1 = Parser(sess, cfg, srdr as @reader);
+    let p1 = Parser(sess, cfg, srdr as @mut reader);
     p1.parse_all_token_trees()
 }
 
@@ -315,7 +315,7 @@ pub fn tts_to_parser(sess: @mut ParseSess,
                      tts: ~[ast::token_tree],
                      cfg: ast::CrateConfig) -> Parser {
     let trdr = lexer::new_tt_reader(sess.span_diagnostic, None, tts);
-    Parser(sess, cfg, trdr as @reader)
+    Parser(sess, cfg, trdr as @mut reader)
 }
 
 // abort if necessary
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 59db1a3cfa2..27e339f000c 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -265,7 +265,7 @@ struct ParsedItemsAndViewItems {
 
 pub fn Parser(sess: @mut ParseSess,
               cfg: ast::CrateConfig,
-              rdr: @reader)
+              rdr: @mut reader)
            -> Parser {
     let tok0 = rdr.next_token();
     let interner = get_ident_interner();
@@ -315,7 +315,7 @@ pub struct Parser {
     tokens_consumed: @mut uint,
     restriction: @mut restriction,
     quote_depth: @mut uint, // not (yet) related to the quasiquoter
-    reader: @reader,
+    reader: @mut reader,
     interner: @token::ident_interner,
     /// The set of seen errors about obsolete syntax. Used to suppress
     /// extra detail when the same error is seen twice
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index ffe9575a864..6a3d829aca0 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -104,7 +104,7 @@ pub static default_columns: uint = 78u;
 // copy forward.
 pub fn print_crate(cm: @CodeMap,
                    intr: @ident_interner,
-                   span_diagnostic: @diagnostic::span_handler,
+                   span_diagnostic: @mut diagnostic::span_handler,
                    crate: &ast::Crate,
                    filename: @str,
                    input: @io::Reader,
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 7aa52bc13e3..c3a5ba7116d 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -88,11 +88,11 @@ pub trait Visitor<E> {
     fn visit_struct_field(@mut self, @struct_field, E);
 }
 
-pub fn visit_crate<E:Clone>(visitor: @Visitor<E>, crate: &Crate, env: E) {
+pub fn visit_crate<E:Clone>(visitor: @mut Visitor<E>, crate: &Crate, env: E) {
     visitor.visit_mod(&crate.module, crate.span, CRATE_NODE_ID, env)
 }
 
-pub fn visit_mod<E:Clone>(visitor: @Visitor<E>, module: &_mod, env: E) {
+pub fn visit_mod<E:Clone>(visitor: @mut Visitor<E>, module: &_mod, env: E) {
     for view_item in module.view_items.iter() {
         visitor.visit_view_item(view_item, env.clone())
     }
@@ -101,11 +101,11 @@ pub fn visit_mod<E:Clone>(visitor: @Visitor<E>, module: &_mod, env: E) {
     }
 }
 
-pub fn visit_view_item<E:Clone>(_: @Visitor<E>, _: &view_item, _: E) {
+pub fn visit_view_item<E:Clone>(_: @mut Visitor<E>, _: &view_item, _: E) {
     // Empty!
 }
 
-pub fn visit_local<E:Clone>(visitor: @Visitor<E>, local: &Local, env: E) {
+pub fn visit_local<E:Clone>(visitor: @mut Visitor<E>, local: &Local, env: E) {
     visitor.visit_pat(local.pat, env.clone());
     visitor.visit_ty(&local.ty, env.clone());
     match local.init {
@@ -114,13 +114,13 @@ pub fn visit_local<E:Clone>(visitor: @Visitor<E>, local: &Local, env: E) {
     }
 }
 
-fn visit_trait_ref<E:Clone>(visitor: @Visitor<E>,
+fn visit_trait_ref<E:Clone>(visitor: @mut Visitor<E>,
                             trait_ref: &ast::trait_ref,
                             env: E) {
     visit_path(visitor, &trait_ref.path, env)
 }
 
-pub fn visit_item<E:Clone>(visitor: @Visitor<E>, item: &item, env: E) {
+pub fn visit_item<E:Clone>(visitor: @mut Visitor<E>, item: &item, env: E) {
     match item.node {
         item_static(ref typ, _, expr) => {
             visitor.visit_ty(typ, env.clone());
@@ -187,7 +187,7 @@ pub fn visit_item<E:Clone>(visitor: @Visitor<E>, item: &item, env: E) {
     }
 }
 
-pub fn visit_enum_def<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_enum_def<E:Clone>(visitor: @mut Visitor<E>,
                                enum_definition: &ast::enum_def,
                                generics: &Generics,
                                env: E) {
@@ -209,11 +209,11 @@ pub fn visit_enum_def<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn skip_ty<E>(_: @Visitor<E>, _: &Ty, _: E) {
+pub fn skip_ty<E>(_: @mut Visitor<E>, _: &Ty, _: E) {
     // Empty!
 }
 
-pub fn visit_ty<E:Clone>(visitor: @Visitor<E>, typ: &Ty, env: E) {
+pub fn visit_ty<E:Clone>(visitor: @mut Visitor<E>, typ: &Ty, env: E) {
     match typ.node {
         ty_box(ref mutable_type) | ty_uniq(ref mutable_type) |
         ty_vec(ref mutable_type) | ty_ptr(ref mutable_type) |
@@ -254,13 +254,13 @@ pub fn visit_ty<E:Clone>(visitor: @Visitor<E>, typ: &Ty, env: E) {
     }
 }
 
-pub fn visit_path<E:Clone>(visitor: @Visitor<E>, path: &Path, env: E) {
+pub fn visit_path<E:Clone>(visitor: @mut Visitor<E>, path: &Path, env: E) {
     for typ in path.types.iter() {
         visitor.visit_ty(typ, env.clone())
     }
 }
 
-pub fn visit_pat<E:Clone>(visitor: @Visitor<E>, pattern: &pat, env: E) {
+pub fn visit_pat<E:Clone>(visitor: @mut Visitor<E>, pattern: &pat, env: E) {
     match pattern.node {
         pat_enum(ref path, ref children) => {
             visit_path(visitor, path, env.clone());
@@ -313,7 +313,7 @@ pub fn visit_pat<E:Clone>(visitor: @Visitor<E>, pattern: &pat, env: E) {
     }
 }
 
-pub fn visit_foreign_item<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_foreign_item<E:Clone>(visitor: @mut Visitor<E>,
                                    foreign_item: &foreign_item,
                                    env: E) {
     match foreign_item.node {
@@ -325,7 +325,7 @@ pub fn visit_foreign_item<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_ty_param_bounds<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_ty_param_bounds<E:Clone>(visitor: @mut Visitor<E>,
                                       bounds: &OptVec<TyParamBound>,
                                       env: E) {
     for bound in bounds.iter() {
@@ -338,7 +338,7 @@ pub fn visit_ty_param_bounds<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_generics<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_generics<E:Clone>(visitor: @mut Visitor<E>,
                                generics: &Generics,
                                env: E) {
     for type_parameter in generics.ty_params.iter() {
@@ -346,7 +346,7 @@ pub fn visit_generics<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_fn_decl<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_fn_decl<E:Clone>(visitor: @mut Visitor<E>,
                               function_declaration: &fn_decl,
                               env: E) {
     for argument in function_declaration.inputs.iter() {
@@ -360,7 +360,7 @@ pub fn visit_fn_decl<E:Clone>(visitor: @Visitor<E>,
 // visit_fn() and check for fk_method().  I named this visit_method_helper()
 // because it is not a default impl of any method, though I doubt that really
 // clarifies anything. - Niko
-pub fn visit_method_helper<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_method_helper<E:Clone>(visitor: @mut Visitor<E>,
                                     method: &method,
                                     env: E) {
     visitor.visit_fn(&fk_method(method.ident, &method.generics, method),
@@ -371,7 +371,7 @@ pub fn visit_method_helper<E:Clone>(visitor: @Visitor<E>,
                      env)
 }
 
-pub fn visit_fn<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_fn<E:Clone>(visitor: @mut Visitor<E>,
                          function_kind: &fn_kind,
                          function_declaration: &fn_decl,
                          function_body: &Block,
@@ -384,7 +384,7 @@ pub fn visit_fn<E:Clone>(visitor: @Visitor<E>,
     visitor.visit_block(function_body, env)
 }
 
-pub fn visit_ty_method<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_ty_method<E:Clone>(visitor: @mut Visitor<E>,
                                 method_type: &TypeMethod,
                                 env: E) {
     for argument_type in method_type.decl.inputs.iter() {
@@ -394,7 +394,7 @@ pub fn visit_ty_method<E:Clone>(visitor: @Visitor<E>,
     visitor.visit_ty(&method_type.decl.output, env.clone())
 }
 
-pub fn visit_trait_method<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_trait_method<E:Clone>(visitor: @mut Visitor<E>,
                                    trait_method: &trait_method,
                                    env: E) {
     match *trait_method {
@@ -405,7 +405,7 @@ pub fn visit_trait_method<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_struct_def<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_struct_def<E:Clone>(visitor: @mut Visitor<E>,
                                  struct_definition: @struct_def,
                                  _: ast::ident,
                                  _: &Generics,
@@ -416,13 +416,13 @@ pub fn visit_struct_def<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_struct_field<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_struct_field<E:Clone>(visitor: @mut Visitor<E>,
                                    struct_field: &struct_field,
                                    env: E) {
     visitor.visit_ty(&struct_field.node.ty, env)
 }
 
-pub fn visit_block<E:Clone>(visitor: @Visitor<E>, block: &Block, env: E) {
+pub fn visit_block<E:Clone>(visitor: @mut Visitor<E>, block: &Block, env: E) {
     for view_item in block.view_items.iter() {
         visitor.visit_view_item(view_item, env.clone())
     }
@@ -432,7 +432,7 @@ pub fn visit_block<E:Clone>(visitor: @Visitor<E>, block: &Block, env: E) {
     visit_expr_opt(visitor, block.expr, env)
 }
 
-pub fn visit_stmt<E>(visitor: @Visitor<E>, statement: &stmt, env: E) {
+pub fn visit_stmt<E>(visitor: @mut Visitor<E>, statement: &stmt, env: E) {
     match statement.node {
         stmt_decl(declaration, _) => visitor.visit_decl(declaration, env),
         stmt_expr(expression, _) | stmt_semi(expression, _) => {
@@ -442,14 +442,14 @@ pub fn visit_stmt<E>(visitor: @Visitor<E>, statement: &stmt, env: E) {
     }
 }
 
-pub fn visit_decl<E:Clone>(visitor: @Visitor<E>, declaration: &decl, env: E) {
+pub fn visit_decl<E:Clone>(visitor: @mut Visitor<E>, declaration: &decl, env: E) {
     match declaration.node {
         decl_local(ref local) => visitor.visit_local(*local, env),
         decl_item(item) => visitor.visit_item(item, env),
     }
 }
 
-pub fn visit_expr_opt<E>(visitor: @Visitor<E>,
+pub fn visit_expr_opt<E>(visitor: @mut Visitor<E>,
                          optional_expression: Option<@expr>,
                          env: E) {
     match optional_expression {
@@ -458,7 +458,7 @@ pub fn visit_expr_opt<E>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_exprs<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_exprs<E:Clone>(visitor: @mut Visitor<E>,
                             expressions: &[@expr],
                             env: E) {
     for expression in expressions.iter() {
@@ -466,11 +466,11 @@ pub fn visit_exprs<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_mac<E>(_: @Visitor<E>, _: &mac, _: E) {
+pub fn visit_mac<E>(_: @mut Visitor<E>, _: &mac, _: E) {
     // Empty!
 }
 
-pub fn visit_expr<E:Clone>(visitor: @Visitor<E>, expression: @expr, env: E) {
+pub fn visit_expr<E:Clone>(visitor: @mut Visitor<E>, expression: @expr, env: E) {
     match expression.node {
         expr_vstore(subexpression, _) => {
             visitor.visit_expr(subexpression, env.clone())
@@ -595,7 +595,7 @@ pub fn visit_expr<E:Clone>(visitor: @Visitor<E>, expression: @expr, env: E) {
     visitor.visit_expr_post(expression, env.clone())
 }
 
-pub fn visit_arm<E:Clone>(visitor: @Visitor<E>, arm: &arm, env: E) {
+pub fn visit_arm<E:Clone>(visitor: @mut Visitor<E>, arm: &arm, env: E) {
     for pattern in arm.pats.iter() {
         visitor.visit_pat(*pattern, env.clone())
     }
@@ -630,7 +630,7 @@ pub trait SimpleVisitor {
 }
 
 pub struct SimpleVisitorVisitor {
-    simple_visitor: @SimpleVisitor,
+    simple_visitor: @mut SimpleVisitor,
 }
 
 impl Visitor<()> for SimpleVisitorVisitor {
@@ -640,58 +640,58 @@ impl Visitor<()> for SimpleVisitorVisitor {
                  node_id: NodeId,
                  env: ()) {
         self.simple_visitor.visit_mod(module, span, node_id);
-        visit_mod(self as @Visitor<()>, module, env)
+        visit_mod(self as @mut Visitor<()>, module, env)
     }
     fn visit_view_item(@mut self, view_item: &view_item, env: ()) {
         self.simple_visitor.visit_view_item(view_item);
-        visit_view_item(self as @Visitor<()>, view_item, env)
+        visit_view_item(self as @mut Visitor<()>, view_item, env)
     }
     fn visit_foreign_item(@mut self, foreign_item: @foreign_item, env: ()) {
         self.simple_visitor.visit_foreign_item(foreign_item);
-        visit_foreign_item(self as @Visitor<()>, foreign_item, env)
+        visit_foreign_item(self as @mut Visitor<()>, foreign_item, env)
     }
     fn visit_item(@mut self, item: @item, env: ()) {
         self.simple_visitor.visit_item(item);
-        visit_item(self as @Visitor<()>, item, env)
+        visit_item(self as @mut Visitor<()>, item, env)
     }
     fn visit_local(@mut self, local: @Local, env: ()) {
         self.simple_visitor.visit_local(local);
-        visit_local(self as @Visitor<()>, local, env)
+        visit_local(self as @mut Visitor<()>, local, env)
     }
     fn visit_block(@mut self, block: &Block, env: ()) {
         self.simple_visitor.visit_block(block);
-        visit_block(self as @Visitor<()>, block, env)
+        visit_block(self as @mut Visitor<()>, block, env)
     }
     fn visit_stmt(@mut self, statement: @stmt, env: ()) {
         self.simple_visitor.visit_stmt(statement);
-        visit_stmt(self as @Visitor<()>, statement, env)
+        visit_stmt(self as @mut Visitor<()>, statement, env)
     }
     fn visit_arm(@mut self, arm: &arm, env: ()) {
         self.simple_visitor.visit_arm(arm);
-        visit_arm(self as @Visitor<()>, arm, env)
+        visit_arm(self as @mut Visitor<()>, arm, env)
     }
     fn visit_pat(@mut self, pattern: @pat, env: ()) {
         self.simple_visitor.visit_pat(pattern);
-        visit_pat(self as @Visitor<()>, pattern, env)
+        visit_pat(self as @mut Visitor<()>, pattern, env)
     }
     fn visit_decl(@mut self, declaration: @decl, env: ()) {
         self.simple_visitor.visit_decl(declaration);
-        visit_decl(self as @Visitor<()>, declaration, env)
+        visit_decl(self as @mut Visitor<()>, declaration, env)
     }
     fn visit_expr(@mut self, expression: @expr, env: ()) {
         self.simple_visitor.visit_expr(expression);
-        visit_expr(self as @Visitor<()>, expression, env)
+        visit_expr(self as @mut Visitor<()>, expression, env)
     }
     fn visit_expr_post(@mut self, expression: @expr, _: ()) {
         self.simple_visitor.visit_expr_post(expression)
     }
     fn visit_ty(@mut self, typ: &Ty, env: ()) {
         self.simple_visitor.visit_ty(typ);
-        visit_ty(self as @Visitor<()>, typ, env)
+        visit_ty(self as @mut Visitor<()>, typ, env)
     }
     fn visit_generics(@mut self, generics: &Generics, env: ()) {
         self.simple_visitor.visit_generics(generics);
-        visit_generics(self as @Visitor<()>, generics, env)
+        visit_generics(self as @mut Visitor<()>, generics, env)
     }
     fn visit_fn(@mut self,
                 function_kind: &fn_kind,
@@ -705,7 +705,7 @@ impl Visitor<()> for SimpleVisitorVisitor {
                                      block,
                                      span,
                                      node_id);
-        visit_fn(self as @Visitor<()>,
+        visit_fn(self as @mut Visitor<()>,
                  function_kind,
                  function_declaration,
                  block,
@@ -715,11 +715,11 @@ impl Visitor<()> for SimpleVisitorVisitor {
     }
     fn visit_ty_method(@mut self, method_type: &TypeMethod, env: ()) {
         self.simple_visitor.visit_ty_method(method_type);
-        visit_ty_method(self as @Visitor<()>, method_type, env)
+        visit_ty_method(self as @mut Visitor<()>, method_type, env)
     }
     fn visit_trait_method(@mut self, trait_method: &trait_method, env: ()) {
         self.simple_visitor.visit_trait_method(trait_method);
-        visit_trait_method(self as @Visitor<()>, trait_method, env)
+        visit_trait_method(self as @mut Visitor<()>, trait_method, env)
     }
     fn visit_struct_def(@mut self,
                         struct_definition: @struct_def,
@@ -731,7 +731,7 @@ impl Visitor<()> for SimpleVisitorVisitor {
                                              identifier,
                                              generics,
                                              node_id);
-        visit_struct_def(self as @Visitor<()>,
+        visit_struct_def(self as @mut Visitor<()>,
                          struct_definition,
                          identifier,
                          generics,
@@ -740,7 +740,7 @@ impl Visitor<()> for SimpleVisitorVisitor {
     }
     fn visit_struct_field(@mut self, struct_field: @struct_field, env: ()) {
         self.simple_visitor.visit_struct_field(struct_field);
-        visit_struct_field(self as @Visitor<()>, struct_field, env)
+        visit_struct_field(self as @mut Visitor<()>, struct_field, env)
     }
 }
 
diff --git a/src/rt/rust_type.h b/src/rt/rust_type.h
index 60ca5674b01..57538f1ec75 100644
--- a/src/rt/rust_type.h
+++ b/src/rt/rust_type.h
@@ -58,6 +58,7 @@ struct type_desc {
     glue_fn *drop_glue;
     glue_fn *free_glue;
     glue_fn *visit_glue;
+    size_t borrow_offset;
 };
 
 extern "C" type_desc *rust_clone_type_desc(type_desc*);
diff --git a/src/rt/rust_util.cpp b/src/rt/rust_util.cpp
index 4a15830e529..28c69af427a 100644
--- a/src/rt/rust_util.cpp
+++ b/src/rt/rust_util.cpp
@@ -21,6 +21,7 @@ struct type_desc str_body_tydesc = {
     NULL, // drop_glue
     NULL, // free_glue
     NULL, // visit_glue
+    0, // borrow_offset
 };
 
 //
diff --git a/src/test/run-pass/unique-object.rs b/src/test/compile-fail/borrowck-borrow-mut-object-twice.rs
index e645f13cd4c..502d7e017b5 100644
--- a/src/test/run-pass/unique-object.rs
+++ b/src/test/compile-fail/borrowck-borrow-mut-object-twice.rs
@@ -8,22 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-trait Foo {
-    fn f(&self) -> int;
-}
+// Check that `&mut` objects cannot be borrowed twice, just like
+// other `&mut` pointers.
 
-struct Bar {
-    x: int
+trait Foo {
+    fn f1<'a>(&'a mut self) -> &'a ();
+    fn f2(&mut self);
 }
 
-impl Foo for Bar {
-    fn f(&self) -> int {
-        self.x
-    }
+fn test(x: &mut Foo) {
+    let _y = x.f1();
+    x.f2(); //~ ERROR cannot borrow `*x` as mutable more than once at a time
 }
 
-pub fn main() {
-    let x = ~Bar { x: 10 };
-    let y = x as ~Foo;
-    assert_eq!(y.f(), 10);
-}
+fn main() {}
diff --git a/src/test/compile-fail/borrowck-object-lifetime.rs b/src/test/compile-fail/borrowck-object-lifetime.rs
new file mode 100644
index 00000000000..25d5be7ed55
--- /dev/null
+++ b/src/test/compile-fail/borrowck-object-lifetime.rs
@@ -0,0 +1,42 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo {
+    fn borrowed<'a>(&'a self) -> &'a ();
+}
+
+fn borrowed_receiver<'a>(x: &'a Foo) -> &'a () {
+    x.borrowed()
+}
+
+fn managed_receiver(x: @Foo) -> &() {
+    x.borrowed() //~ ERROR cannot root managed value long enough
+}
+
+fn managed_receiver_1(x: @Foo) {
+    *x.borrowed()
+}
+
+fn owned_receiver(x: ~Foo) -> &() {
+    x.borrowed() //~ ERROR borrowed value does not live long enough
+}
+
+fn mut_owned_receiver(mut x: ~Foo) {
+    let _y = x.borrowed();
+    let _z = &mut x; //~ ERROR cannot borrow
+}
+
+fn imm_owned_receiver(mut x: ~Foo) {
+    let _y = x.borrowed();
+    let _z = &x;
+}
+
+fn main() {}
+
diff --git a/src/test/compile-fail/borrowck-object-mutability.rs b/src/test/compile-fail/borrowck-object-mutability.rs
new file mode 100644
index 00000000000..1ea9e3c8815
--- /dev/null
+++ b/src/test/compile-fail/borrowck-object-mutability.rs
@@ -0,0 +1,47 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo {
+    fn borrowed(&self);
+    fn borrowed_mut(&mut self);
+}
+
+fn borrowed_receiver(x: &Foo) {
+    x.borrowed();
+    x.borrowed_mut(); //~ ERROR cannot borrow
+}
+
+fn borrowed_mut_receiver(x: &mut Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+}
+
+fn managed_receiver(x: @Foo) {
+    x.borrowed();
+    x.borrowed_mut(); //~ ERROR cannot borrow
+}
+
+fn managed_mut_receiver(x: @mut Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+}
+
+fn owned_receiver(x: ~Foo) {
+    x.borrowed();
+    x.borrowed_mut(); //~ ERROR cannot borrow
+}
+
+fn mut_owned_receiver(mut x: ~Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+}
+
+fn main() {}
+
diff --git a/src/test/compile-fail/kindck-owned-trait-contains.rs b/src/test/compile-fail/kindck-owned-trait-contains.rs
index 19b38769d95..cf047674cd6 100644
--- a/src/test/compile-fail/kindck-owned-trait-contains.rs
+++ b/src/test/compile-fail/kindck-owned-trait-contains.rs
@@ -31,5 +31,4 @@ fn main() {
     //~^ ERROR dereference of reference outside its lifetime
     //~^^ ERROR automatically borrowed pointer is not valid at the time of borrow
     //~^^^ ERROR lifetime of return value does not outlive the function call
-    //~^^^^ ERROR cannot infer an appropriate lifetime
 }
diff --git a/src/test/compile-fail/object-pointer-types.rs b/src/test/compile-fail/object-pointer-types.rs
new file mode 100644
index 00000000000..b7d320fbab0
--- /dev/null
+++ b/src/test/compile-fail/object-pointer-types.rs
@@ -0,0 +1,64 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo {
+    fn borrowed(&self);
+    fn borrowed_mut(&mut self);
+
+    fn managed(@self);
+    fn managed_mut(@mut self);
+
+    fn owned(~self);
+}
+
+fn borrowed_receiver(x: &Foo) {
+    x.borrowed();
+    x.borrowed_mut(); // See [1]
+    x.managed(); //~ ERROR does not implement any method
+    x.managed_mut(); //~ ERROR does not implement any method
+    x.owned(); //~ ERROR does not implement any method
+}
+
+fn borrowed_mut_receiver(x: &mut Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+    x.managed(); //~ ERROR does not implement any method
+    x.managed_mut(); //~ ERROR does not implement any method
+    x.owned(); //~ ERROR does not implement any method
+}
+
+fn managed_receiver(x: @Foo) {
+    x.borrowed();
+    x.borrowed_mut(); // See [1]
+    x.managed();
+    x.managed_mut();  //~ ERROR does not implement any method
+    x.owned(); //~ ERROR does not implement any method
+}
+
+fn managed_mut_receiver(x: @mut Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+    x.managed();  //~ ERROR does not implement any method
+    x.managed_mut();
+    x.owned(); //~ ERROR does not implement any method
+}
+
+fn owned_receiver(x: ~Foo) {
+    x.borrowed();
+    x.borrowed_mut(); // See [1]
+    x.managed();  //~ ERROR does not implement any method
+    x.managed_mut();  //~ ERROR does not implement any method
+    x.owned();
+}
+
+fn main() {}
+
+// [1]: These cases are illegal, but the error is not detected
+// until borrowck, so see the test borrowck-object-mutability.rs
diff --git a/src/test/compile-fail/selftype-traittype.rs b/src/test/compile-fail/selftype-traittype.rs
index 220573660c5..b5484b786a0 100644
--- a/src/test/compile-fail/selftype-traittype.rs
+++ b/src/test/compile-fail/selftype-traittype.rs
@@ -13,7 +13,7 @@ trait add {
 }
 
 fn do_add(x: @add, y: @add) -> @add {
-    x.plus(y) //~ ERROR cannot call a method whose type contains a self-type through a boxed trait
+    x.plus(y) //~ ERROR cannot call a method whose type contains a self-type through an object
 }
 
 fn main() {}
diff --git a/src/test/run-fail/borrowck-wg-fail-object.rs b/src/test/run-fail/borrowck-wg-fail-object.rs
new file mode 100644
index 00000000000..73f2cf09552
--- /dev/null
+++ b/src/test/run-fail/borrowck-wg-fail-object.rs
@@ -0,0 +1,21 @@
+// error-pattern:borrowed
+
+trait Foo {
+    fn foo(&self, @mut int);
+}
+
+impl Foo for int {
+    fn foo(&self, x: @mut int) {
+        *x += *self;
+    }
+}
+
+fn main() {
+    let x = @mut 3_i;
+    let y = x as @mut Foo;
+
+    // The call to `y.foo(...)` should freeze `y` (and thus also `x`,
+    // since `x === y`). It is thus an error when `foo` tries to
+    // mutate `x`.
+    y.foo(x);
+}
diff --git a/src/test/run-pass/class-cast-to-trait.rs b/src/test/run-pass/class-cast-to-trait.rs
index a8ff9061216..737253a956f 100644
--- a/src/test/run-pass/class-cast-to-trait.rs
+++ b/src/test/run-pass/class-cast-to-trait.rs
@@ -56,6 +56,6 @@ fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat {
 
 
 pub fn main() {
-  let mut nyan: @noisy = @cat(0u, 2, ~"nyan") as @noisy;
+  let nyan: @mut noisy = @mut cat(0u, 2, ~"nyan") as @mut noisy;
   nyan.speak();
 }
diff --git a/src/test/run-pass/objects-owned-object-borrowed-method-header.rs b/src/test/run-pass/objects-owned-object-borrowed-method-header.rs
new file mode 100644
index 00000000000..23c271f53ca
--- /dev/null
+++ b/src/test/run-pass/objects-owned-object-borrowed-method-header.rs
@@ -0,0 +1,39 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test invoked `&self` methods on owned objects where the values
+// closed over contain managed values. This implies that the ~ boxes
+// will have headers that must be skipped over.
+
+trait FooTrait {
+    fn foo(&self) -> uint;
+}
+
+struct BarStruct {
+    x: @uint
+}
+
+impl FooTrait for BarStruct {
+    fn foo(&self) -> uint {
+        *self.x
+    }
+}
+
+pub fn main() {
+    let foos: ~[ ~FooTrait: ] = ~[
+        ~BarStruct{ x: @0 } as ~FooTrait:,
+        ~BarStruct{ x: @1 } as ~FooTrait:,
+        ~BarStruct{ x: @2 } as ~FooTrait:
+    ];
+
+    for i in range(0u, foos.len()) {
+        assert_eq!(i, foos[i].foo());
+    }
+}
diff --git a/src/test/run-pass/owned-trait-objects.rs b/src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs
index c9d0fde6d3c..72ae7cf9bb9 100644
--- a/src/test/run-pass/owned-trait-objects.rs
+++ b/src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// Test invoked `&self` methods on owned objects where the values
+// closed over do not contain managed values, and thus the ~ boxes do
+// not have headers.
+
 trait FooTrait {
     fn foo(&self) -> uint;
 }
diff --git a/src/test/run-pass/objects-owned-object-owned-method.rs b/src/test/run-pass/objects-owned-object-owned-method.rs
new file mode 100644
index 00000000000..0d675c16d1a
--- /dev/null
+++ b/src/test/run-pass/objects-owned-object-owned-method.rs
@@ -0,0 +1,32 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test invoked `&self` methods on owned objects where the values
+// closed over contain managed values. This implies that the ~ boxes
+// will have headers that must be skipped over.
+
+trait FooTrait {
+    fn foo(~self) -> uint;
+}
+
+struct BarStruct {
+    x: uint
+}
+
+impl FooTrait for BarStruct {
+    fn foo(~self) -> uint {
+        self.x
+    }
+}
+
+pub fn main() {
+    let foo = ~BarStruct{ x: 22 } as ~FooTrait;
+    assert_eq!(22, foo.foo());
+}
diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs
index 2a91d1fc8b5..8ab1bef286c 100644
--- a/src/test/run-pass/reflect-visit-data.rs
+++ b/src/test/run-pass/reflect-visit-data.rs
@@ -502,7 +502,7 @@ impl my_visitor {
         unsafe {
             let u = my_visitor(**self);
             let v = ptr_visit_adaptor::<my_visitor>(Inner {inner: u});
-            visit_tydesc(inner, @v as @TyVisitor);
+            visit_tydesc(inner, &v as &TyVisitor);
             true
         }
     }
@@ -662,7 +662,7 @@ pub fn main() {
         let td = get_tydesc_for(r);
         error!("tydesc sz: %u, align: %u",
                (*td).size, (*td).align);
-        let v = @v as @TyVisitor;
+        let v = &v as &TyVisitor;
         visit_tydesc(td, v);
 
         let r = u.vals.clone();
diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs
index 3ea597e0d59..544f42eb69f 100644
--- a/src/test/run-pass/reflect-visit-type.rs
+++ b/src/test/run-pass/reflect-visit-type.rs
@@ -79,7 +79,7 @@ impl TyVisitor for MyVisitor {
     fn visit_evec_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool {
         self.types.push(~"[");
         unsafe {
-            visit_tydesc(inner, (@*self) as @TyVisitor);
+            visit_tydesc(inner, (&*self) as &TyVisitor);
         }
         self.types.push(~"]");
         true
@@ -87,7 +87,7 @@ impl TyVisitor for MyVisitor {
     fn visit_evec_uniq_managed(&self, _mtbl: uint, inner: *TyDesc) -> bool {
         self.types.push(~"[");
         unsafe {
-            visit_tydesc(inner, (@*self) as @TyVisitor);
+            visit_tydesc(inner, (&*self) as &TyVisitor);
         }
         self.types.push(~"]");
         true
@@ -154,7 +154,7 @@ impl TyVisitor for MyVisitor {
     fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
 }
 
-fn visit_ty<T>(v: @TyVisitor) {
+fn visit_ty<T>(v: &TyVisitor) {
     unsafe {
         visit_tydesc(get_tydesc::<T>(), v);
     }