Skip to content

Commit 817f980

Browse files
committed
Make calling methods parameterized on the trait work from default methods.
This is done by adding a new notion of "vtable_self". We do not yet properly handle super traits. Closes #7183.
1 parent a9e51f5 commit 817f980

File tree

9 files changed

+117
-31
lines changed

9 files changed

+117
-31
lines changed

src/librustc/middle/astencode.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,13 @@ fn encode_vtable_origin(ecx: &e::EncodeContext,
632632
}
633633
}
634634
}
635+
typeck::vtable_self(def_id) => {
636+
do ebml_w.emit_enum_variant("vtable_self", 2u, 1u) |ebml_w| {
637+
do ebml_w.emit_enum_variant_arg(0u) |ebml_w| {
638+
ebml_w.emit_def_id(def_id)
639+
}
640+
}
641+
}
635642
}
636643
}
637644
}
@@ -652,7 +659,9 @@ impl vtable_decoder_helpers for reader::Decoder {
652659
fn read_vtable_origin(&mut self, xcx: @ExtendedDecodeContext)
653660
-> typeck::vtable_origin {
654661
do self.read_enum("vtable_origin") |this| {
655-
do this.read_enum_variant(["vtable_static", "vtable_param"])
662+
do this.read_enum_variant(["vtable_static",
663+
"vtable_param",
664+
"vtable_self"])
656665
|this, i| {
657666
match i {
658667
0 => {
@@ -678,6 +687,13 @@ impl vtable_decoder_helpers for reader::Decoder {
678687
}
679688
)
680689
}
690+
2 => {
691+
typeck::vtable_self(
692+
do this.read_enum_variant_arg(0u) |this| {
693+
this.read_def_id(xcx)
694+
}
695+
)
696+
}
681697
// hard to avoid - user input
682698
_ => fail!("bad enum variant")
683699
}

src/librustc/middle/trans/base.rs

+1
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
461461
&tsubsts,
462462
None,
463463
None,
464+
None,
464465
None);
465466

466467
val

src/librustc/middle/trans/callee.rs

+27-4
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,9 @@ pub fn trans_fn_ref_with_vtables(
245245
// We need to do a bunch of special handling for default methods.
246246
// We need to modify the def_id and our substs in order to monomorphize
247247
// the function.
248-
let (def_id, opt_impl_did, substs) = match tcx.provided_method_sources.find(&def_id) {
249-
None => (def_id, None, substs),
248+
let (def_id, opt_impl_did, substs, self_vtable) =
249+
match tcx.provided_method_sources.find(&def_id) {
250+
None => (def_id, None, substs, None),
250251
Some(source) => {
251252
// There are two relevant substitutions when compiling
252253
// default methods. First, there is the substitution for
@@ -266,6 +267,26 @@ pub fn trans_fn_ref_with_vtables(
266267
default methods");
267268
let method = ty::method(tcx, source.method_id);
268269

270+
// Get all of the type params for the receiver
271+
let param_defs = method.generics.type_param_defs;
272+
let receiver_substs =
273+
type_params.initn(param_defs.len()).to_owned();
274+
let receiver_vtables = match vtables {
275+
None => @~[],
276+
Some(call_vtables) => {
277+
let num_method_vtables =
278+
ty::count_traits_and_supertraits(tcx, *param_defs);
279+
@call_vtables.initn(num_method_vtables).to_owned()
280+
}
281+
};
282+
283+
let self_vtable =
284+
typeck::vtable_static(source.impl_id, receiver_substs,
285+
receiver_vtables);
286+
287+
// XXX: I think that if the *trait* has vtables on it,
288+
// it is all over
289+
269290
// Compute the first substitution
270291
let first_subst = make_substs_for_receiver_types(
271292
tcx, source.impl_id, trait_ref, method);
@@ -279,7 +300,8 @@ pub fn trans_fn_ref_with_vtables(
279300
first_subst.repr(tcx), new_substs.repr(tcx));
280301

281302

282-
(source.method_id, Some(source.impl_id), new_substs)
303+
(source.method_id, Some(source.impl_id),
304+
new_substs, Some(self_vtable))
283305
}
284306
};
285307

@@ -326,7 +348,8 @@ pub fn trans_fn_ref_with_vtables(
326348

327349
let (val, must_cast) =
328350
monomorphize::monomorphic_fn(ccx, def_id, &substs,
329-
vtables, opt_impl_did, Some(ref_id));
351+
vtables, self_vtable,
352+
opt_impl_did, Some(ref_id));
330353
let mut val = val;
331354
if must_cast && ref_id != 0 {
332355
// Monotype of the REFERENCE to the function (type params

src/librustc/middle/trans/common.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ pub struct param_substs {
132132
tys: ~[ty::t],
133133
vtables: Option<typeck::vtable_res>,
134134
type_param_defs: @~[ty::TypeParameterDef],
135-
self_ty: Option<ty::t>
135+
self_ty: Option<ty::t>,
136+
self_vtable: Option<typeck::vtable_origin>
136137
}
137138

138139
impl param_substs {
@@ -981,7 +982,11 @@ pub fn monomorphize_type(bcx: block, t: ty::t) -> ty::t {
981982
Some(substs) => {
982983
ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t)
983984
}
984-
_ => { assert!(!ty::type_has_params(t)); t }
985+
_ => {
986+
assert!(!ty::type_has_params(t));
987+
assert!(!ty::type_has_self(t));
988+
t
989+
}
985990
}
986991
}
987992

@@ -1063,6 +1068,19 @@ pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
10631068
}
10641069
}
10651070
}
1071+
typeck::vtable_self(_trait_id) => {
1072+
match fcx.param_substs {
1073+
Some(@param_substs
1074+
{self_vtable: Some(ref self_vtable), _}) => {
1075+
copy *self_vtable
1076+
}
1077+
_ => {
1078+
tcx.sess.bug(fmt!(
1079+
"resolve_vtable_in_fn_ctxt: asked to lookup but \
1080+
no self_vtable in the fn_ctxt!"))
1081+
}
1082+
}
1083+
}
10661084
}
10671085
}
10681086

src/librustc/middle/trans/meth.rs

+22-19
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ pub fn trans_self_arg(bcx: block,
139139

140140
// Compute the type of self.
141141
let self_ty = monomorphize_type(bcx, mentry.self_ty);
142-
143142
let result = trans_arg_expr(bcx,
144143
self_ty,
145144
mentry.self_mode,
@@ -174,21 +173,6 @@ pub fn trans_method_callee(bcx: block,
174173
// Replace method_self with method_static here.
175174
let mut origin = mentry.origin;
176175
match origin {
177-
typeck::method_self(trait_id, method_index) => {
178-
// Get the ID of the impl we're inside.
179-
let impl_def_id = bcx.fcx.impl_id.get();
180-
181-
debug!("impl_def_id is %?", impl_def_id);
182-
183-
// Get the ID of the method we're calling.
184-
let method_name =
185-
ty::trait_method(tcx, trait_id, method_index).ident;
186-
let method_id =
187-
method_with_name_or_default(bcx.ccx(),
188-
impl_def_id,
189-
method_name);
190-
origin = typeck::method_static(method_id);
191-
}
192176
typeck::method_super(trait_id, method_index) => {
193177
// <self_ty> is the self type for this method call
194178
let self_ty = node_id_type(bcx, this.id);
@@ -213,6 +197,7 @@ pub fn trans_method_callee(bcx: block,
213197
impl_id,
214198
method_name));
215199
}
200+
typeck::method_self(*) |
216201
typeck::method_static(*) | typeck::method_param(*) |
217202
typeck::method_trait(*) => {}
218203
}
@@ -250,6 +235,21 @@ pub fn trans_method_callee(bcx: block,
250235
None => fail!("trans_method_callee: missing param_substs")
251236
}
252237
}
238+
239+
typeck::method_self(trait_id, method_index) => {
240+
match bcx.fcx.param_substs {
241+
Some(@param_substs
242+
{self_vtable: Some(ref vtbl), _}) => {
243+
trans_monomorphized_callee(bcx, callee_id, this, mentry,
244+
trait_id, method_index,
245+
copy *vtbl)
246+
}
247+
_ => {
248+
fail!("trans_method_callee: missing self_vtable")
249+
}
250+
}
251+
}
252+
253253
typeck::method_trait(_, off, store) => {
254254
trans_trait_callee(bcx,
255255
callee_id,
@@ -258,9 +258,9 @@ pub fn trans_method_callee(bcx: block,
258258
store,
259259
mentry.explicit_self)
260260
}
261-
typeck::method_self(*) | typeck::method_super(*) => {
262-
fail!("method_self or method_super should have been handled \
263-
above")
261+
typeck::method_super(*) => {
262+
fail!("method_super should have been handled \
263+
above")
264264
}
265265
}
266266
}
@@ -460,6 +460,9 @@ pub fn trans_monomorphized_callee(bcx: block,
460460
typeck::vtable_param(*) => {
461461
fail!("vtable_param left in monomorphized function's vtable substs");
462462
}
463+
typeck::vtable_self(*) => {
464+
fail!("vtable_self left in monomorphized function's vtable substs");
465+
}
463466
};
464467

465468
}

src/librustc/middle/trans/monomorphize.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
4343
fn_id: ast::def_id,
4444
real_substs: &ty::substs,
4545
vtables: Option<typeck::vtable_res>,
46+
self_vtable: Option<typeck::vtable_origin>,
4647
impl_did_opt: Option<ast::def_id>,
4748
ref_id: Option<ast::node_id>)
4849
-> (ValueRef, bool)
@@ -165,6 +166,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
165166
let mut pt = /* bad */copy (*pt);
166167
pt.push(elt);
167168
let s = mangle_exported_name(ccx, /*bad*/copy pt, mono_ty);
169+
debug!("monomorphize_fn mangled to %s", s);
168170

169171
let mk_lldecl = || {
170172
let lldecl = decl_internal_cdecl_fn(ccx.llmod, /*bad*/copy s, llfty);
@@ -176,7 +178,8 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
176178
tys: substs,
177179
vtables: vtables,
178180
type_param_defs: tpt.generics.type_param_defs,
179-
self_ty: real_substs.self_ty
181+
self_ty: real_substs.self_ty,
182+
self_vtable: self_vtable
180183
});
181184

182185
let lldecl = match map_node {

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

+13-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use middle::typeck::check::{structurally_resolved_type};
1717
use middle::typeck::infer::fixup_err_to_str;
1818
use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type};
1919
use middle::typeck::infer;
20-
use middle::typeck::{CrateCtxt, vtable_origin, vtable_param, vtable_res};
21-
use middle::typeck::vtable_static;
20+
use middle::typeck::{CrateCtxt, vtable_origin, vtable_res};
21+
use middle::typeck::{vtable_static, vtable_param, vtable_self};
2222
use middle::subst::Subst;
2323
use util::common::indenter;
2424
use util::ppaux::tys_to_str;
@@ -237,6 +237,17 @@ fn lookup_vtable(vcx: &VtableContext,
237237
}
238238
}
239239

240+
ty::ty_self(trait_id) => {
241+
debug!("trying to find %? vtable for type %?",
242+
trait_ref.def_id, trait_id);
243+
244+
if trait_id == trait_ref.def_id {
245+
let vtable = vtable_self(trait_id);
246+
debug!("found self vtable: %?", vtable);
247+
return Some(vtable);
248+
}
249+
}
250+
240251
_ => {
241252
let mut found = ~[];
242253

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use middle::typeck::check::{FnCtxt, SelfInfo};
2020
use middle::typeck::infer::{force_all, resolve_all, resolve_region};
2121
use middle::typeck::infer::resolve_type;
2222
use middle::typeck::infer;
23-
use middle::typeck::{vtable_origin, vtable_static, vtable_param};
23+
use middle::typeck::{vtable_origin, vtable_static, vtable_param, vtable_self};
2424
use middle::typeck::method_map_entry;
2525
use middle::typeck::write_substs_to_tcx;
2626
use middle::typeck::write_ty_to_tcx;
@@ -104,6 +104,9 @@ fn resolve_vtable_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) {
104104
&vtable_param(n, b) => {
105105
vtable_param(n, b)
106106
}
107+
&vtable_self(def_id) => {
108+
vtable_self(def_id)
109+
}
107110
}
108111
}
109112
}

src/librustc/middle/typeck/mod.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,12 @@ pub enum vtable_origin {
154154
The first uint is the param number (identifying T in the example),
155155
and the second is the bound number (identifying baz)
156156
*/
157-
vtable_param(uint, uint)
157+
vtable_param(uint, uint),
158+
159+
/*
160+
Dynamic vtable, comes from self.
161+
*/
162+
vtable_self(ast::def_id)
158163
}
159164

160165
impl Repr for vtable_origin {
@@ -171,6 +176,9 @@ impl Repr for vtable_origin {
171176
vtable_param(x, y) => {
172177
fmt!("vtable_param(%?, %?)", x, y)
173178
}
179+
vtable_self(def_id) => {
180+
fmt!("vtable_self(%?)", def_id)
181+
}
174182
}
175183
}
176184
}

0 commit comments

Comments
 (0)