Skip to content

Commit adc4bed

Browse files
committed
librustc: Implement (and require) explicit self for derivable traits. r=nmatsakis
1 parent 29e10c9 commit adc4bed

13 files changed

+89
-46
lines changed

Diff for: src/librustc/middle/trans/deriving.rs

+44-11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use lib::llvm::llvm::{LLVMCountParams, LLVMGetParam};
55
use middle::trans::base::{GEP_enum, finish_fn, get_insn_ctxt, get_item_val};
66
use middle::trans::base::{new_fn_ctxt, sub_block, top_scope_block};
7+
use middle::trans::base;
78
use middle::trans::build::{AddCase, Br, CondBr, GEPi, Load, PointerCast};
89
use middle::trans::build::{Store, Switch, Unreachable, ValueRef};
910
use middle::trans::callee;
@@ -14,7 +15,8 @@ use middle::trans::common::{C_bool, C_int, T_ptr, block, crate_ctxt};
1415
use middle::trans::common::{fn_ctxt};
1516
use middle::trans::expr::SaveIn;
1617
use middle::trans::type_of::type_of;
17-
use middle::ty::DerivedFieldInfo;
18+
use middle::ty::{DerivedFieldInfo, re_static};
19+
use middle::typeck::check::method;
1820
use middle::typeck::method_static;
1921
use syntax::ast;
2022
use syntax::ast::{def_id, ident, node_id, ty_param};
@@ -78,14 +80,33 @@ pub fn trans_deriving_impl(ccx: @crate_ctxt,
7880
for method_dids.each |method_did| {
7981
let kind = DerivingKind::of_item(ccx, *method_did);
8082
let llfn = get_item_val(ccx, method_did.node);
83+
84+
// Transform the self type as appropriate.
85+
let derived_method_info =
86+
ccx.tcx.automatically_derived_methods.get(*method_did);
87+
let transformed_self_ty =
88+
method::transform_self_type_for_method(
89+
ccx.tcx,
90+
Some(re_static),
91+
self_ty.ty,
92+
derived_method_info.method_info.self_type);
93+
8194
match ty::get(self_ty.ty).sty {
8295
ty::ty_class(*) => {
83-
trans_deriving_struct_method(ccx, llfn, impl_def_id,
84-
self_ty.ty, kind);
96+
trans_deriving_struct_method(ccx,
97+
llfn,
98+
impl_def_id,
99+
self_ty.ty,
100+
transformed_self_ty,
101+
kind);
85102
}
86103
ty::ty_enum(*) => {
87-
trans_deriving_enum_method(ccx, llfn, impl_def_id,
88-
self_ty.ty, kind);
104+
trans_deriving_enum_method(ccx,
105+
llfn,
106+
impl_def_id,
107+
self_ty.ty,
108+
transformed_self_ty,
109+
kind);
89110
}
90111
_ => {
91112
ccx.tcx.sess.bug(~"translation of non-struct \
@@ -119,6 +140,7 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
119140
llfn: ValueRef,
120141
impl_did: def_id,
121142
self_ty: ty::t,
143+
transformed_self_ty: ty::t,
122144
kind: DerivingKind) {
123145
let _icx = ccx.insn_ctxt("trans_deriving_struct_method");
124146
let fcx = new_fn_ctxt(ccx, ~[], llfn, None);
@@ -128,8 +150,10 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
128150

129151
let llextraparams = get_extra_params(llfn, kind);
130152

131-
let llselfty = type_of(ccx, self_ty);
132-
let llselfval = PointerCast(bcx, fcx.llenv, T_ptr(llselfty));
153+
let lltransformedselfty = type_of(ccx, transformed_self_ty);
154+
let lltransformedselfval =
155+
PointerCast(bcx, fcx.llenv, T_ptr(lltransformedselfty));
156+
let llselfval = Load(bcx, lltransformedselfval);
133157

134158
// If there is an "other" value, then get it. The "other" value is the
135159
// value we're comparing against in the case of Eq and Ord.
@@ -155,6 +179,9 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
155179
for ccx.tcx.deriving_struct_methods.get(impl_did).eachi
156180
|i, derived_method_info| {
157181
let llselfval = GEPi(bcx, llselfval, [0, 0, i]);
182+
let llselfallocaty = common::val_ty(llselfval);
183+
let llselfalloca = base::alloca(bcx, llselfallocaty);
184+
Store(bcx, llselfval, llselfalloca);
158185

159186
let llotherval_opt = llotherval_opt.map(
160187
|llotherval| GEPi(bcx, *llotherval, [0, 0, i]));
@@ -163,7 +190,7 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
163190
bcx = call_substructure_method(bcx,
164191
derived_method_info,
165192
self_ty,
166-
llselfval,
193+
llselfalloca,
167194
llotherval_opt,
168195
llextraparams);
169196

@@ -197,6 +224,7 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
197224
llfn: ValueRef,
198225
impl_did: def_id,
199226
self_ty: ty::t,
227+
transformed_self_ty: ty::t,
200228
kind: DerivingKind) {
201229
let _icx = ccx.insn_ctxt("trans_deriving_enum_method");
202230
let fcx = new_fn_ctxt(ccx, ~[], llfn, None);
@@ -206,8 +234,10 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
206234

207235
let llextraparams = get_extra_params(llfn, kind);
208236

209-
let llselfty = type_of(ccx, self_ty);
210-
let llselfval = PointerCast(bcx, fcx.llenv, T_ptr(llselfty));
237+
let lltransformedselfty = type_of(ccx, transformed_self_ty);
238+
let lltransformedselfval =
239+
PointerCast(bcx, fcx.llenv, T_ptr(lltransformedselfty));
240+
let llselfval = Load(bcx, lltransformedselfval);
211241

212242
let llotherval_opt;
213243
match kind {
@@ -280,6 +310,9 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
280310
enum_variant_infos[self_variant_index].id;
281311
let llselfval = GEP_enum(match_bcx, llselfpayload, enum_id,
282312
variant_def_id, enum_substs.tps, i);
313+
let llselfallocaty = common::val_ty(llselfval);
314+
let llselfalloca = base::alloca(match_bcx, llselfallocaty);
315+
Store(match_bcx, llselfval, llselfalloca);
283316

284317
let llotherval_opt = llotherpayload_opt.map(|llotherpayload|
285318
GEP_enum(match_bcx, *llotherpayload, enum_id,
@@ -289,7 +322,7 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
289322
match_bcx = call_substructure_method(match_bcx,
290323
derived_method_info,
291324
self_ty,
292-
llselfval,
325+
llselfalloca,
293326
llotherval_opt,
294327
llextraparams);
295328

Diff for: src/librustc/middle/typeck.rs

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ use std::list;
6363
use list::{List, Nil, Cons};
6464
use dvec::DVec;
6565

66+
export check;
6667
export check_crate;
6768
export infer;
6869
export method_map;

Diff for: src/librustc/middle/typeck/deriving.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use syntax::print::pprust;
1717
use syntax::visit::{default_simple_visitor, mk_simple_visitor, visit_crate};
1818
use middle::resolve::{Impl, MethodInfo};
1919
use middle::ty;
20-
use middle::ty::{DerivedFieldInfo, substs, ty_class, ty_enum};
21-
use middle::ty::{ty_param_bounds_and_ty};
20+
use middle::ty::{DerivedFieldInfo, ReVar, re_infer, re_static, substs};
21+
use middle::ty::{ty_class, ty_enum, ty_param_bounds_and_ty};
2222
use /*middle::typeck::*/check::method;
2323
use /*middle::typeck::*/check::vtable;
2424
use /*middle::typeck::*/infer::infer_ctxt;
@@ -56,10 +56,12 @@ impl DerivingChecker {
5656
let tcx = self.crate_context.tcx;
5757

5858
let impl_self_tpbt = ty::lookup_item_type(tcx, impl_info.did);
59-
let transformed_type = method::transform_self_type_for_method(
60-
tcx, None, impl_self_tpbt.ty, method_info.self_type);
6159

6260
let inference_context = infer::new_infer_ctxt(self.crate_context.tcx);
61+
let region = inference_context.next_region_var_nb(span);
62+
let transformed_type = method::transform_self_type_for_method(
63+
tcx, Some(region), impl_self_tpbt.ty, method_info.self_type);
64+
6365
let substs = {
6466
self_r: None,
6567
self_ty: None,
@@ -68,6 +70,13 @@ impl DerivingChecker {
6870
let transformed_type = ty::subst(
6971
self.crate_context.tcx, &substs, transformed_type);
7072

73+
// Automatically reference the substructure type.
74+
let region = inference_context.next_region_var_nb(span);
75+
let substructure_type = ty::mk_rptr(
76+
self.crate_context.tcx,
77+
region,
78+
{ ty: substructure_type, mutbl: ast::m_imm });
79+
7180
debug!("(matching impl method) substructure type %s, transformed \
7281
type %s, subst tps %u",
7382
ppaux::ty_to_str(self.crate_context.tcx, substructure_type),

Diff for: src/librustc/rustc.rc

+4-4
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ mod middle {
9595
mod ty;
9696
#[legacy_exports]
9797
mod resolve;
98-
mod typeck {
98+
pub mod typeck {
9999
#[legacy_exports];
100-
mod check {
101-
#[legacy_exports];
100+
#[legacy_exports]
101+
pub mod check {
102102
#[legacy_exports]
103103
mod alt;
104104
#[legacy_exports]
@@ -112,7 +112,7 @@ mod middle {
112112
#[legacy_exports]
113113
mod demand;
114114
#[legacy_exports]
115-
mod method;
115+
pub mod method;
116116
}
117117
#[legacy_exports]
118118
mod rscope;

Diff for: src/test/compile-fail/enum-deriving-incomplete.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
trait MyEq {
22
#[derivable]
3-
pure fn eq(other: &self) -> bool;
3+
pure fn eq(&self, other: &self) -> bool;
44
}
55

66
struct A {

Diff for: src/test/compile-fail/missing-derivable-attr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
trait MyEq {
2-
pure fn eq(other: &self) -> bool;
2+
pure fn eq(&self, other: &self) -> bool;
33
}
44

55
struct A {
66
x: int
77
}
88

99
impl int : MyEq {
10-
pure fn eq(other: &int) -> bool { self == *other }
10+
pure fn eq(&self, other: &int) -> bool { *self == *other }
1111
}
1212

1313
impl A : MyEq; //~ ERROR missing method

Diff for: src/test/run-pass/deriving-generic-bounded.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
trait MyEq {
22
#[derivable]
3-
pure fn eq(other: &self) -> bool;
3+
pure fn eq(&self, other: &self) -> bool;
44
}
55

66
impl int : MyEq {
7-
pure fn eq(other: &int) -> bool {
8-
self == *other
7+
pure fn eq(&self, other: &int) -> bool {
8+
*self == *other
99
}
1010
}
1111

1212
impl<T:MyEq> @T : MyEq {
13-
pure fn eq(other: &@T) -> bool {
13+
pure fn eq(&self, other: &@T) -> bool {
1414
unsafe {
1515
io::println("@T");
1616
}
17-
(*self).eq(&**other)
17+
(**self).eq(&**other)
1818
}
1919
}
2020

Diff for: src/test/run-pass/deriving-one-method.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
trait MyEq {
22
#[derivable]
3-
pure fn eq(other: &self) -> bool;
4-
pure fn ne(other: &self) -> bool;
3+
pure fn eq(&self, other: &self) -> bool;
4+
pure fn ne(&self, other: &self) -> bool;
55
}
66

77
struct A {
88
x: int
99
}
1010

1111
impl int : MyEq {
12-
pure fn eq(other: &int) -> bool { self == *other }
13-
pure fn ne(other: &int) -> bool { self != *other }
12+
pure fn eq(&self, other: &int) -> bool { *self == *other }
13+
pure fn ne(&self, other: &int) -> bool { *self != *other }
1414
}
1515

1616
impl A : MyEq {
17-
pure fn ne(other: &A) -> bool { !self.eq(other) }
17+
pure fn ne(&self, other: &A) -> bool { !self.eq(other) }
1818
}
1919

2020
fn main() {

Diff for: src/test/run-pass/deriving-override.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
trait MyEq {
22
#[derivable]
3-
pure fn eq(other: &self) -> bool;
3+
pure fn eq(&self, other: &self) -> bool;
44
#[derivable]
5-
pure fn ne(other: &self) -> bool;
5+
pure fn ne(&self, other: &self) -> bool;
66
}
77

88
struct A {
99
x: int
1010
}
1111

1212
impl int : MyEq {
13-
pure fn eq(other: &int) -> bool { self == *other }
14-
pure fn ne(other: &int) -> bool { self != *other }
13+
pure fn eq(&self, other: &int) -> bool { *self == *other }
14+
pure fn ne(&self, other: &int) -> bool { *self != *other }
1515
}
1616

1717
impl A : MyEq {
18-
pure fn ne(other: &A) -> bool { !self.eq(other) }
18+
pure fn ne(&self, other: &A) -> bool { !self.eq(other) }
1919
}
2020

2121
fn main() {

Diff for: src/test/run-pass/deriving-param-pass-through.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
trait Trait {
22
#[derivable]
3-
fn f(x: int, y: &str);
3+
fn f(&self, x: int, y: &str);
44
}
55

66
impl int : Trait {
7-
fn f(x: int, y: &str) {
7+
fn f(&self, x: int, y: &str) {
88
assert x == 42;
99
assert y == "hello";
1010
}
1111
}
1212

1313
impl float : Trait {
14-
fn f(x: int, y: &str) {
14+
fn f(&self, x: int, y: &str) {
1515
assert x == 42;
1616
assert y == "hello";
1717
}

Diff for: src/test/run-pass/deriving-returning-nil.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
trait Show {
22
#[derivable]
3-
fn show();
3+
fn show(&self);
44
}
55

66
impl int : Show {
7-
fn show() {
7+
fn show(&self) {
88
io::println(self.to_str());
99
}
1010
}

Diff for: src/test/run-pass/deriving-simple.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
trait MyEq {
22
#[derivable]
3-
pure fn eq(other: &self) -> bool;
3+
pure fn eq(&self, other: &self) -> bool;
44
}
55

66
struct A {
@@ -14,7 +14,7 @@ struct B {
1414
}
1515

1616
impl A : MyEq {
17-
pure fn eq(other: &A) -> bool {
17+
pure fn eq(&self, other: &A) -> bool {
1818
unsafe { io::println(fmt!("eq %d %d", self.x, other.x)); }
1919
self.x == other.x
2020
}

Diff for: src/test/run-pass/enum-deriving-simple.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
trait MyEq {
22
#[derivable]
3-
pure fn eq(other: &self) -> bool;
3+
pure fn eq(&self, other: &self) -> bool;
44
}
55

66
struct A {
@@ -14,7 +14,7 @@ enum B {
1414
}
1515

1616
impl A : MyEq {
17-
pure fn eq(other: &A) -> bool {
17+
pure fn eq(&self, other: &A) -> bool {
1818
unsafe { io::println("in eq"); }
1919
self.x == other.x
2020
}

0 commit comments

Comments
 (0)