Skip to content

Commit e0fa5cd

Browse files
committed
Self types for ifaces
This allows a 'Name:' to appear in front of an iface declaration's name, which will cause 'Name' to refer to the self type (with the same number of type parameters as the iface has) in the method signatures of the iface. For example: iface F: functor<A> { fn fmap<B>(f: fn(A) -> B) -> F<B>; } Issue #1718
1 parent 5c42e3d commit e0fa5cd

File tree

10 files changed

+242
-149
lines changed

10 files changed

+242
-149
lines changed

src/comp/metadata/tydecode.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,13 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
216216
let did = parse_def(st, conv);
217217
ret ty::mk_param(st.tcx, parse_int(st) as uint, did);
218218
}
219+
's' {
220+
assert next(st) as char == '[';
221+
let params = [];
222+
while peek(st) as char != ']' { params += [parse_ty(st, conv)]; }
223+
st.pos += 1u;
224+
ret ty::mk_self(st.tcx, params);
225+
}
219226
'@' { ret ty::mk_box(st.tcx, parse_mt(st, conv)); }
220227
'~' { ret ty::mk_uniq(st.tcx, parse_mt(st, conv)); }
221228
'*' { ret ty::mk_ptr(st.tcx, parse_mt(st, conv)); }

src/comp/metadata/tyencode.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
169169
w.write_char('|');
170170
w.write_str(uint::str(id));
171171
}
172+
ty::ty_self(tps) {
173+
w.write_str("s[");
174+
for t in tps { enc_ty(w, cx, t); }
175+
w.write_char(']');
176+
}
172177
ty::ty_type { w.write_char('Y'); }
173178
ty::ty_send_type { w.write_char('y'); }
174179
ty::ty_opaque_closure_ptr(ty::ck_block) { w.write_str("C&"); }

src/comp/middle/resolve.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -888,10 +888,17 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
888888
ast::item_impl(tps, _, _, _) {
889889
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
890890
}
891-
ast::item_iface(tps, _) | ast::item_enum(_, tps) |
892-
ast::item_ty(_, tps) {
891+
ast::item_enum(_, tps) | ast::item_ty(_, tps) {
893892
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
894893
}
894+
ast::item_iface(tps, _) {
895+
if ns == ns_type {
896+
if name == "self" {
897+
ret some(def_self(local_def(it.id)));
898+
}
899+
ret lookup_in_ty_params(e, name, tps);
900+
}
901+
}
895902
ast::item_mod(_) {
896903
ret lookup_in_local_mod(e, it.id, sp, name, ns, inside);
897904
}

src/comp/middle/shape.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -421,9 +421,6 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
421421
add_substr(s, shape_of(ccx, subt, ty_param_map));
422422

423423
}
424-
ty::ty_var(n) {
425-
fail "shape_of ty_var";
426-
}
427424
ty::ty_param(n, _) {
428425
// Find the type parameter in the parameter list.
429426
alt vec::position_elt(ty_param_map, n) {
@@ -450,8 +447,8 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
450447
ty::ty_constr(inner_t, _) {
451448
s += shape_of(ccx, inner_t, ty_param_map);
452449
}
453-
ty::ty_named(_, _) {
454-
ccx.tcx.sess.bug("shape_of: shouldn't see a ty_named");
450+
ty::ty_var(_) | ty::ty_named(_, _) | ty::ty_self(_) {
451+
ccx.tcx.sess.bug("shape_of: unexpected type struct found");
455452
}
456453
}
457454

src/comp/middle/trans/base.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5315,7 +5315,10 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item) {
53155315
impl::trans_impl_vtable(ccx, item_path(ccx, it), i_did, ms, tps, it);
53165316
}
53175317
ast::item_iface(_, _) {
5318-
impl::trans_iface_vtable(ccx, item_path(ccx, it), it);
5318+
if !vec::any(*ty::iface_methods(ccx.tcx, local_def(it.id)), {|m|
5319+
ty::type_contains_vars(ccx.tcx, ty::mk_fn(ccx.tcx, m.fty))}) {
5320+
impl::trans_iface_vtable(ccx, item_path(ccx, it), it);
5321+
}
53195322
}
53205323
_ { }
53215324
}

src/comp/middle/trans/impl.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,9 @@ fn trans_static_callee(bcx: @block_ctxt, callee_id: ast::node_id,
9494
{env: self_env(val) with lval_static_fn(bcx, did, callee_id)}
9595
}
9696

97-
fn wrapper_fn_ty(ccx: @crate_ctxt, dict_ty: TypeRef, m: ty::method)
98-
-> {ty: ty::t, llty: TypeRef} {
99-
let fty = ty::mk_fn(ccx.tcx, m.fty);
100-
let bare_fn_ty = type_of_fn_from_ty(ccx, fty, *m.tps);
97+
fn wrapper_fn_ty(ccx: @crate_ctxt, dict_ty: TypeRef, fty: ty::t,
98+
tps: @[ty::param_bounds]) -> {ty: ty::t, llty: TypeRef} {
99+
let bare_fn_ty = type_of_fn_from_ty(ccx, fty, *tps);
101100
let {inputs, output} = llfn_arg_tys(bare_fn_ty);
102101
{ty: fty, llty: T_fn([dict_ty] + inputs, output)}
103102
}
@@ -107,7 +106,9 @@ fn trans_vtable_callee(bcx: @block_ctxt, self: ValueRef, dict: ValueRef,
107106
n_method: uint) -> lval_maybe_callee {
108107
let bcx = bcx, ccx = bcx_ccx(bcx), tcx = ccx.tcx;
109108
let method = ty::iface_methods(tcx, iface_id)[n_method];
110-
let {ty: fty, llty: llfty} = wrapper_fn_ty(ccx, val_ty(dict), method);
109+
let {ty: fty, llty: llfty} =
110+
wrapper_fn_ty(ccx, val_ty(dict), ty::node_id_to_type(tcx, callee_id),
111+
method.tps);
111112
let vtable = PointerCast(bcx, Load(bcx, GEPi(bcx, dict, [0, 0])),
112113
T_ptr(T_array(T_ptr(llfty), n_method + 1u)));
113114
let mptr = Load(bcx, GEPi(bcx, vtable, [0, n_method as int]));
@@ -266,7 +267,8 @@ fn trans_impl_vtable(ccx: @crate_ctxt, pt: path,
266267

267268
fn trans_iface_wrapper(ccx: @crate_ctxt, pt: path, m: ty::method,
268269
n: uint) -> ValueRef {
269-
let {llty: llfty, _} = wrapper_fn_ty(ccx, T_ptr(T_i8()), m);
270+
let {llty: llfty, _} = wrapper_fn_ty(ccx, T_ptr(T_i8()),
271+
ty::mk_fn(ccx.tcx, m.fty), m.tps);
270272
trans_wrapper(ccx, pt, llfty, {|llfn, bcx|
271273
let self = Load(bcx, PointerCast(bcx,
272274
LLVMGetParam(llfn, 2u as c_uint),
@@ -358,10 +360,7 @@ fn dict_id(tcx: ty::ctxt, origin: typeck::dict_origin) -> dict_id {
358360
d_params += [dict_param_dict(dict_id(tcx, origs[orig]))];
359361
orig += 1u;
360362
}
361-
_ {
362-
tcx.sess.bug("Someone forgot to document an invariant in \
363-
dict_id");
364-
}
363+
_ {}
365364
}
366365
}
367366
}

src/comp/middle/ty.rs

Lines changed: 19 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export mk_send_type;
8080
export mk_uint;
8181
export mk_uniq;
8282
export mk_var;
83+
export mk_self;
8384
export mk_opaque_closure_ptr;
8485
export mk_named;
8586
export gen_ty;
@@ -126,6 +127,7 @@ export ty_send_type;
126127
export ty_uint;
127128
export ty_uniq;
128129
export ty_var;
130+
export ty_self;
129131
export ty_named;
130132
export same_type;
131133
export ty_var_id;
@@ -266,9 +268,10 @@ enum sty {
266268
ty_iface(def_id, [t]),
267269
ty_res(def_id, t, [t]),
268270
ty_tup([t]),
269-
ty_var(int), // type variable
270271

271-
ty_param(uint, def_id), // fn/enum type param
272+
ty_var(int), // type variable during typechecking
273+
ty_param(uint, def_id), // type parameter
274+
ty_self([t]), // interface method self type
272275

273276
ty_type, // type_desc*
274277
ty_send_type, // type_desc* that has been cloned into exchange heap
@@ -324,45 +327,25 @@ type ty_param_bounds_and_ty = {bounds: @[param_bounds], ty: t};
324327
type type_cache = hashmap<ast::def_id, ty_param_bounds_and_ty>;
325328

326329
const idx_nil: uint = 0u;
327-
328330
const idx_bool: uint = 1u;
329-
330331
const idx_int: uint = 2u;
331-
332332
const idx_float: uint = 3u;
333-
334333
const idx_uint: uint = 4u;
335-
336334
const idx_i8: uint = 5u;
337-
338335
const idx_i16: uint = 6u;
339-
340336
const idx_i32: uint = 7u;
341-
342337
const idx_i64: uint = 8u;
343-
344338
const idx_u8: uint = 9u;
345-
346339
const idx_u16: uint = 10u;
347-
348340
const idx_u32: uint = 11u;
349-
350341
const idx_u64: uint = 12u;
351-
352342
const idx_f32: uint = 13u;
353-
354343
const idx_f64: uint = 14u;
355-
356344
const idx_char: uint = 15u;
357-
358345
const idx_str: uint = 16u;
359-
360346
const idx_type: uint = 17u;
361-
362347
const idx_send_type: uint = 18u;
363-
364348
const idx_bot: uint = 19u;
365-
366349
const idx_first_others: uint = 20u;
367350

368351
type type_store = interner::interner<@raw_t>;
@@ -462,7 +445,7 @@ fn mk_raw_ty(cx: ctxt, st: sty) -> @raw_t {
462445
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
463446
ty_str | ty_type | ty_send_type | ty_opaque_closure_ptr(_) {}
464447
ty_param(_, _) { has_params = true; }
465-
ty_var(_) { has_vars = true; }
448+
ty_var(_) | ty_self(_) { has_vars = true; }
466449
ty_enum(_, tys) | ty_iface(_, tys) {
467450
for tt: t in tys { derive_flags_t(cx, has_params, has_vars, tt); }
468451
}
@@ -598,6 +581,8 @@ fn mk_res(cx: ctxt, did: ast::def_id, inner: t, tps: [t]) -> t {
598581

599582
fn mk_var(cx: ctxt, v: int) -> t { ret gen_ty(cx, ty_var(v)); }
600583

584+
fn mk_self(cx: ctxt, tps: [t]) -> t { ret gen_ty(cx, ty_self(tps)); }
585+
601586
fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
602587
ret gen_ty(cx, ty_param(n, k));
603588
}
@@ -653,7 +638,6 @@ pure fn ty_name(cx: ctxt, typ: t) -> option<@str> {
653638
}
654639

655640
fn default_arg_mode_for_ty(tcx: ty::ctxt, ty: ty::t) -> ast::rmode {
656-
assert !ty::type_contains_vars(tcx, ty);
657641
if ty::type_is_immediate(tcx, ty) { ast::by_val }
658642
else { ast::by_ref }
659643
}
@@ -664,7 +648,7 @@ fn walk_ty(cx: ctxt, ty: t, f: fn(t)) {
664648
ty_str | ty_send_type | ty_type |
665649
ty_opaque_closure_ptr(_) | ty_var(_) | ty_param(_, _) {}
666650
ty_box(tm) | ty_vec(tm) | ty_ptr(tm) { walk_ty(cx, tm.ty, f); }
667-
ty_enum(_, subtys) | ty_iface(_, subtys) {
651+
ty_enum(_, subtys) | ty_iface(_, subtys) | ty_self(subtys) {
668652
for subty: t in subtys { walk_ty(cx, subty, f); }
669653
}
670654
ty_rec(fields) {
@@ -728,6 +712,9 @@ fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t {
728712
ty_iface(did, subtys) {
729713
ty = mk_iface(cx, did, vec::map(subtys, {|t| fold_ty(cx, fld, t) }));
730714
}
715+
ty_self(subtys) {
716+
ty = mk_self(cx, vec::map(subtys, {|t| fold_ty(cx, fld, t) }));
717+
}
731718
ty_rec(fields) {
732719
let new_fields: [field] = [];
733720
for fl: field in fields {
@@ -1189,15 +1176,9 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
11891176
result = type_is_pod(cx, substitute_type_params(cx, tps, inner));
11901177
}
11911178
ty_constr(subt, _) { result = type_is_pod(cx, subt); }
1192-
ty_var(_) {
1193-
cx.sess.bug("ty_var in type_is_pod");
1194-
}
11951179
ty_param(_, _) { result = false; }
11961180
ty_opaque_closure_ptr(_) { result = true; }
1197-
ty_named(_,_) {
1198-
cx.sess.bug("ty_named in type_is_pod");
1199-
}
1200-
1181+
_ { cx.sess.bug("unexpected type in type_is_pod"); }
12011182
}
12021183

12031184
ret result;
@@ -1352,6 +1333,11 @@ fn hash_type_structure(st: sty) -> uint {
13521333
ty_fn(f) { ret hash_fn(27u, f.inputs, f.output); }
13531334
ty_var(v) { ret hash_uint(30u, v as uint); }
13541335
ty_param(pid, _) { ret hash_uint(31u, pid); }
1336+
ty_self(ts) {
1337+
let h = 28u;
1338+
for t in ts { h += (h << 5u) + t; }
1339+
ret h;
1340+
}
13551341
ty_type { ret 32u; }
13561342
ty_bot { ret 34u; }
13571343
ty_ptr(mt) { ret hash_subty(35u, mt.ty); }
@@ -2548,19 +2534,8 @@ fn type_err_to_str(err: ty::type_err) -> str {
25482534
// Replaces type parameters in the given type using the given list of
25492535
// substitions.
25502536
fn substitute_type_params(cx: ctxt, substs: [ty::t], typ: t) -> t {
2551-
if !type_contains_params(cx, typ) { ret typ; }
25522537
// Precondition? idx < vec::len(substs)
2553-
fn substituter(_cx: ctxt, substs: @[ty::t], idx: uint, _did: def_id)
2554-
-> t {
2555-
if idx < vec::len(*substs) {
2556-
ret substs[idx];
2557-
}
2558-
else {
2559-
fail #fmt("Internal error in substituter (substitute_type_params)\
2560-
%u %u", vec::len(*substs), idx);
2561-
}
2562-
}
2563-
ret fold_ty(cx, fm_param(bind substituter(cx, @substs, _, _)), typ);
2538+
fold_ty(cx, fm_param({|idx, _id| substs[idx]}), typ)
25642539
}
25652540

25662541
fn def_has_ty_params(def: ast::def) -> bool {

0 commit comments

Comments
 (0)