]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/typeck/check/method.rs
librustc: Permit by-value-self methods to be invoked on objects
[rust.git] / src / librustc / middle / typeck / check / method.rs
index fafc84d2b10f08fce2b97a8559ef541d954551b9..c3b2756bdbff2f7f165af2718ec6a1fe293a7452 100644 (file)
@@ -93,6 +93,7 @@ trait `ToStr` imported, and I call `to_str()` on a value of type `T`,
 use middle::typeck::{MethodStatic, MethodObject};
 use middle::typeck::{param_index};
 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
+use middle::typeck::TypeAndSubsts;
 use util::common::indenter;
 use util::ppaux;
 use util::ppaux::Repr;
@@ -270,7 +271,9 @@ fn construct_transformed_self_ty_for_object(
             tcx.sess.span_bug(span, "static method for object type receiver");
         }
         ast::SelfValue => {
-            ty::mk_err() // error reported in `enforce_object_limitations()`
+            let tr = ty::mk_trait(tcx, trait_def_id, obj_substs,
+                                  ty::empty_builtin_bounds());
+            ty::mk_uniq(tcx, tr)
         }
         ast::SelfRegion(..) | ast::SelfUniq => {
             let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
@@ -688,7 +691,7 @@ fn push_candidates_from_impl(&mut self,
         // variables for each parameter:
         let span = self.self_expr.map_or(self.span, |e| e.span);
         let vcx = self.fcx.vtable_context();
-        let ty::ty_param_substs_and_ty {
+        let TypeAndSubsts {
             substs: impl_substs,
             ty: impl_ty
         } = impl_self_ty(&vcx, span, impl_did);
@@ -1224,14 +1227,7 @@ fn enforce_object_limitations(&self, candidate: &Candidate) {
                      through an object");
             }
 
-            ast::SelfValue => { // reason (a) above
-                self.tcx().sess.span_err(
-                    self.span,
-                    "cannot call a method with a by-value receiver \
-                     through an object");
-            }
-
-            ast::SelfRegion(..) | ast::SelfUniq => {}
+            ast::SelfValue | ast::SelfRegion(..) | ast::SelfUniq => {}
         }
 
         // reason (a) above
@@ -1301,7 +1297,26 @@ fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
             }
 
             SelfValue => {
-                rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
+                debug!("(is relevant?) explicit self is by-value");
+                match ty::get(rcvr_ty).sty {
+                    ty::ty_uniq(typ) => {
+                        match ty::get(typ).sty {
+                            ty::ty_trait(box ty::TyTrait {
+                                def_id: self_did,
+                                ..
+                            }) => {
+                                rcvr_matches_object(self_did, candidate) ||
+                                    rcvr_matches_ty(self.fcx,
+                                                    rcvr_ty,
+                                                    candidate)
+                            }
+                            _ => {
+                                rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
+                            }
+                        }
+                    }
+                    _ => rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
+                }
             }
 
             SelfRegion(_, m) => {