Skip to content

Commit 3afd6c3

Browse files
committed
librustc: Implement simple explicit self for objects. r=nmatsakis
1 parent e9b39d9 commit 3afd6c3

File tree

6 files changed

+122
-18
lines changed

6 files changed

+122
-18
lines changed

src/librustc/middle/astencode.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,9 @@ fn serialize_method_map_entry(ecx: @e::encode_ctxt,
451451
do ebml_w.emit_field(~"self_arg", 0u) {
452452
ebml_w.emit_arg(ecx, mme.self_arg);
453453
}
454+
do ebml_w.emit_field(~"explicit_self", 2u) {
455+
mme.explicit_self.serialize(&ebml_w);
456+
}
454457
do ebml_w.emit_field(~"origin", 1u) {
455458
mme.origin.serialize(&ebml_w);
456459
}
@@ -464,6 +467,11 @@ impl Reader::Deserializer: read_method_map_entry_helper {
464467
self.read_field(~"self_arg", 0u, || {
465468
self.read_arg(xcx)
466469
}),
470+
explicit_self:
471+
self.read_field(~"explicit_self", 2u, || {
472+
let self_type: ast::self_ty_ = deserialize(&self);
473+
self_type
474+
}),
467475
origin:
468476
self.read_field(~"origin", 1u, || {
469477
let method_origin: method_origin = deserialize(&self);

src/librustc/middle/trans/meth.rs

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,12 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
202202
}
203203
}
204204
typeck::method_trait(_, off, vstore) => {
205-
trans_trait_callee(bcx, callee_id, off, self, vstore)
205+
trans_trait_callee(bcx,
206+
callee_id,
207+
off,
208+
self,
209+
vstore,
210+
mentry.explicit_self)
206211
}
207212
typeck::method_self(*) => {
208213
fail ~"method_self should have been handled above"
@@ -378,7 +383,12 @@ fn trans_monomorphized_callee(bcx: block,
378383
}
379384
}
380385
typeck::vtable_trait(_, _) => {
381-
trans_trait_callee(bcx, callee_id, n_method, base, ty::vstore_box)
386+
trans_trait_callee(bcx,
387+
callee_id,
388+
n_method,
389+
base,
390+
ty::vstore_box,
391+
mentry.explicit_self)
382392
}
383393
typeck::vtable_param(*) => {
384394
fail ~"vtable_param left in monomorphized function's vtable substs";
@@ -480,8 +490,9 @@ fn trans_trait_callee(bcx: block,
480490
callee_id: ast::node_id,
481491
n_method: uint,
482492
self_expr: @ast::expr,
483-
vstore: ty::vstore)
484-
-> Callee
493+
vstore: ty::vstore,
494+
explicit_self: ast::self_ty_)
495+
-> Callee
485496
{
486497
//!
487498
//
@@ -497,15 +508,21 @@ fn trans_trait_callee(bcx: block,
497508
let self_datum = unpack_datum!(bcx, expr::trans_to_datum(bcx, self_expr));
498509
let llpair = self_datum.to_ref_llval(bcx);
499510
let callee_ty = node_id_type(bcx, callee_id);
500-
trans_trait_callee_from_llval(bcx, callee_ty, n_method, llpair, vstore)
511+
trans_trait_callee_from_llval(bcx,
512+
callee_ty,
513+
n_method,
514+
llpair,
515+
vstore,
516+
explicit_self)
501517
}
502518
503519
fn trans_trait_callee_from_llval(bcx: block,
504520
callee_ty: ty::t,
505521
n_method: uint,
506522
llpair: ValueRef,
507-
vstore: ty::vstore)
508-
-> Callee
523+
vstore: ty::vstore,
524+
explicit_self: ast::self_ty_)
525+
-> Callee
509526
{
510527
//!
511528
//
@@ -517,14 +534,17 @@ fn trans_trait_callee_from_llval(bcx: block,
517534
let mut bcx = bcx;
518535
519536
// Load the vtable from the @Trait pair
537+
debug!("(translating trait callee) loading vtable from pair %s",
538+
val_str(bcx.ccx().tn, llpair));
520539
let llvtable = Load(bcx,
521540
PointerCast(bcx,
522541
GEPi(bcx, llpair, [0u, 0u]),
523542
T_ptr(T_ptr(T_vtable()))));
524543
525544
// Load the box from the @Trait pair and GEP over the box header if
526545
// necessary:
527-
let llself;
546+
let mut llself;
547+
debug!("(translating trait callee) loading second index from pair");
528548
let llbox = Load(bcx, GEPi(bcx, llpair, [0u, 1u]));
529549
match vstore {
530550
ty::vstore_box | ty::vstore_uniq => {
@@ -538,7 +558,32 @@ fn trans_trait_callee_from_llval(bcx: block,
538558
}
539559
}
540560
561+
// Munge `llself` appropriately for the type of `self` in the method.
562+
match explicit_self {
563+
ast::sty_static => {
564+
bcx.tcx().sess.bug(~"shouldn't see static method here");
565+
}
566+
ast::sty_by_ref => {} // Nothing to do.
567+
ast::sty_value => {
568+
bcx.tcx().sess.bug(~"methods with by-value self should not be \
569+
called on objects");
570+
}
571+
ast::sty_region(_) => {
572+
let llscratch = alloca(bcx, val_ty(llself));
573+
Store(bcx, llself, llscratch);
574+
llself = llscratch;
575+
}
576+
ast::sty_box(_) => {
577+
// Bump the reference count on the box.
578+
debug!("(translating trait callee) callee type is `%s`",
579+
bcx.ty_to_str(callee_ty));
580+
bcx = glue::take_ty(bcx, llself, callee_ty);
581+
}
582+
ast::sty_uniq(_) => {} // Nothing to do here.
583+
}
584+
541585
// Load the function from the vtable and cast it to the expected type.
586+
debug!("(translating trait callee) loading method");
542587
let llcallee_ty = type_of::type_of_fn_from_ty(ccx, callee_ty);
543588
let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method]));
544589
let mptr = PointerCast(bcx, mptr, T_ptr(llcallee_ty));
@@ -622,8 +667,12 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t],
622667
make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| {
623668
let fty = ty::subst_tps(tcx, substs, None, ty::mk_fn(tcx, im.fty));
624669
if (*im.tps).len() > 0u || ty::type_has_self(fty) {
670+
debug!("(making impl vtable) method has self or type params: %s",
671+
tcx.sess.str_of(im.ident));
625672
C_null(T_ptr(T_nil()))
626673
} else {
674+
debug!("(making impl vtable) adding method to vtable: %s",
675+
tcx.sess.str_of(im.ident));
627676
let mut m_id = method_with_name(ccx, impl_id, im.ident);
628677
if has_tps {
629678
// If the method is in another crate, need to make an inlined

src/librustc/middle/trans/reflect.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,12 @@ impl reflector {
7272
// XXX: Should not be vstore_box!
7373
let bcx = callee::trans_call_inner(
7474
self.bcx, None, mth_ty, bool_ty,
75-
|bcx| meth::trans_trait_callee_from_llval(bcx, mth_ty,
76-
mth_idx, v,
77-
ty::vstore_box),
75+
|bcx| meth::trans_trait_callee_from_llval(bcx,
76+
mth_ty,
77+
mth_idx,
78+
v,
79+
ty::vstore_box,
80+
ast::sty_by_ref),
7881
ArgVals(args), SaveIn(scratch.val), DontAutorefArg);
7982
let result = scratch.to_value_llval(bcx);
8083
let next_bcx = sub_block(bcx, ~"next");
@@ -307,4 +310,4 @@ fn ast_proto_constant(proto: ast::Proto) -> uint {
307310
ast::ProtoBox => 3u,
308311
ast::ProtoBorrowed => 4u,
309312
}
310-
}
313+
}

src/librustc/middle/typeck/check/method.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ struct LookupContext {
130130
struct Candidate {
131131
rcvr_ty: ty::t,
132132
rcvr_substs: ty::substs,
133+
explicit_self: ast::self_ty_,
133134

134135
// FIXME #3446---these two fields should be easily derived from
135136
// origin, yet are not
@@ -406,6 +407,7 @@ impl LookupContext {
406407
let cand = Candidate {
407408
rcvr_ty: rcvr_ty,
408409
rcvr_substs: rcvr_substs,
410+
explicit_self: method.self_ty,
409411
num_method_tps: method.tps.len(),
410412
self_mode: get_mode_from_self_type(method.self_ty),
411413
origin: method_param({trait_id:init_trait_id,
@@ -465,6 +467,7 @@ impl LookupContext {
465467
self.inherent_candidates.push(Candidate {
466468
rcvr_ty: rcvr_ty,
467469
rcvr_substs: move rcvr_substs,
470+
explicit_self: method.self_ty,
468471
num_method_tps: method.tps.len(),
469472
self_mode: get_mode_from_self_type(method.self_ty),
470473
origin: method_trait(did, index, vstore)
@@ -492,6 +495,7 @@ impl LookupContext {
492495
self.inherent_candidates.push(Candidate {
493496
rcvr_ty: rcvr_ty,
494497
rcvr_substs: move rcvr_substs,
498+
explicit_self: method.self_ty,
495499
num_method_tps: method.tps.len(),
496500
self_mode: get_mode_from_self_type(method.self_ty),
497501
origin: method_self(did, index)
@@ -543,6 +547,7 @@ impl LookupContext {
543547
candidates.push(Candidate {
544548
rcvr_ty: impl_ty,
545549
rcvr_substs: move impl_substs,
550+
explicit_self: method.self_type,
546551
num_method_tps: method.n_tps,
547552
self_mode: get_mode_from_self_type(method.self_type),
548553
origin: method_static(method.did)
@@ -577,6 +582,7 @@ impl LookupContext {
577582
candidates.push(Candidate {
578583
rcvr_ty: impl_ty,
579584
rcvr_substs: move impl_substs,
585+
explicit_self: provided_method_info.method_info.self_type,
580586
num_method_tps: provided_method_info.method_info.n_tps,
581587
self_mode: get_mode_from_self_type(
582588
provided_method_info.method_info.self_type),
@@ -739,12 +745,25 @@ impl LookupContext {
739745
match self.search_for_method(autoref_ty) {
740746
None => {}
741747
Some(move mme) => {
742-
self.fcx.write_adjustment(
743-
self.self_expr.id,
744-
@{autoderefs: autoderefs,
745-
autoref: Some({kind: kind,
746-
region: region,
747-
mutbl: *mutbl})});
748+
match mme.origin {
749+
method_trait(*) => {
750+
// Do not write adjustments; they make no sense
751+
// here since the adjustments are to be performed
752+
// on the self element of the object pair/triple,
753+
// not the object itself.
754+
//
755+
// FIXME (#4088): This is wrong in the presence
756+
// of autoderef.
757+
}
758+
_ => {
759+
self.fcx.write_adjustment(
760+
self.self_expr.id,
761+
@{autoderefs: autoderefs,
762+
autoref: Some({kind: kind,
763+
region: region,
764+
mutbl: *mutbl})});
765+
}
766+
}
748767
return Some(mme);
749768
}
750769
}
@@ -911,6 +930,7 @@ impl LookupContext {
911930
self.fcx.write_ty_substs(self.callee_id, fty, all_substs);
912931
return {self_arg: {mode: ast::expl(candidate.self_mode),
913932
ty: candidate.rcvr_ty},
933+
explicit_self: candidate.explicit_self,
914934
origin: candidate.origin};
915935
}
916936

src/librustc/middle/typeck/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ type method_map_entry = {
134134
// in the fn type (FIXME #3446)
135135
self_arg: ty::arg,
136136

137+
// the type of explicit self on the method
138+
explicit_self: ast::self_ty_,
139+
137140
// method details being invoked
138141
origin: method_origin
139142
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
trait Foo {
2+
fn f(&self);
3+
}
4+
5+
struct S {
6+
x: int
7+
}
8+
9+
impl S : Foo {
10+
fn f(&self) {
11+
assert self.x == 3;
12+
}
13+
}
14+
15+
fn main() {
16+
let x = @S { x: 3 };
17+
let y = x as @Foo;
18+
y.f();
19+
}
20+
21+

0 commit comments

Comments
 (0)