about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-11-14 16:32:37 -0800
committerPatrick Walton <pcwalton@mimiga.net>2012-11-15 10:26:49 -0800
commitadc4bed773ea6af7343a5a6bbe46e288367fecee (patch)
tree1718d659bc568abff0d3f1023b3e2e3d094433dd /src
parent29e10c91fe1d2b854b4db7a4cb3c12e3ea8dbddc (diff)
librustc: Implement (and require) explicit self for derivable traits. r=nmatsakis
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/trans/deriving.rs55
-rw-r--r--src/librustc/middle/typeck.rs1
-rw-r--r--src/librustc/middle/typeck/deriving.rs17
-rw-r--r--src/librustc/rustc.rc8
-rw-r--r--src/test/compile-fail/enum-deriving-incomplete.rs2
-rw-r--r--src/test/compile-fail/missing-derivable-attr.rs4
-rw-r--r--src/test/run-pass/deriving-generic-bounded.rs10
-rw-r--r--src/test/run-pass/deriving-one-method.rs10
-rw-r--r--src/test/run-pass/deriving-override.rs10
-rw-r--r--src/test/run-pass/deriving-param-pass-through.rs6
-rw-r--r--src/test/run-pass/deriving-returning-nil.rs4
-rw-r--r--src/test/run-pass/deriving-simple.rs4
-rw-r--r--src/test/run-pass/enum-deriving-simple.rs4
13 files changed, 89 insertions, 46 deletions
diff --git a/src/librustc/middle/trans/deriving.rs b/src/librustc/middle/trans/deriving.rs
index 6b54407781c..8fc81101faf 100644
--- a/src/librustc/middle/trans/deriving.rs
+++ b/src/librustc/middle/trans/deriving.rs
@@ -4,6 +4,7 @@
 use lib::llvm::llvm::{LLVMCountParams, LLVMGetParam};
 use middle::trans::base::{GEP_enum, finish_fn, get_insn_ctxt, get_item_val};
 use middle::trans::base::{new_fn_ctxt, sub_block, top_scope_block};
+use middle::trans::base;
 use middle::trans::build::{AddCase, Br, CondBr, GEPi, Load, PointerCast};
 use middle::trans::build::{Store, Switch, Unreachable, ValueRef};
 use middle::trans::callee;
@@ -14,7 +15,8 @@ use middle::trans::common::{C_bool, C_int, T_ptr, block, crate_ctxt};
 use middle::trans::common::{fn_ctxt};
 use middle::trans::expr::SaveIn;
 use middle::trans::type_of::type_of;
-use middle::ty::DerivedFieldInfo;
+use middle::ty::{DerivedFieldInfo, re_static};
+use middle::typeck::check::method;
 use middle::typeck::method_static;
 use syntax::ast;
 use syntax::ast::{def_id, ident, node_id, ty_param};
@@ -78,14 +80,33 @@ pub fn trans_deriving_impl(ccx: @crate_ctxt,
             for method_dids.each |method_did| {
                 let kind = DerivingKind::of_item(ccx, *method_did);
                 let llfn = get_item_val(ccx, method_did.node);
+
+                // Transform the self type as appropriate.
+                let derived_method_info =
+                    ccx.tcx.automatically_derived_methods.get(*method_did);
+                let transformed_self_ty =
+                    method::transform_self_type_for_method(
+                        ccx.tcx,
+                        Some(re_static),
+                        self_ty.ty,
+                        derived_method_info.method_info.self_type);
+
                 match ty::get(self_ty.ty).sty {
                     ty::ty_class(*) => {
-                        trans_deriving_struct_method(ccx, llfn, impl_def_id,
-                                                     self_ty.ty, kind);
+                        trans_deriving_struct_method(ccx,
+                                                     llfn,
+                                                     impl_def_id,
+                                                     self_ty.ty,
+                                                     transformed_self_ty,
+                                                     kind);
                     }
                     ty::ty_enum(*) => {
-                        trans_deriving_enum_method(ccx, llfn, impl_def_id,
-                                                   self_ty.ty, kind);
+                        trans_deriving_enum_method(ccx,
+                                                   llfn,
+                                                   impl_def_id,
+                                                   self_ty.ty,
+                                                   transformed_self_ty,
+                                                   kind);
                     }
                     _ => {
                         ccx.tcx.sess.bug(~"translation of non-struct \
@@ -119,6 +140,7 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
                                 llfn: ValueRef,
                                 impl_did: def_id,
                                 self_ty: ty::t,
+                                transformed_self_ty: ty::t,
                                 kind: DerivingKind) {
     let _icx = ccx.insn_ctxt("trans_deriving_struct_method");
     let fcx = new_fn_ctxt(ccx, ~[], llfn, None);
@@ -128,8 +150,10 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
 
     let llextraparams = get_extra_params(llfn, kind);
 
-    let llselfty = type_of(ccx, self_ty);
-    let llselfval = PointerCast(bcx, fcx.llenv, T_ptr(llselfty));
+    let lltransformedselfty = type_of(ccx, transformed_self_ty);
+    let lltransformedselfval =
+        PointerCast(bcx, fcx.llenv, T_ptr(lltransformedselfty));
+    let llselfval = Load(bcx, lltransformedselfval);
 
     // If there is an "other" value, then get it. The "other" value is the
     // value we're comparing against in the case of Eq and Ord.
@@ -155,6 +179,9 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
     for ccx.tcx.deriving_struct_methods.get(impl_did).eachi
             |i, derived_method_info| {
         let llselfval = GEPi(bcx, llselfval, [0, 0, i]);
+        let llselfallocaty = common::val_ty(llselfval);
+        let llselfalloca = base::alloca(bcx, llselfallocaty);
+        Store(bcx, llselfval, llselfalloca);
 
         let llotherval_opt = llotherval_opt.map(
             |llotherval| GEPi(bcx, *llotherval, [0, 0, i]));
@@ -163,7 +190,7 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
         bcx = call_substructure_method(bcx,
                                        derived_method_info,
                                        self_ty,
-                                       llselfval,
+                                       llselfalloca,
                                        llotherval_opt,
                                        llextraparams);
 
@@ -197,6 +224,7 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
                               llfn: ValueRef,
                               impl_did: def_id,
                               self_ty: ty::t,
+                              transformed_self_ty: ty::t,
                               kind: DerivingKind) {
     let _icx = ccx.insn_ctxt("trans_deriving_enum_method");
     let fcx = new_fn_ctxt(ccx, ~[], llfn, None);
@@ -206,8 +234,10 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
 
     let llextraparams = get_extra_params(llfn, kind);
 
-    let llselfty = type_of(ccx, self_ty);
-    let llselfval = PointerCast(bcx, fcx.llenv, T_ptr(llselfty));
+    let lltransformedselfty = type_of(ccx, transformed_self_ty);
+    let lltransformedselfval =
+        PointerCast(bcx, fcx.llenv, T_ptr(lltransformedselfty));
+    let llselfval = Load(bcx, lltransformedselfval);
 
     let llotherval_opt;
     match kind {
@@ -280,6 +310,9 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
                         enum_variant_infos[self_variant_index].id;
                 let llselfval = GEP_enum(match_bcx, llselfpayload, enum_id,
                                          variant_def_id, enum_substs.tps, i);
+                let llselfallocaty = common::val_ty(llselfval);
+                let llselfalloca = base::alloca(match_bcx, llselfallocaty);
+                Store(match_bcx, llselfval, llselfalloca);
 
                 let llotherval_opt = llotherpayload_opt.map(|llotherpayload|
                     GEP_enum(match_bcx, *llotherpayload, enum_id,
@@ -289,7 +322,7 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
                 match_bcx = call_substructure_method(match_bcx,
                                                      derived_method_info,
                                                      self_ty,
-                                                     llselfval,
+                                                     llselfalloca,
                                                      llotherval_opt,
                                                      llextraparams);
 
diff --git a/src/librustc/middle/typeck.rs b/src/librustc/middle/typeck.rs
index d4df07f7eb8..977fc06ce86 100644
--- a/src/librustc/middle/typeck.rs
+++ b/src/librustc/middle/typeck.rs
@@ -63,6 +63,7 @@ use std::list;
 use list::{List, Nil, Cons};
 use dvec::DVec;
 
+export check;
 export check_crate;
 export infer;
 export method_map;
diff --git a/src/librustc/middle/typeck/deriving.rs b/src/librustc/middle/typeck/deriving.rs
index 197a06a1d97..010ca242c7d 100644
--- a/src/librustc/middle/typeck/deriving.rs
+++ b/src/librustc/middle/typeck/deriving.rs
@@ -17,8 +17,8 @@ use syntax::print::pprust;
 use syntax::visit::{default_simple_visitor, mk_simple_visitor, visit_crate};
 use middle::resolve::{Impl, MethodInfo};
 use middle::ty;
-use middle::ty::{DerivedFieldInfo, substs, ty_class, ty_enum};
-use middle::ty::{ty_param_bounds_and_ty};
+use middle::ty::{DerivedFieldInfo, ReVar, re_infer, re_static, substs};
+use middle::ty::{ty_class, ty_enum, ty_param_bounds_and_ty};
 use /*middle::typeck::*/check::method;
 use /*middle::typeck::*/check::vtable;
 use /*middle::typeck::*/infer::infer_ctxt;
@@ -56,10 +56,12 @@ impl DerivingChecker {
         let tcx = self.crate_context.tcx;
 
         let impl_self_tpbt = ty::lookup_item_type(tcx, impl_info.did);
-        let transformed_type = method::transform_self_type_for_method(
-            tcx, None, impl_self_tpbt.ty, method_info.self_type);
 
         let inference_context = infer::new_infer_ctxt(self.crate_context.tcx);
+        let region = inference_context.next_region_var_nb(span);
+        let transformed_type = method::transform_self_type_for_method(
+            tcx, Some(region), impl_self_tpbt.ty, method_info.self_type);
+
         let substs = {
             self_r: None,
             self_ty: None,
@@ -68,6 +70,13 @@ impl DerivingChecker {
         let transformed_type = ty::subst(
             self.crate_context.tcx, &substs, transformed_type);
 
+        // Automatically reference the substructure type.
+        let region = inference_context.next_region_var_nb(span);
+        let substructure_type = ty::mk_rptr(
+            self.crate_context.tcx,
+            region,
+            { ty: substructure_type, mutbl: ast::m_imm });
+
         debug!("(matching impl method) substructure type %s, transformed \
                 type %s, subst tps %u",
                ppaux::ty_to_str(self.crate_context.tcx, substructure_type),
diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc
index 0dd9ae7217f..2b92255bcc5 100644
--- a/src/librustc/rustc.rc
+++ b/src/librustc/rustc.rc
@@ -95,10 +95,10 @@ mod middle {
     mod ty;
     #[legacy_exports]
     mod resolve;
-    mod typeck {
+    pub mod typeck {
         #[legacy_exports];
-        mod check {
-            #[legacy_exports];
+        #[legacy_exports]
+        pub mod check {
             #[legacy_exports]
             mod alt;
             #[legacy_exports]
@@ -112,7 +112,7 @@ mod middle {
             #[legacy_exports]
             mod demand;
             #[legacy_exports]
-            mod method;
+            pub mod method;
         }
         #[legacy_exports]
         mod rscope;
diff --git a/src/test/compile-fail/enum-deriving-incomplete.rs b/src/test/compile-fail/enum-deriving-incomplete.rs
index eb103a48df9..0d6d499842f 100644
--- a/src/test/compile-fail/enum-deriving-incomplete.rs
+++ b/src/test/compile-fail/enum-deriving-incomplete.rs
@@ -1,6 +1,6 @@
 trait MyEq {
     #[derivable]
-    pure fn eq(other: &self) -> bool;
+    pure fn eq(&self, other: &self) -> bool;
 }
 
 struct A {
diff --git a/src/test/compile-fail/missing-derivable-attr.rs b/src/test/compile-fail/missing-derivable-attr.rs
index 140c915c57d..a28519e0a56 100644
--- a/src/test/compile-fail/missing-derivable-attr.rs
+++ b/src/test/compile-fail/missing-derivable-attr.rs
@@ -1,5 +1,5 @@
 trait MyEq {
-    pure fn eq(other: &self) -> bool;
+    pure fn eq(&self, other: &self) -> bool;
 }
 
 struct A {
@@ -7,7 +7,7 @@ struct A {
 }
 
 impl int : MyEq {
-    pure fn eq(other: &int) -> bool { self == *other }
+    pure fn eq(&self, other: &int) -> bool { *self == *other }
 }
 
 impl A : MyEq;  //~ ERROR missing method
diff --git a/src/test/run-pass/deriving-generic-bounded.rs b/src/test/run-pass/deriving-generic-bounded.rs
index a45b7df3a2a..2dd27fdba67 100644
--- a/src/test/run-pass/deriving-generic-bounded.rs
+++ b/src/test/run-pass/deriving-generic-bounded.rs
@@ -1,20 +1,20 @@
 trait MyEq {
     #[derivable]
-    pure fn eq(other: &self) -> bool;
+    pure fn eq(&self, other: &self) -> bool;
 }
 
 impl int : MyEq {
-    pure fn eq(other: &int) -> bool {
-        self == *other
+    pure fn eq(&self, other: &int) -> bool {
+        *self == *other
     }
 }
 
 impl<T:MyEq> @T : MyEq {
-    pure fn eq(other: &@T) -> bool {
+    pure fn eq(&self, other: &@T) -> bool {
         unsafe {
             io::println("@T");
         }
-        (*self).eq(&**other)
+        (**self).eq(&**other)
     }
 }
 
diff --git a/src/test/run-pass/deriving-one-method.rs b/src/test/run-pass/deriving-one-method.rs
index 20fe5a35cd3..3a4e9db22c8 100644
--- a/src/test/run-pass/deriving-one-method.rs
+++ b/src/test/run-pass/deriving-one-method.rs
@@ -1,7 +1,7 @@
 trait MyEq {
     #[derivable]
-    pure fn eq(other: &self) -> bool;
-    pure fn ne(other: &self) -> bool;
+    pure fn eq(&self, other: &self) -> bool;
+    pure fn ne(&self, other: &self) -> bool;
 }
 
 struct A {
@@ -9,12 +9,12 @@ struct A {
 }
 
 impl int : MyEq {
-    pure fn eq(other: &int) -> bool { self == *other }
-    pure fn ne(other: &int) -> bool { self != *other }
+    pure fn eq(&self, other: &int) -> bool { *self == *other }
+    pure fn ne(&self, other: &int) -> bool { *self != *other }
 }
 
 impl A : MyEq {
-    pure fn ne(other: &A) -> bool { !self.eq(other) }
+    pure fn ne(&self, other: &A) -> bool { !self.eq(other) }
 }
 
 fn main() {
diff --git a/src/test/run-pass/deriving-override.rs b/src/test/run-pass/deriving-override.rs
index 5b030e4db18..ff6b4480259 100644
--- a/src/test/run-pass/deriving-override.rs
+++ b/src/test/run-pass/deriving-override.rs
@@ -1,8 +1,8 @@
 trait MyEq {
     #[derivable]
-    pure fn eq(other: &self) -> bool;
+    pure fn eq(&self, other: &self) -> bool;
     #[derivable]
-    pure fn ne(other: &self) -> bool;
+    pure fn ne(&self, other: &self) -> bool;
 }
 
 struct A {
@@ -10,12 +10,12 @@ struct A {
 }
 
 impl int : MyEq {
-    pure fn eq(other: &int) -> bool { self == *other }
-    pure fn ne(other: &int) -> bool { self != *other }
+    pure fn eq(&self, other: &int) -> bool { *self == *other }
+    pure fn ne(&self, other: &int) -> bool { *self != *other }
 }
 
 impl A : MyEq {
-    pure fn ne(other: &A) -> bool { !self.eq(other) }
+    pure fn ne(&self, other: &A) -> bool { !self.eq(other) }
 }
 
 fn main() {
diff --git a/src/test/run-pass/deriving-param-pass-through.rs b/src/test/run-pass/deriving-param-pass-through.rs
index 23c540d9044..35ec951d6e7 100644
--- a/src/test/run-pass/deriving-param-pass-through.rs
+++ b/src/test/run-pass/deriving-param-pass-through.rs
@@ -1,17 +1,17 @@
 trait Trait {
     #[derivable]
-    fn f(x: int, y: &str);
+    fn f(&self, x: int, y: &str);
 }
 
 impl int : Trait {
-    fn f(x: int, y: &str) {
+    fn f(&self, x: int, y: &str) {
         assert x == 42;
         assert y == "hello";
     }
 }
 
 impl float : Trait {
-    fn f(x: int, y: &str) {
+    fn f(&self, x: int, y: &str) {
         assert x == 42;
         assert y == "hello";
     }
diff --git a/src/test/run-pass/deriving-returning-nil.rs b/src/test/run-pass/deriving-returning-nil.rs
index 385bb9a3b95..af0a5518967 100644
--- a/src/test/run-pass/deriving-returning-nil.rs
+++ b/src/test/run-pass/deriving-returning-nil.rs
@@ -1,10 +1,10 @@
 trait Show {
     #[derivable]
-    fn show();
+    fn show(&self);
 }
 
 impl int : Show {
-    fn show() {
+    fn show(&self) {
         io::println(self.to_str());
     }
 }
diff --git a/src/test/run-pass/deriving-simple.rs b/src/test/run-pass/deriving-simple.rs
index 60c51a73ddb..35d3584bcae 100644
--- a/src/test/run-pass/deriving-simple.rs
+++ b/src/test/run-pass/deriving-simple.rs
@@ -1,6 +1,6 @@
 trait MyEq {
     #[derivable]
-    pure fn eq(other: &self) -> bool;
+    pure fn eq(&self, other: &self) -> bool;
 }
 
 struct A {
@@ -14,7 +14,7 @@ struct B {
 }
 
 impl A : MyEq {
-    pure fn eq(other: &A) -> bool {
+    pure fn eq(&self, other: &A) -> bool {
         unsafe { io::println(fmt!("eq %d %d", self.x, other.x)); }
         self.x == other.x
     }
diff --git a/src/test/run-pass/enum-deriving-simple.rs b/src/test/run-pass/enum-deriving-simple.rs
index b075f1b1c6a..a084b4cec4f 100644
--- a/src/test/run-pass/enum-deriving-simple.rs
+++ b/src/test/run-pass/enum-deriving-simple.rs
@@ -1,6 +1,6 @@
 trait MyEq {
     #[derivable]
-    pure fn eq(other: &self) -> bool;
+    pure fn eq(&self, other: &self) -> bool;
 }
 
 struct A {
@@ -14,7 +14,7 @@ enum B {
 }
 
 impl A : MyEq {
-    pure fn eq(other: &A) -> bool {
+    pure fn eq(&self, other: &A) -> bool {
         unsafe { io::println("in eq"); }
         self.x == other.x
     }