summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-10-05 16:55:42 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-10-05 16:57:13 -0700
commit04497ea7b9b9598faa7456e7de1304e9118d2bb0 (patch)
tree9ee04dec89c90fbbba0ef544a24e0f0f887c902c /src/rustc
parentf8bc0d25455d7bfb299cd0e7693ee575f5dbce21 (diff)
downloadrust-04497ea7b9b9598faa7456e7de1304e9118d2bb0.tar.gz
rust-04497ea7b9b9598faa7456e7de1304e9118d2bb0.zip
rustc: Implement simple uses of &trait
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/metadata/encoder.rs11
-rw-r--r--src/rustc/metadata/tyencode.rs1
-rw-r--r--src/rustc/middle/astencode.rs11
-rw-r--r--src/rustc/middle/privacy.rs2
-rw-r--r--src/rustc/middle/trans/common.rs9
-rw-r--r--src/rustc/middle/trans/glue.rs5
-rw-r--r--src/rustc/middle/trans/meth.rs38
-rw-r--r--src/rustc/middle/trans/reflect.rs4
-rw-r--r--src/rustc/middle/trans/type_of.rs2
-rw-r--r--src/rustc/middle/trans/type_use.rs2
-rw-r--r--src/rustc/middle/ty.rs29
-rw-r--r--src/rustc/middle/typeck.rs2
-rw-r--r--src/rustc/middle/typeck/astconv.rs17
-rw-r--r--src/rustc/middle/typeck/check/method.rs16
-rw-r--r--src/rustc/middle/typeck/check/regionck.rs6
-rw-r--r--src/rustc/middle/typeck/check/vtable.rs94
16 files changed, 180 insertions, 69 deletions
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index 87ef3b4749c..597640ef410 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -34,6 +34,7 @@ export metadata_encoding_version;
 export def_to_str;
 export encode_ctxt;
 export write_type;
+export write_vstore;
 export encode_def_id;
 
 type abbrev_map = map::HashMap<ty::t, tyencode::ty_abbrev>;
@@ -180,6 +181,16 @@ fn write_type(ecx: @encode_ctxt, ebml_w: ebml::Writer, typ: ty::t) {
     tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
 }
 
+fn write_vstore(ecx: @encode_ctxt, ebml_w: ebml::Writer, vstore: ty::vstore) {
+    let ty_str_ctxt =
+        @{diag: ecx.diag,
+          ds: def_to_str,
+          tcx: ecx.tcx,
+          reachable: |a| reachable(ecx, a),
+          abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
+    tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
+}
+
 fn encode_type(ecx: @encode_ctxt, ebml_w: ebml::Writer, typ: ty::t) {
     ebml_w.start_tag(tag_items_data_item_type);
     write_type(ecx, ebml_w, typ);
diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs
index 88d83ca23f4..611ffb598ae 100644
--- a/src/rustc/metadata/tyencode.rs
+++ b/src/rustc/metadata/tyencode.rs
@@ -16,6 +16,7 @@ export enc_ty;
 export enc_bounds;
 export enc_mode;
 export enc_arg;
+export enc_vstore;
 
 type ctxt = {
     diag: span_handler,
diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs
index 29368ae95b8..f2ee3df6610 100644
--- a/src/rustc/middle/astencode.rs
+++ b/src/rustc/middle/astencode.rs
@@ -490,8 +490,8 @@ impl method_origin: tr {
           typeck::method_param(mp) => {
             typeck::method_param({trait_id:mp.trait_id.tr(xcx),.. mp})
           }
-          typeck::method_trait(did, m) => {
-            typeck::method_trait(did.tr(xcx), m)
+          typeck::method_trait(did, m, vstore) => {
+            typeck::method_trait(did.tr(xcx), m, vstore)
           }
         }
     }
@@ -631,6 +631,7 @@ impl @e::encode_ctxt: get_ty_str_ctxt {
 trait ebml_writer_helpers {
     fn emit_arg(ecx: @e::encode_ctxt, arg: ty::arg);
     fn emit_ty(ecx: @e::encode_ctxt, ty: ty::t);
+    fn emit_vstore(ecx: @e::encode_ctxt, vstore: ty::vstore);
     fn emit_tys(ecx: @e::encode_ctxt, tys: ~[ty::t]);
     fn emit_bounds(ecx: @e::encode_ctxt, bs: ty::param_bounds);
     fn emit_tpbt(ecx: @e::encode_ctxt, tpbt: ty::ty_param_bounds_and_ty);
@@ -643,6 +644,12 @@ impl ebml::Writer: ebml_writer_helpers {
         }
     }
 
+    fn emit_vstore(ecx: @e::encode_ctxt, vstore: ty::vstore) {
+        do self.emit_opaque {
+            e::write_vstore(ecx, self, vstore)
+        }
+    }
+
     fn emit_arg(ecx: @e::encode_ctxt, arg: ty::arg) {
         do self.emit_opaque {
             tyencode::enc_arg(self.writer, ecx.ty_str_ctxt(), arg);
diff --git a/src/rustc/middle/privacy.rs b/src/rustc/middle/privacy.rs
index 4d291ceb590..f15ace40d30 100644
--- a/src/rustc/middle/privacy.rs
+++ b/src/rustc/middle/privacy.rs
@@ -81,7 +81,7 @@ fn check_crate(tcx: ty::ctxt, method_map: &method_map, crate: @ast::crate) {
                 }
             }
             method_param({trait_id: trait_id, 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/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs
index 6768f3e71a0..68e957bfe70 100644
--- a/src/rustc/middle/trans/common.rs
+++ b/src/rustc/middle/trans/common.rs
@@ -963,8 +963,13 @@ fn T_captured_tydescs(cx: @crate_ctxt, n: uint) -> TypeRef {
     return T_struct(vec::from_elem::<TypeRef>(n, T_ptr(cx.tydesc_type)));
 }
 
-fn T_opaque_trait(cx: @crate_ctxt) -> TypeRef {
-    T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)])
+fn T_opaque_trait(cx: @crate_ctxt, vstore: ty::vstore) -> TypeRef {
+    match vstore {
+        ty::vstore_box =>
+            T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)]),
+        _ =>
+            T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())])
+    }
 }
 
 fn T_opaque_port_ptr() -> TypeRef { return T_ptr(T_i8()); }
diff --git a/src/rustc/middle/trans/glue.rs b/src/rustc/middle/trans/glue.rs
index a8a750cd4be..d60a5a0bd7d 100644
--- a/src/rustc/middle/trans/glue.rs
+++ b/src/rustc/middle/trans/glue.rs
@@ -477,10 +477,13 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
       ty::ty_fn(_) => {
         closure::make_fn_glue(bcx, v0, t, drop_ty)
       }
-      ty::ty_trait(_, _, _) => {
+      ty::ty_trait(_, _, ty::vstore_box) => {
         let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u]));
         decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx))
       }
+      ty::ty_trait(_, _, ty::vstore_uniq) => {
+        ccx.tcx.sess.unimpl(~"drop of unique trait");
+      }
       ty::ty_opaque_closure_ptr(ck) => {
         closure::make_opaque_cbox_drop_glue(bcx, ck, v0)
       }
diff --git a/src/rustc/middle/trans/meth.rs b/src/rustc/middle/trans/meth.rs
index a94519306a4..6710a64054d 100644
--- a/src/rustc/middle/trans/meth.rs
+++ b/src/rustc/middle/trans/meth.rs
@@ -142,8 +142,8 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
                 None => fail ~"trans_method_callee: missing param_substs"
             }
         }
-        typeck::method_trait(_, off) => {
-            trans_trait_callee(bcx, callee_id, off, self)
+        typeck::method_trait(_, off, vstore) => {
+            trans_trait_callee(bcx, callee_id, off, self, vstore)
         }
     }
 }
@@ -288,8 +288,8 @@ fn trans_monomorphized_callee(bcx: block,
               })
           }
       }
-      typeck::vtable_trait(*) => {
-          trans_trait_callee(bcx, callee_id, n_method, base)
+      typeck::vtable_trait(_, _) => {
+          trans_trait_callee(bcx, callee_id, n_method, base, ty::vstore_box)
       }
       typeck::vtable_param(*) => {
           fail ~"vtable_param left in monomorphized function's vtable substs";
@@ -390,7 +390,8 @@ fn combine_impl_and_methods_origins(bcx: block,
 fn trans_trait_callee(bcx: block,
                       callee_id: ast::node_id,
                       n_method: uint,
-                      self_expr: @ast::expr)
+                      self_expr: @ast::expr,
+                      vstore: ty::vstore)
     -> Callee
 {
     //!
@@ -398,8 +399,8 @@ fn trans_trait_callee(bcx: block,
     // 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
+    // @/~/&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.
 
     let _icx = bcx.insn_ctxt("impl::trans_trait_callee");
@@ -407,13 +408,14 @@ fn trans_trait_callee(bcx: block,
     let self_datum = unpack_datum!(bcx, expr::trans_to_datum(bcx, self_expr));
     let llpair = self_datum.to_ref_llval(bcx);
     let callee_ty = node_id_type(bcx, callee_id);
-    trans_trait_callee_from_llval(bcx, callee_ty, n_method, llpair)
+    trans_trait_callee_from_llval(bcx, callee_ty, n_method, llpair, vstore)
 }
 
 fn trans_trait_callee_from_llval(bcx: block,
                                  callee_ty: ty::t,
                                  n_method: uint,
-                                 llpair: ValueRef)
+                                 llpair: ValueRef,
+                                 vstore: ty::vstore)
     -> Callee
 {
     //!
@@ -431,9 +433,21 @@ fn trans_trait_callee_from_llval(bcx: block,
                                   GEPi(bcx, llpair, [0u, 0u]),
                                   T_ptr(T_ptr(T_vtable()))));
 
-    // Load the box from the @Trait pair and GEP over the box header:
+    // Load the box from the @Trait pair and GEP over the box header if
+    // necessary:
+    let llself;
     let llbox = Load(bcx, GEPi(bcx, llpair, [0u, 1u]));
-    let llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
+    match vstore {
+        ty::vstore_box | ty::vstore_uniq => {
+            llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
+        }
+        ty::vstore_slice(_) => {
+            llself = llbox;
+        }
+        ty::vstore_fixed(*) => {
+            bcx.tcx().sess.bug(~"vstore_fixed trait");
+        }
+    }
 
     // Load the function from the vtable and cast it to the expected type.
     let llcallee_ty = type_of::type_of_fn_from_ty(ccx, callee_ty);
@@ -503,7 +517,7 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t],
     // XXX: This should support multiple traits.
     let trt_id = driver::session::expect(
         tcx.sess,
-        ty::ty_to_def_id(ty::impl_traits(tcx, impl_id)[0]),
+        ty::ty_to_def_id(ty::impl_traits(tcx, impl_id, ty::vstore_box)[0]),
         || ~"make_impl_vtable: non-trait-type implemented");
 
     let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs
index cdd11ee85c5..3996f0ff5ee 100644
--- a/src/rustc/middle/trans/reflect.rs
+++ b/src/rustc/middle/trans/reflect.rs
@@ -70,10 +70,12 @@ impl reflector {
         }
         let bool_ty = ty::mk_bool(tcx);
         let scratch = scratch_datum(bcx, bool_ty, false);
+        // XXX: Should not be vstore_box!
         let 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),
+                                                      mth_idx, v,
+                                                      ty::vstore_box),
             ArgVals(args), SaveIn(scratch.val), DontAutorefArg);
         let result = scratch.to_value_llval(bcx);
         let next_bcx = sub_block(bcx, ~"next");
diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs
index b45da3b2700..7b5a912ed7f 100644
--- a/src/rustc/middle/trans/type_of.rs
+++ b/src/rustc/middle/trans/type_of.rs
@@ -159,7 +159,7 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
         T_struct(~[T_struct(tys)])
       }
       ty::ty_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
-      ty::ty_trait(_, _, _) => T_opaque_trait(cx),
+      ty::ty_trait(_, _, vstore) => T_opaque_trait(cx, vstore),
       ty::ty_type => T_ptr(cx.tydesc_type),
       ty::ty_tup(elts) => {
         let mut tys = ~[];
diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs
index 6bd3c22f626..8bd5bd7afc7 100644
--- a/src/rustc/middle/trans/type_use.rs
+++ b/src/rustc/middle/trans/type_use.rs
@@ -247,7 +247,7 @@ fn mark_for_expr(cx: ctx, e: @expr) {
               typeck::method_param({param_num: param, _}) => {
                 cx.uses[param] |= use_tydesc;
               }
-              typeck::method_trait(_, _) => (),
+              typeck::method_trait(*) => (),
             }
         }
       }
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index 109db9ace09..78949ec5f79 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -90,6 +90,7 @@ export ty_estr, mk_estr, type_is_str;
 export ty_evec, mk_evec, type_is_vec;
 export ty_unboxed_vec, mk_unboxed_vec, mk_mut_unboxed_vec;
 export vstore, vstore_fixed, vstore_uniq, vstore_box, vstore_slice;
+export serialize_vstore, deserialize_vstore;
 export ty_nil, mk_nil, type_is_nil;
 export ty_trait, mk_trait;
 export ty_param, mk_param, ty_params_to_tys;
@@ -217,6 +218,7 @@ type method = {ident: ast::ident,
 
 type mt = {ty: t, mutbl: ast::mutability};
 
+#[auto_serialize]
 enum vstore {
     vstore_fixed(uint),
     vstore_uniq,
@@ -1624,7 +1626,10 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool {
       ty_evec(_, vstore_uniq) |
       ty_evec(_, vstore_box) => true,
 
-      ty_trait(*) => true,
+      ty_trait(_, _, vstore_box) |
+      ty_trait(_, _, vstore_uniq) => true,
+      ty_trait(_, _, vstore_fixed(_)) |
+      ty_trait(_, _, vstore_slice(_)) => false,
 
       ty_param(*) | ty_infer(*) => true,
 
@@ -2821,7 +2826,7 @@ fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
           }
           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.
@@ -3362,7 +3367,15 @@ fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
 /*
   Could this return a list of (def_id, substs) pairs?
  */
-fn impl_traits(cx: ctxt, id: ast::def_id) -> ~[t] {
+fn impl_traits(cx: ctxt, id: ast::def_id, vstore: vstore) -> ~[t] {
+    fn vstoreify(cx: ctxt, ty: t, vstore: vstore) -> t {
+        match ty::get(ty).sty {
+            ty::ty_trait(_, _, trait_vstore) if vstore == trait_vstore => ty,
+            ty::ty_trait(did, substs, _) => mk_trait(cx, did, substs, vstore),
+            _ => cx.sess.bug(~"impl_traits: not a trait")
+        }
+    }
+
     if id.crate == ast::local_crate {
         debug!("(impl_traits) searching for trait impl %?", id);
         match cx.items.find(id.node) {
@@ -3372,19 +3385,23 @@ fn impl_traits(cx: ctxt, id: ast::def_id) -> ~[t] {
                     _)) => {
 
                do option::map_default(&opt_trait, ~[]) |trait_ref| {
-                       ~[node_id_to_type(cx, trait_ref.ref_id)]
+                       ~[vstoreify(cx,
+                                   node_id_to_type(cx, trait_ref.ref_id),
+                                   vstore)]
                    }
            }
            Some(ast_map::node_item(@{node: ast::item_class(sd,_),
                            _},_)) => {
                do vec::map(sd.traits) |trait_ref| {
-                    node_id_to_type(cx, trait_ref.ref_id)
+                    vstoreify(cx, node_id_to_type(cx, trait_ref.ref_id),
+                              vstore)
                 }
            }
            _ => ~[]
         }
     } else {
-        csearch::get_impl_traits(cx, id)
+        vec::map(csearch::get_impl_traits(cx, id),
+                 |x| vstoreify(cx, *x, vstore))
     }
 }
 
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index 3a9471139f9..6c461126853 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -86,7 +86,7 @@ enum method_origin {
     method_param(method_param),
 
     // method invoked on a trait instance
-    method_trait(ast::def_id, uint),
+    method_trait(ast::def_id, uint, ty::vstore),
 }
 
 // details for a method invoked with a receiver whose type is a type parameter
diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs
index 45a7c22e2f9..14797fcdd6b 100644
--- a/src/rustc/middle/typeck/astconv.rs
+++ b/src/rustc/middle/typeck/astconv.rs
@@ -189,16 +189,19 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope Copy Owned>(
                                                        type_def_id, path);
                 match ty::get(result.ty).sty {
                     ty::ty_trait(trait_def_id, substs, _) => {
-                        if vst != ty::vstore_box {
-                            tcx.sess.span_unimpl(path.span,
-                                                 ~"`~trait` and `&trait` are \
-                                                   unimplemented; use \
-                                                   `@trait` instead for now");
+                        match vst {
+                            ty::vstore_box | ty::vstore_slice(*) => {}
+                            _ => {
+                                tcx.sess.span_unimpl(path.span,
+                                                     ~"`~trait` is \
+                                                       unimplemented; use \
+                                                       `@trait` instead for \
+                                                       now");
+                            }
                         }
                         return ty::mk_trait(tcx, trait_def_id, substs, vst);
                     }
-                    _ =>
-                        {}
+                    _ => {}
                 }
               }
               _ => ()
diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs
index d08d3e9b847..d55f9facc62 100644
--- a/src/rustc/middle/typeck/check/method.rs
+++ b/src/rustc/middle/typeck/check/method.rs
@@ -221,9 +221,9 @@ impl LookupContext {
                 ty_param(p) => {
                     self.push_inherent_candidates_from_param(p);
                 }
-                ty_trait(did, ref substs, _) => {
+                ty_trait(did, ref substs, vstore) => {
                     self.push_inherent_candidates_from_trait(
-                        self_ty, did, substs);
+                        self_ty, did, substs, vstore);
                     self.push_inherent_impl_candidates_for_type(did);
                 }
                 ty_self => {
@@ -233,7 +233,8 @@ impl LookupContext {
                         ~"unexpected `none` for self_impl_def_id");
                     let substs = {self_r: None, self_ty: None, tps: ~[]};
                     self.push_inherent_candidates_from_trait(
-                        self_ty, self_did, &substs);
+                        self_ty, self_did, &substs,
+                        ty::vstore_slice(ty::re_static));   // XXX: Wrong!
                 }
                 ty_enum(did, _) | ty_class(did, _) => {
                     self.push_inherent_impl_candidates_for_type(did);
@@ -347,7 +348,8 @@ impl LookupContext {
     fn push_inherent_candidates_from_trait(&self,
                                            self_ty: ty::t,
                                            did: def_id,
-                                           substs: &ty::substs)
+                                           substs: &ty::substs,
+                                           vstore: ty::vstore)
     {
         debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)",
                self.did_to_str(did),
@@ -391,7 +393,7 @@ impl LookupContext {
             rcvr_substs: move rcvr_substs,
             num_method_tps: method.tps.len(),
             self_mode: get_mode_from_self_type(method.self_ty),
-            origin: method_trait(did, index)
+            origin: method_trait(did, index, vstore)
         });
     }
 
@@ -770,7 +772,7 @@ impl LookupContext {
             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)
             }
         };
@@ -791,7 +793,7 @@ impl LookupContext {
             method_param(mp) => {
                 self.report_param_candidate(idx, mp.trait_id)
             }
-            method_trait(trait_did, _) => {
+            method_trait(trait_did, _, _) => {
                 self.report_param_candidate(idx, trait_did)
             }
         }
diff --git a/src/rustc/middle/typeck/check/regionck.rs b/src/rustc/middle/typeck/check/regionck.rs
index d8ea330ee11..0b258da5672 100644
--- a/src/rustc/middle/typeck/check/regionck.rs
+++ b/src/rustc/middle/typeck/check/regionck.rs
@@ -221,11 +221,7 @@ fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) {
                 result::Err(_) => { return; /*typeck will fail anyhow*/ }
                 result::Ok(target_ty) => {
                     match ty::get(target_ty).sty {
-                        ty::ty_trait(_, substs, _) => {
-                            let trait_region = match substs.self_r {
-                                Some(r) => {r}
-                                None => {ty::re_static}
-                            };
+                        ty::ty_trait(_, _, vstore_slice(trait_region)) => {
                             let source_ty = rcx.fcx.expr_ty(source);
                             constrain_regions_in_type(rcx, trait_region,
                                                       expr.span, source_ty);
diff --git a/src/rustc/middle/typeck/check/vtable.rs b/src/rustc/middle/typeck/check/vtable.rs
index e8926468b3a..00fb134f2be 100644
--- a/src/rustc/middle/typeck/check/vtable.rs
+++ b/src/rustc/middle/typeck/check/vtable.rs
@@ -156,8 +156,8 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
     let _i = indenter();
 
     let tcx = fcx.ccx.tcx;
-    let (trait_id, trait_substs) = match ty::get(trait_ty).sty {
-        ty::ty_trait(did, substs, _) => (did, substs),
+    let (trait_id, trait_substs, trait_vstore) = match ty::get(trait_ty).sty {
+        ty::ty_trait(did, substs, vstore) => (did, substs, vstore),
         _ => tcx.sess.impossible_case(expr.span,
                                       "lookup_vtable_invariant: \
                                        don't know how to handle a non-trait")
@@ -270,7 +270,8 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
                         // it's the same trait as trait_ty, we need to
                         // unify it with trait_ty in order to get all
                         // the ty vars sorted out.
-                        for vec::each(ty::impl_traits(tcx, im.did)) |of_ty| {
+                        for vec::each(ty::impl_traits(tcx, im.did,
+                                                      trait_vstore)) |of_ty| {
                             match ty::get(*of_ty).sty {
                                 ty::ty_trait(id, _, _) => {
                                     // Not the trait we're looking for
@@ -378,7 +379,8 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
                             // lists of types to unify pairwise.
 
                             connect_trait_tps(fcx, expr, substs_f.tps,
-                                              trait_tps, im.did);
+                                              trait_tps, im.did,
+                                              trait_vstore);
                             let subres = lookup_vtables(
                                 fcx, expr, im_bs, &substs_f,
                                 false, is_early);
@@ -436,11 +438,12 @@ fn fixup_ty(fcx: @fn_ctxt,
 }
 
 fn connect_trait_tps(fcx: @fn_ctxt, expr: @ast::expr, impl_tys: ~[ty::t],
-                     trait_tys: ~[ty::t], impl_did: ast::def_id) {
+                     trait_tys: ~[ty::t], impl_did: ast::def_id,
+                     vstore: ty::vstore) {
     let tcx = fcx.ccx.tcx;
 
     // XXX: This should work for multiple traits.
-    let ity = ty::impl_traits(tcx, impl_did)[0];
+    let ity = ty::impl_traits(tcx, impl_did, vstore)[0];
     let trait_ty = ty::subst_tps(tcx, impl_tys, ity);
     debug!("(connect trait tps) trait type is %?, impl did is %?",
            ty::get(trait_ty).sty, impl_did);
@@ -508,7 +511,7 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
       ast::expr_cast(src, _) => {
         let target_ty = fcx.expr_ty(ex);
         match ty::get(target_ty).sty {
-          ty::ty_trait(*) => {
+          ty::ty_trait(_, _, vstore) => {
             // Look up vtables for the type we're casting to, passing in the
             // source and target type.
             //
@@ -520,26 +523,73 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
             match vtable_opt {
                 None => {
                     // Try the new-style boxed trait; "@int as @Trait".
+                    // Or the new-style region trait; "&int as &Trait".
                     let mut err = false;
                     let ty = structurally_resolved_type(fcx, ex.span, ty);
                     match ty::get(ty).sty {
-                        ty::ty_box(boxed_ty) => {
-                            let vtable_opt =
-                                lookup_vtable_invariant(fcx, ex, boxed_ty.ty,
-                                                        target_ty, true,
-                                                        is_early);
-                            match vtable_opt {
-                                Some(vtable) => {
-                                    /*
-                                    Map this expression to that vtable (that
-                                    is: "ex has vtable <vtable>")
-                                    */
-                                    if !is_early {
-                                        cx.vtable_map.insert(ex.id,
-                                                             @~[vtable]);
+                        ty::ty_box(mt) | ty::ty_rptr(_, mt) => {
+                            // Ensure that the trait vstore and the pointer
+                            // type match.
+                            match (ty::get(ty).sty, vstore) {
+                                (ty::ty_box(_), ty::vstore_box) |
+                                (ty::ty_rptr(*), ty::vstore_slice(*)) => {
+                                    let vtable_opt =
+                                        lookup_vtable_invariant(fcx,
+                                                                ex,
+                                                                mt.ty,
+                                                                target_ty,
+                                                                true,
+                                                                is_early);
+                                    match vtable_opt {
+                                        Some(vtable) => {
+                                            // Map this expression to that
+                                            // vtable (that is: "ex has vtable
+                                            // <vtable>")
+                                            if !is_early {
+                                                cx.vtable_map.insert(
+                                                    ex.id, @~[vtable]);
+                                            }
+                                        }
+                                        None => err = true
                                     }
+
+                                    // Now, if this is &trait, we need to link
+                                    // the regions.
+                                    match (ty::get(ty).sty, vstore) {
+                                        (ty::ty_rptr(ra, _),
+                                         ty::vstore_slice(rb)) => {
+                                            infer::mk_subr(fcx.infcx(),
+                                                           false,
+                                                           ex.span,
+                                                           rb,
+                                                           ra);
+                                        }
+                                        _ => {}
+                                    }
+                                }
+                                (ty::ty_box(_), _) => {
+                                    fcx.ccx.tcx.sess.span_err(ex.span,
+                                                              ~"must cast \
+                                                                a boxed \
+                                                                pointer to \
+                                                                a boxed
+                                                                trait");
+                                    err = true;
+                                }
+                                (ty::ty_rptr(*), _) => {
+                                    fcx.ccx.tcx.sess.span_err(ex.span,
+                                                              ~"must cast \
+                                                                a borrowed \
+                                                                pointer to \
+                                                                a borrowed \
+                                                                trait");
+                                }
+                                _ => {
+                                    fcx.ccx.tcx.sess.impossible_case(
+                                        ex.span,
+                                        ~"impossible combination of type and \
+                                          trait vstore");
                                 }
-                                None => err = true
                             }
                         }
                         _ => err = true