Skip to content

Commit 7efef98

Browse files
committed
Make uses of self in impls compile
Get rid of expr_self_call, introduces def_self. `self` is now, syntactically, simply a variable. A method implicitly brings a `self` binding into scope. Issue #1227
1 parent 1dd2f1e commit 7efef98

17 files changed

+137
-203
lines changed

src/comp/middle/alias.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
240240
}
241241
let f_may_close =
242242
alt f.node {
243-
ast::expr_path(_) { def_is_local(cx.tcx.def_map.get(f.id), true) }
243+
ast::expr_path(_) { def_is_local(cx.tcx.def_map.get(f.id)) }
244244
_ { true }
245245
};
246246
if f_may_close {
@@ -374,7 +374,7 @@ fn check_for(cx: ctx, local: @ast::local, seq: @ast::expr, blk: ast::blk,
374374
fn check_var(cx: ctx, ex: @ast::expr, p: @ast::path, id: ast::node_id,
375375
assign: bool, sc: scope) {
376376
let def = cx.tcx.def_map.get(id);
377-
if !def_is_local(def, false) { ret; }
377+
if !def_is_local(def) { ret; }
378378
let my_defnum = ast_util::def_id_of_def(def).node;
379379
let my_local_id = local_id_of_node(cx, my_defnum);
380380
let var_t = ty::expr_ty(cx.tcx, ex);
@@ -529,20 +529,19 @@ fn ty_can_unsafely_include(cx: ctx, needle: unsafe_ty, haystack: ty::t,
529529
ret helper(cx.tcx, needle, haystack, mut);
530530
}
531531

532-
fn def_is_local(d: ast::def, objfields_count: bool) -> bool {
533-
ret alt d {
534-
ast::def_local(_, _) | ast::def_arg(_, _) | ast::def_binding(_) |
535-
ast::def_upvar(_, _, _) | ast::def_self(_) {
536-
true
537-
}
538-
ast::def_obj_field(_, _) { objfields_count }
539-
_ { false }
540-
};
532+
fn def_is_local(d: ast::def) -> bool {
533+
alt d {
534+
ast::def_local(_, _) | ast::def_arg(_, _) | ast::def_binding(_) |
535+
ast::def_upvar(_, _, _) | ast::def_self(_) |
536+
ast::def_obj_field(_, _) { true }
537+
_ { false }
538+
}
541539
}
542540

543541
fn local_id_of_node(cx: ctx, id: node_id) -> uint {
544-
alt cx.tcx.items.get(id) {
545-
ast_map::node_arg(_, id) | ast_map::node_local(id) { id }
542+
alt cx.tcx.items.find(id) {
543+
some(ast_map::node_arg(_, id)) | some(ast_map::node_local(id)) { id }
544+
_ { 0u }
546545
}
547546
}
548547

src/comp/middle/mut.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ fn check_move_rhs(cx: @ctx, src: @expr) {
203203
def_obj_field(_, _) {
204204
mk_err(cx, src.span, msg_move_out, "object field");
205205
}
206+
def_self(_) {
207+
mk_err(cx, src.span, msg_move_out, "method self");
208+
}
206209
_ { }
207210
}
208211
check_lval(cx, src, msg_move_out);

src/comp/middle/resolve.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ tag scope {
3737
scope_loop(@ast::local); // there's only 1 decl per loop.
3838
scope_block(ast::blk, @mutable uint, @mutable uint);
3939
scope_arm(ast::arm);
40+
scope_self(ast::node_id);
4041
}
4142

4243
type scopes = list<scope>;
@@ -437,6 +438,9 @@ fn visit_expr_with_scope(x: @ast::expr, sc: scopes, v: vt<scopes>) {
437438
v.visit_local(decl, new_sc, v);
438439
v.visit_block(blk, new_sc, v);
439440
}
441+
ast::expr_anon_obj(_) {
442+
visit::visit_expr(x, cons(scope_self(x.id), @sc), v);
443+
}
440444
_ { visit::visit_expr(x, sc, v); }
441445
}
442446
}
@@ -723,7 +727,10 @@ fn def_is_local(d: def) -> bool {
723727
}
724728

725729
fn def_is_obj_field(d: def) -> bool {
726-
ret alt d { ast::def_obj_field(_, _) { true } _ { false } };
730+
alt d {
731+
ast::def_obj_field(_, _) | ast::def_self(_) { true }
732+
_ { false }
733+
}
727734
}
728735

729736
fn def_is_ty_arg(d: def) -> bool {
@@ -741,7 +748,7 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
741748
scope_item(it) {
742749
alt it.node {
743750
ast::item_obj(ob, ty_params, _) {
744-
ret lookup_in_obj(name, ob, ty_params, ns);
751+
ret lookup_in_obj(name, ob, ty_params, ns, it.id);
745752
}
746753
ast::item_impl(_, _, _) {
747754
if (name == "self" && ns == ns_value) {
@@ -763,6 +770,11 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
763770
_ { }
764771
}
765772
}
773+
scope_self(id) {
774+
if (name == "self" && ns == ns_value) {
775+
ret some(ast::def_self(local_def(id)));
776+
}
777+
}
766778
scope_native_item(it) {
767779
alt it.node {
768780
ast::native_item_fn(decl, ty_params) {
@@ -881,9 +893,10 @@ fn lookup_in_fn(name: ident, decl: ast::fn_decl, ty_params: [ast::ty_param],
881893
}
882894

883895
fn lookup_in_obj(name: ident, ob: ast::_obj, ty_params: [ast::ty_param],
884-
ns: namespace) -> option::t<def> {
896+
ns: namespace, id: node_id) -> option::t<def> {
885897
alt ns {
886898
ns_value. {
899+
if name == "self" { ret some(ast::def_self(local_def(id))); }
887900
for f: ast::obj_field in ob.fields {
888901
if str::eq(f.ident, name) {
889902
ret some(ast::def_obj_field(local_def(f.id), f.mut));
@@ -1295,23 +1308,17 @@ fn index_nmod(md: ast::native_mod) -> mod_index {
12951308

12961309
// External lookups
12971310
fn ns_for_def(d: def) -> namespace {
1298-
ret alt d {
1299-
ast::def_fn(_, _) { ns_value }
1300-
ast::def_obj_field(_, _) { ns_value }
1301-
ast::def_mod(_) { ns_module }
1302-
ast::def_native_mod(_) { ns_module }
1303-
ast::def_const(_) { ns_value }
1304-
ast::def_arg(_, _) { ns_value }
1305-
ast::def_local(_, _) { ns_value }
1306-
ast::def_upvar(_, _, _) { ns_value }
1307-
ast::def_variant(_, _) { ns_value }
1308-
ast::def_ty(_) { ns_type }
1309-
ast::def_binding(_) { ns_type }
1310-
ast::def_use(_) { ns_module }
1311-
ast::def_native_ty(_) { ns_type }
1312-
ast::def_native_fn(_, _) { ns_value }
1313-
ast::def_self(_) { ns_value }
1314-
};
1311+
alt d {
1312+
ast::def_fn(_, _) | ast::def_obj_field(_, _) | ast::def_self(_) |
1313+
ast::def_const(_) | ast::def_arg(_, _) | ast::def_local(_, _) |
1314+
ast::def_upvar(_, _, _) | ast::def_variant(_, _) |
1315+
ast::def_native_fn(_, _) | ast::def_self(_) { ns_value }
1316+
1317+
ast::def_mod(_) | ast::def_native_mod(_) { ns_module }
1318+
1319+
ast::def_ty(_) | ast::def_binding(_) | ast::def_use(_) |
1320+
ast::def_native_ty(_) { ns_type }
1321+
}
13151322
}
13161323

13171324
fn lookup_external(e: env, cnum: int, ids: [ident], ns: namespace) ->

src/comp/middle/trans.rs

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2678,7 +2678,9 @@ fn trans_local_var(cx: @block_ctxt, def: ast::def) -> local_var_result {
26782678
ret { val: cx.fcx.llobjfields.get(did.node), kind: owned };
26792679
}
26802680
ast::def_self(did) {
2681-
ret lval_owned(cx, cx.fcx.llenv);
2681+
let slf = option::get(cx.fcx.llself);
2682+
let ptr = PointerCast(cx, slf.v, T_ptr(type_of_or_i8(cx, slf.t)));
2683+
ret {val: ptr, kind: owned};
26822684
}
26832685
_ {
26842686
bcx_ccx(cx).sess.span_unimpl
@@ -2832,21 +2834,29 @@ fn trans_index(cx: @block_ctxt, sp: span, base: @ast::expr, idx: @ast::expr,
28322834
ret lval_owned(next_cx, elt);
28332835
}
28342836

2837+
fn expr_is_lval(bcx: @block_ctxt, e: @ast::expr) -> bool {
2838+
let ccx = bcx_ccx(bcx);
2839+
ty::expr_is_lval(ccx.method_map, ccx.tcx, e)
2840+
}
2841+
28352842
// This is for impl methods, not obj methods.
28362843
fn trans_method_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
28372844
did: ast::def_id) -> lval_maybe_callee {
2838-
let bcx = trans_expr(bcx, base, ignore); // FIXME pass self
2839-
lval_static_fn(bcx, did, e.id)
2845+
let tz = [], tr = [];
2846+
let basety = ty::expr_ty(bcx_tcx(bcx), base);
2847+
let {bcx, val} = trans_arg_expr(bcx, {mode: ast::by_ref, ty: basety},
2848+
type_of_or_i8(bcx, basety), tz, tr, base);
2849+
let val = PointerCast(bcx, val, T_opaque_boxed_closure_ptr(bcx_ccx(bcx)));
2850+
{env: obj_env(val) with lval_static_fn(bcx, did, e.id)}
28402851
}
28412852

28422853
fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
28432854
alt e.node {
28442855
ast::expr_path(p) { ret trans_path(bcx, p, e.id); }
28452856
ast::expr_field(base, ident) {
2846-
let method_map = bcx_ccx(bcx).method_map;
28472857
// Lval means this is a record field, so not a method
2848-
if !ty::expr_is_lval(method_map, bcx_tcx(bcx), e) {
2849-
alt method_map.find(e.id) {
2858+
if !expr_is_lval(bcx, e) {
2859+
alt bcx_ccx(bcx).method_map.find(e.id) {
28502860
some(did) { // An impl method
28512861
ret trans_method_callee(bcx, e, base, did);
28522862
}
@@ -2858,15 +2868,6 @@ fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
28582868
}
28592869
}
28602870
}
2861-
ast::expr_self_method(ident) {
2862-
alt bcx.fcx.llself {
2863-
some(pair) {
2864-
let fld = trans_object_field_inner(bcx, pair.v, ident, pair.t);
2865-
ret {bcx: fld.bcx, val: fld.mthptr, kind: owned,
2866-
env: obj_env(fld.objptr), generic: none};
2867-
}
2868-
}
2869-
}
28702871
_ {}
28712872
}
28722873
let lv = trans_temp_lval(bcx, e);
@@ -3475,7 +3476,7 @@ fn trans_expr_save_in(bcx: @block_ctxt, e: @ast::expr, dest: ValueRef)
34753476
// use trans_temp_expr.
34763477
fn trans_temp_lval(bcx: @block_ctxt, e: @ast::expr) -> lval_result {
34773478
let bcx = bcx;
3478-
if ty::expr_is_lval(bcx_ccx(bcx).method_map, bcx_tcx(bcx), e) {
3479+
if expr_is_lval(bcx, e) {
34793480
ret trans_lval(bcx, e);
34803481
} else {
34813482
let tcx = bcx_tcx(bcx);
@@ -3513,7 +3514,7 @@ fn trans_temp_expr(bcx: @block_ctxt, e: @ast::expr) -> result {
35133514
// - exprs with non-immediate type never get dest=by_val
35143515
fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
35153516
let tcx = bcx_tcx(bcx);
3516-
if ty::expr_is_lval(bcx_ccx(bcx).method_map, tcx, e) {
3517+
if expr_is_lval(bcx, e) {
35173518
ret lval_to_dps(bcx, e, dest);
35183519
}
35193520

@@ -3555,7 +3556,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
35553556
ret trans_closure::trans_bind(bcx, f, args, e.id, dest);
35563557
}
35573558
ast::expr_copy(a) {
3558-
if !ty::expr_is_lval(bcx_ccx(bcx).method_map, tcx, a) {
3559+
if !expr_is_lval(bcx, a) {
35593560
ret trans_expr(bcx, a, dest);
35603561
}
35613562
else { ret lval_to_dps(bcx, a, dest); }
@@ -3957,9 +3958,7 @@ fn init_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
39573958
let bcx = bcx;
39583959
alt local.node.init {
39593960
some(init) {
3960-
if init.op == ast::init_assign ||
3961-
!ty::expr_is_lval(bcx_ccx(bcx).method_map, bcx_tcx(bcx),
3962-
init.expr) {
3961+
if init.op == ast::init_assign || !expr_is_lval(bcx, init.expr) {
39633962
bcx = trans_expr_save_in(bcx, init.expr, llptr);
39643963
} else { // This is a move from an lval, must perform an actual move
39653964
let sub = trans_lval(bcx, init.expr);
@@ -4347,15 +4346,15 @@ fn new_fn_ctxt(cx: @local_ctxt, sp: span, llfndecl: ValueRef) -> @fn_ctxt {
43474346
// spaces that have been created for them (by code in the llallocas field of
43484347
// the function's fn_ctxt). create_llargs_for_fn_args populates the llargs
43494348
// field of the fn_ctxt with
4350-
fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: option::t<ty::t>,
4349+
fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: self_arg,
43514350
args: [ast::arg], ty_params: [ast::ty_param]) {
43524351
// Skip the implicit arguments 0, and 1. TODO: Pull out 2u and define
43534352
// it as a constant, since we're using it in several places in trans this
43544353
// way.
43554354
let arg_n = 2u;
43564355
alt ty_self {
4357-
some(tt) { cx.llself = some::<val_self_pair>({v: cx.llenv, t: tt}); }
4358-
none. {
4356+
obj_self(tt) | impl_self(tt) { cx.llself = some({v: cx.llenv, t: tt}); }
4357+
no_self. {
43594358
let i = 0u;
43604359
for tp: ast::ty_param in ty_params {
43614360
let llarg = llvm::LLVMGetParam(cx.llfn, arg_n);
@@ -4473,19 +4472,23 @@ fn finish_fn(fcx: @fn_ctxt, lltop: BasicBlockRef) {
44734472
RetVoid(ret_cx);
44744473
}
44754474

4475+
tag self_arg { obj_self(ty::t); impl_self(ty::t); no_self; }
4476+
44764477
// trans_closure: Builds an LLVM function out of a source function.
44774478
// If the function closes over its environment a closure will be
44784479
// returned.
44794480
fn trans_closure(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef,
4480-
ty_self: option::t<ty::t>, ty_params: [ast::ty_param],
4481+
ty_self: self_arg, ty_params: [ast::ty_param],
44814482
id: ast::node_id, maybe_load_env: block(@fn_ctxt)) {
44824483
set_uwtable(llfndecl);
44834484

44844485
// Set up arguments to the function.
44854486
let fcx = new_fn_ctxt_w_id(cx, sp, llfndecl, id, f.decl.cf);
44864487
create_llargs_for_fn_args(fcx, ty_self, f.decl.inputs, ty_params);
4487-
alt fcx.llself {
4488-
some(llself) { populate_fn_ctxt_from_llself(fcx, llself); }
4488+
alt ty_self {
4489+
obj_self(_) {
4490+
populate_fn_ctxt_from_llself(fcx, option::get(fcx.llself));
4491+
}
44894492
_ { }
44904493
}
44914494

@@ -4526,7 +4529,7 @@ fn trans_closure(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef,
45264529
// trans_fn: creates an LLVM function corresponding to a source language
45274530
// function.
45284531
fn trans_fn(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef,
4529-
ty_self: option::t<ty::t>, ty_params: [ast::ty_param],
4532+
ty_self: self_arg, ty_params: [ast::ty_param],
45304533
id: ast::node_id) {
45314534
let do_time = cx.ccx.sess.get_opts().stats;
45324535
let start = do_time ? time::get_time() : {sec: 0u32, usec: 0u32};
@@ -4549,7 +4552,7 @@ fn trans_res_ctor(cx: @local_ctxt, sp: span, dtor: ast::_fn,
45494552
}
45504553
let fcx = new_fn_ctxt(cx, sp, llctor_decl);
45514554
let ret_t = ty::ret_ty_of_fn(cx.ccx.tcx, ctor_id);
4552-
create_llargs_for_fn_args(fcx, none, dtor.decl.inputs, ty_params);
4555+
create_llargs_for_fn_args(fcx, no_self, dtor.decl.inputs, ty_params);
45534556
let bcx = new_top_block_ctxt(fcx);
45544557
let lltop = bcx.llbb;
45554558
let arg_t = arg_tys_of_fn(ccx, ctor_id)[0].ty;
@@ -4608,7 +4611,7 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id,
46084611
}
46094612
}
46104613
let fcx = new_fn_ctxt(cx, variant.span, llfndecl);
4611-
create_llargs_for_fn_args(fcx, none, fn_args, ty_params);
4614+
create_llargs_for_fn_args(fcx, no_self, fn_args, ty_params);
46124615
let ty_param_substs: [ty::t] = [];
46134616
i = 0u;
46144617
for tp: ast::ty_param in ty_params {
@@ -4655,13 +4658,15 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id,
46554658
finish_fn(fcx, lltop);
46564659
}
46574660

4658-
fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method]) {
4661+
fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method],
4662+
id: ast::node_id) {
46594663
let sub_cx = extend_path(cx, name);
46604664
for m in methods {
46614665
alt cx.ccx.item_ids.find(m.node.id) {
4662-
some(llfndecl) {
4666+
some(llfn) {
46634667
trans_fn(extend_path(sub_cx, m.node.ident), m.span, m.node.meth,
4664-
llfndecl, none, [], m.node.id);
4668+
llfn, impl_self(ty::node_id_to_monotype(cx.ccx.tcx, id)),
4669+
[], m.node.id);
46654670
}
46664671
}
46674672
}
@@ -4961,7 +4966,7 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
49614966
let sub_cx = extend_path(cx, item.ident);
49624967
alt cx.ccx.item_ids.find(item.id) {
49634968
some(llfndecl) {
4964-
trans_fn(sub_cx, item.span, f, llfndecl, none, tps, item.id);
4969+
trans_fn(sub_cx, item.span, f, llfndecl, no_self, tps, item.id);
49654970
}
49664971
_ {
49674972
cx.ccx.sess.span_fatal(item.span,
@@ -4975,14 +4980,14 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
49754980
with *extend_path(cx, item.ident)};
49764981
trans_obj(sub_cx, item.span, ob, ctor_id, tps);
49774982
}
4978-
ast::item_impl(_, _, ms) { trans_impl(cx, item.ident, ms); }
4983+
ast::item_impl(_, _, ms) { trans_impl(cx, item.ident, ms, item.id); }
49794984
ast::item_res(dtor, dtor_id, tps, ctor_id) {
49804985
trans_res_ctor(cx, item.span, dtor, ctor_id, tps);
49814986

49824987
// Create a function for the destructor
49834988
alt cx.ccx.item_ids.find(item.id) {
49844989
some(lldtor_decl) {
4985-
trans_fn(cx, item.span, dtor, lldtor_decl, none, tps, dtor_id);
4990+
trans_fn(cx, item.span, dtor, lldtor_decl, no_self, tps, dtor_id);
49864991
}
49874992
_ {
49884993
cx.ccx.sess.span_fatal(item.span, "unbound dtor in trans_item");

src/comp/middle/trans_closure.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ fn trans_expr_fn(bcx: @block_ctxt, f: ast::_fn, sp: span,
339339
let trans_closure_env = lambda(ck: ty::closure_kind) -> ValueRef {
340340
let upvars = get_freevars(ccx.tcx, id);
341341
let {llbox, box_ty, bcx} = build_closure(bcx, upvars, ck);
342-
trans_closure(sub_cx, sp, f, llfn, none, [], id, {|fcx|
342+
trans_closure(sub_cx, sp, f, llfn, no_self, [], id, {|fcx|
343343
load_environment(bcx, fcx, box_ty, upvars, ck);
344344
});
345345
llbox
@@ -351,7 +351,7 @@ fn trans_expr_fn(bcx: @block_ctxt, f: ast::_fn, sp: span,
351351
ast::proto_send. { trans_closure_env(ty::closure_send) }
352352
ast::proto_bare. {
353353
let closure = C_null(T_opaque_boxed_closure_ptr(ccx));
354-
trans_closure(sub_cx, sp, f, llfn, none, [], id, {|_fcx|});
354+
trans_closure(sub_cx, sp, f, llfn, no_self, [], id, {|_fcx|});
355355
closure
356356
}
357357
};

0 commit comments

Comments
 (0)