diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index f5bebd344cc7..8f15e10c3d0e 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -240,7 +240,7 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr]) } let f_may_close = alt f.node { - ast::expr_path(_) { def_is_local(cx.tcx.def_map.get(f.id), true) } + ast::expr_path(_) { def_is_local(cx.tcx.def_map.get(f.id)) } _ { true } }; if f_may_close { @@ -374,7 +374,7 @@ fn check_for(cx: ctx, local: @ast::local, seq: @ast::expr, blk: ast::blk, fn check_var(cx: ctx, ex: @ast::expr, p: @ast::path, id: ast::node_id, assign: bool, sc: scope) { let def = cx.tcx.def_map.get(id); - if !def_is_local(def, false) { ret; } + if !def_is_local(def) { ret; } let my_defnum = ast_util::def_id_of_def(def).node; let my_local_id = local_id_of_node(cx, my_defnum); 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, ret helper(cx.tcx, needle, haystack, mut); } -fn def_is_local(d: ast::def, objfields_count: bool) -> bool { - ret alt d { - ast::def_local(_, _) | ast::def_arg(_, _) | ast::def_binding(_) | - ast::def_upvar(_, _, _) | ast::def_self(_) { - true - } - ast::def_obj_field(_, _) { objfields_count } - _ { false } - }; +fn def_is_local(d: ast::def) -> bool { + alt d { + ast::def_local(_, _) | ast::def_arg(_, _) | ast::def_binding(_) | + ast::def_upvar(_, _, _) | ast::def_self(_) | + ast::def_obj_field(_, _) { true } + _ { false } + } } fn local_id_of_node(cx: ctx, id: node_id) -> uint { - alt cx.tcx.items.get(id) { - ast_map::node_arg(_, id) | ast_map::node_local(id) { id } + alt cx.tcx.items.find(id) { + some(ast_map::node_arg(_, id)) | some(ast_map::node_local(id)) { id } + _ { 0u } } } diff --git a/src/comp/middle/mut.rs b/src/comp/middle/mut.rs index 8d9526796781..d3856f4bd2d2 100644 --- a/src/comp/middle/mut.rs +++ b/src/comp/middle/mut.rs @@ -203,6 +203,9 @@ fn check_move_rhs(cx: @ctx, src: @expr) { def_obj_field(_, _) { mk_err(cx, src.span, msg_move_out, "object field"); } + def_self(_) { + mk_err(cx, src.span, msg_move_out, "method self"); + } _ { } } check_lval(cx, src, msg_move_out); diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 22d5945a792b..19d74e11cd8f 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -37,6 +37,7 @@ tag scope { scope_loop(@ast::local); // there's only 1 decl per loop. scope_block(ast::blk, @mutable uint, @mutable uint); scope_arm(ast::arm); + scope_self(ast::node_id); } type scopes = list; @@ -437,6 +438,9 @@ fn visit_expr_with_scope(x: @ast::expr, sc: scopes, v: vt) { v.visit_local(decl, new_sc, v); v.visit_block(blk, new_sc, v); } + ast::expr_anon_obj(_) { + visit::visit_expr(x, cons(scope_self(x.id), @sc), v); + } _ { visit::visit_expr(x, sc, v); } } } @@ -723,7 +727,10 @@ fn def_is_local(d: def) -> bool { } fn def_is_obj_field(d: def) -> bool { - ret alt d { ast::def_obj_field(_, _) { true } _ { false } }; + alt d { + ast::def_obj_field(_, _) | ast::def_self(_) { true } + _ { false } + } } 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) scope_item(it) { alt it.node { ast::item_obj(ob, ty_params, _) { - ret lookup_in_obj(name, ob, ty_params, ns); + ret lookup_in_obj(name, ob, ty_params, ns, it.id); } ast::item_impl(_, _, _) { if (name == "self" && ns == ns_value) { @@ -763,6 +770,11 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace) _ { } } } + scope_self(id) { + if (name == "self" && ns == ns_value) { + ret some(ast::def_self(local_def(id))); + } + } scope_native_item(it) { alt it.node { 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], } fn lookup_in_obj(name: ident, ob: ast::_obj, ty_params: [ast::ty_param], - ns: namespace) -> option::t { + ns: namespace, id: node_id) -> option::t { alt ns { ns_value. { + if name == "self" { ret some(ast::def_self(local_def(id))); } for f: ast::obj_field in ob.fields { if str::eq(f.ident, name) { 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 { // External lookups fn ns_for_def(d: def) -> namespace { - ret alt d { - ast::def_fn(_, _) { ns_value } - ast::def_obj_field(_, _) { ns_value } - ast::def_mod(_) { ns_module } - ast::def_native_mod(_) { ns_module } - ast::def_const(_) { ns_value } - ast::def_arg(_, _) { ns_value } - ast::def_local(_, _) { ns_value } - ast::def_upvar(_, _, _) { ns_value } - ast::def_variant(_, _) { ns_value } - ast::def_ty(_) { ns_type } - ast::def_binding(_) { ns_type } - ast::def_use(_) { ns_module } - ast::def_native_ty(_) { ns_type } - ast::def_native_fn(_, _) { ns_value } - ast::def_self(_) { ns_value } - }; + alt d { + ast::def_fn(_, _) | ast::def_obj_field(_, _) | ast::def_self(_) | + ast::def_const(_) | ast::def_arg(_, _) | ast::def_local(_, _) | + ast::def_upvar(_, _, _) | ast::def_variant(_, _) | + ast::def_native_fn(_, _) | ast::def_self(_) { ns_value } + + ast::def_mod(_) | ast::def_native_mod(_) { ns_module } + + ast::def_ty(_) | ast::def_binding(_) | ast::def_use(_) | + ast::def_native_ty(_) { ns_type } + } } fn lookup_external(e: env, cnum: int, ids: [ident], ns: namespace) -> diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 886a8da20485..2c724ba8fca7 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2678,7 +2678,9 @@ fn trans_local_var(cx: @block_ctxt, def: ast::def) -> local_var_result { ret { val: cx.fcx.llobjfields.get(did.node), kind: owned }; } ast::def_self(did) { - ret lval_owned(cx, cx.fcx.llenv); + let slf = option::get(cx.fcx.llself); + let ptr = PointerCast(cx, slf.v, T_ptr(type_of_or_i8(cx, slf.t))); + ret {val: ptr, kind: owned}; } _ { bcx_ccx(cx).sess.span_unimpl @@ -2832,21 +2834,29 @@ fn trans_index(cx: @block_ctxt, sp: span, base: @ast::expr, idx: @ast::expr, ret lval_owned(next_cx, elt); } +fn expr_is_lval(bcx: @block_ctxt, e: @ast::expr) -> bool { + let ccx = bcx_ccx(bcx); + ty::expr_is_lval(ccx.method_map, ccx.tcx, e) +} + // This is for impl methods, not obj methods. fn trans_method_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr, did: ast::def_id) -> lval_maybe_callee { - let bcx = trans_expr(bcx, base, ignore); // FIXME pass self - lval_static_fn(bcx, did, e.id) + let tz = [], tr = []; + let basety = ty::expr_ty(bcx_tcx(bcx), base); + let {bcx, val} = trans_arg_expr(bcx, {mode: ast::by_ref, ty: basety}, + type_of_or_i8(bcx, basety), tz, tr, base); + let val = PointerCast(bcx, val, T_opaque_boxed_closure_ptr(bcx_ccx(bcx))); + {env: obj_env(val) with lval_static_fn(bcx, did, e.id)} } fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee { alt e.node { ast::expr_path(p) { ret trans_path(bcx, p, e.id); } ast::expr_field(base, ident) { - let method_map = bcx_ccx(bcx).method_map; // Lval means this is a record field, so not a method - if !ty::expr_is_lval(method_map, bcx_tcx(bcx), e) { - alt method_map.find(e.id) { + if !expr_is_lval(bcx, e) { + alt bcx_ccx(bcx).method_map.find(e.id) { some(did) { // An impl method ret trans_method_callee(bcx, e, base, did); } @@ -2858,15 +2868,6 @@ fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee { } } } - ast::expr_self_method(ident) { - alt bcx.fcx.llself { - some(pair) { - let fld = trans_object_field_inner(bcx, pair.v, ident, pair.t); - ret {bcx: fld.bcx, val: fld.mthptr, kind: owned, - env: obj_env(fld.objptr), generic: none}; - } - } - } _ {} } let lv = trans_temp_lval(bcx, e); @@ -3475,7 +3476,7 @@ fn trans_expr_save_in(bcx: @block_ctxt, e: @ast::expr, dest: ValueRef) // use trans_temp_expr. fn trans_temp_lval(bcx: @block_ctxt, e: @ast::expr) -> lval_result { let bcx = bcx; - if ty::expr_is_lval(bcx_ccx(bcx).method_map, bcx_tcx(bcx), e) { + if expr_is_lval(bcx, e) { ret trans_lval(bcx, e); } else { let tcx = bcx_tcx(bcx); @@ -3513,7 +3514,7 @@ fn trans_temp_expr(bcx: @block_ctxt, e: @ast::expr) -> result { // - exprs with non-immediate type never get dest=by_val fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt { let tcx = bcx_tcx(bcx); - if ty::expr_is_lval(bcx_ccx(bcx).method_map, tcx, e) { + if expr_is_lval(bcx, e) { ret lval_to_dps(bcx, e, dest); } @@ -3555,7 +3556,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt { ret trans_closure::trans_bind(bcx, f, args, e.id, dest); } ast::expr_copy(a) { - if !ty::expr_is_lval(bcx_ccx(bcx).method_map, tcx, a) { + if !expr_is_lval(bcx, a) { ret trans_expr(bcx, a, dest); } else { ret lval_to_dps(bcx, a, dest); } @@ -3957,9 +3958,7 @@ fn init_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt { let bcx = bcx; alt local.node.init { some(init) { - if init.op == ast::init_assign || - !ty::expr_is_lval(bcx_ccx(bcx).method_map, bcx_tcx(bcx), - init.expr) { + if init.op == ast::init_assign || !expr_is_lval(bcx, init.expr) { bcx = trans_expr_save_in(bcx, init.expr, llptr); } else { // This is a move from an lval, must perform an actual move let sub = trans_lval(bcx, init.expr); @@ -4347,15 +4346,15 @@ fn new_fn_ctxt(cx: @local_ctxt, sp: span, llfndecl: ValueRef) -> @fn_ctxt { // spaces that have been created for them (by code in the llallocas field of // the function's fn_ctxt). create_llargs_for_fn_args populates the llargs // field of the fn_ctxt with -fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: option::t, +fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: self_arg, args: [ast::arg], ty_params: [ast::ty_param]) { // Skip the implicit arguments 0, and 1. TODO: Pull out 2u and define // it as a constant, since we're using it in several places in trans this // way. let arg_n = 2u; alt ty_self { - some(tt) { cx.llself = some::({v: cx.llenv, t: tt}); } - none. { + obj_self(tt) | impl_self(tt) { cx.llself = some({v: cx.llenv, t: tt}); } + no_self. { let i = 0u; for tp: ast::ty_param in ty_params { let llarg = llvm::LLVMGetParam(cx.llfn, arg_n); @@ -4473,19 +4472,23 @@ fn finish_fn(fcx: @fn_ctxt, lltop: BasicBlockRef) { RetVoid(ret_cx); } +tag self_arg { obj_self(ty::t); impl_self(ty::t); no_self; } + // trans_closure: Builds an LLVM function out of a source function. // If the function closes over its environment a closure will be // returned. fn trans_closure(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef, - ty_self: option::t, ty_params: [ast::ty_param], + ty_self: self_arg, ty_params: [ast::ty_param], id: ast::node_id, maybe_load_env: block(@fn_ctxt)) { set_uwtable(llfndecl); // Set up arguments to the function. let fcx = new_fn_ctxt_w_id(cx, sp, llfndecl, id, f.decl.cf); create_llargs_for_fn_args(fcx, ty_self, f.decl.inputs, ty_params); - alt fcx.llself { - some(llself) { populate_fn_ctxt_from_llself(fcx, llself); } + alt ty_self { + obj_self(_) { + populate_fn_ctxt_from_llself(fcx, option::get(fcx.llself)); + } _ { } } @@ -4526,7 +4529,7 @@ fn trans_closure(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef, // trans_fn: creates an LLVM function corresponding to a source language // function. fn trans_fn(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef, - ty_self: option::t, ty_params: [ast::ty_param], + ty_self: self_arg, ty_params: [ast::ty_param], id: ast::node_id) { let do_time = cx.ccx.sess.get_opts().stats; 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, } let fcx = new_fn_ctxt(cx, sp, llctor_decl); let ret_t = ty::ret_ty_of_fn(cx.ccx.tcx, ctor_id); - create_llargs_for_fn_args(fcx, none, dtor.decl.inputs, ty_params); + create_llargs_for_fn_args(fcx, no_self, dtor.decl.inputs, ty_params); let bcx = new_top_block_ctxt(fcx); let lltop = bcx.llbb; 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, } } let fcx = new_fn_ctxt(cx, variant.span, llfndecl); - create_llargs_for_fn_args(fcx, none, fn_args, ty_params); + create_llargs_for_fn_args(fcx, no_self, fn_args, ty_params); let ty_param_substs: [ty::t] = []; i = 0u; for tp: ast::ty_param in ty_params { @@ -4655,13 +4658,15 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id, finish_fn(fcx, lltop); } -fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method]) { +fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method], + id: ast::node_id) { let sub_cx = extend_path(cx, name); for m in methods { alt cx.ccx.item_ids.find(m.node.id) { - some(llfndecl) { + some(llfn) { trans_fn(extend_path(sub_cx, m.node.ident), m.span, m.node.meth, - llfndecl, none, [], m.node.id); + llfn, impl_self(ty::node_id_to_monotype(cx.ccx.tcx, id)), + [], m.node.id); } } } @@ -4961,7 +4966,7 @@ fn trans_item(cx: @local_ctxt, item: ast::item) { let sub_cx = extend_path(cx, item.ident); alt cx.ccx.item_ids.find(item.id) { some(llfndecl) { - trans_fn(sub_cx, item.span, f, llfndecl, none, tps, item.id); + trans_fn(sub_cx, item.span, f, llfndecl, no_self, tps, item.id); } _ { cx.ccx.sess.span_fatal(item.span, @@ -4975,14 +4980,14 @@ fn trans_item(cx: @local_ctxt, item: ast::item) { with *extend_path(cx, item.ident)}; trans_obj(sub_cx, item.span, ob, ctor_id, tps); } - ast::item_impl(_, _, ms) { trans_impl(cx, item.ident, ms); } + ast::item_impl(_, _, ms) { trans_impl(cx, item.ident, ms, item.id); } ast::item_res(dtor, dtor_id, tps, ctor_id) { trans_res_ctor(cx, item.span, dtor, ctor_id, tps); // Create a function for the destructor alt cx.ccx.item_ids.find(item.id) { some(lldtor_decl) { - trans_fn(cx, item.span, dtor, lldtor_decl, none, tps, dtor_id); + trans_fn(cx, item.span, dtor, lldtor_decl, no_self, tps, dtor_id); } _ { cx.ccx.sess.span_fatal(item.span, "unbound dtor in trans_item"); diff --git a/src/comp/middle/trans_closure.rs b/src/comp/middle/trans_closure.rs index 039709db8d67..d3a905d70df2 100644 --- a/src/comp/middle/trans_closure.rs +++ b/src/comp/middle/trans_closure.rs @@ -339,7 +339,7 @@ fn trans_expr_fn(bcx: @block_ctxt, f: ast::_fn, sp: span, let trans_closure_env = lambda(ck: ty::closure_kind) -> ValueRef { let upvars = get_freevars(ccx.tcx, id); let {llbox, box_ty, bcx} = build_closure(bcx, upvars, ck); - trans_closure(sub_cx, sp, f, llfn, none, [], id, {|fcx| + trans_closure(sub_cx, sp, f, llfn, no_self, [], id, {|fcx| load_environment(bcx, fcx, box_ty, upvars, ck); }); llbox @@ -351,7 +351,7 @@ fn trans_expr_fn(bcx: @block_ctxt, f: ast::_fn, sp: span, ast::proto_send. { trans_closure_env(ty::closure_send) } ast::proto_bare. { let closure = C_null(T_opaque_boxed_closure_ptr(ccx)); - trans_closure(sub_cx, sp, f, llfn, none, [], id, {|_fcx|}); + trans_closure(sub_cx, sp, f, llfn, no_self, [], id, {|_fcx|}); closure } }; diff --git a/src/comp/middle/trans_objects.rs b/src/comp/middle/trans_objects.rs index 4b8795deea8f..d6ede4eba313 100644 --- a/src/comp/middle/trans_objects.rs +++ b/src/comp/middle/trans_objects.rs @@ -52,7 +52,7 @@ fn trans_obj(cx: @local_ctxt, sp: span, ob: ast::_obj, ctor_id: ast::node_id, let lltop = bcx.llbb; // Both regular arguments and type parameters are handled here. - create_llargs_for_fn_args(fcx, none::, fn_args, ty_params); + create_llargs_for_fn_args(fcx, no_self, fn_args, ty_params); let arg_tys: [ty::arg] = arg_tys_of_fn(ccx, ctor_id); bcx = copy_args_to_allocas(fcx, bcx, fn_args, arg_tys); @@ -893,7 +893,7 @@ fn process_normal_mthd(cx: @local_ctxt, m: @ast::method, self_ty: ty::t, // method's definition will be in the executable. ccx.item_ids.insert(m.node.id, llfn); ccx.item_symbols.insert(m.node.id, s); - trans_fn(mcx, m.span, m.node.meth, llfn, some(self_ty), ty_params, + trans_fn(mcx, m.span, m.node.meth, llfn, obj_self(self_ty), ty_params, m.node.id); ret llfn; diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index f622acb70400..384353c2800b 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -335,7 +335,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) { clear_pp(rslt); handle_var(fcx, rslt, e.id, path_to_ident(fcx.ccx.tcx, p)); } - expr_self_method(v) { clear_pp(expr_pp(fcx.ccx, e)); } expr_log(_, arg) { find_pre_post_expr(fcx, arg); copy_pre_post(fcx.ccx, e.id, arg); diff --git a/src/comp/middle/tstate/states.rs b/src/comp/middle/tstate/states.rs index 414668f3c404..db020ec1bb07 100644 --- a/src/comp/middle/tstate/states.rs +++ b/src/comp/middle/tstate/states.rs @@ -592,7 +592,6 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool { } expr_break. { ret pure_exp(fcx.ccx, e.id, pres); } expr_cont. { ret pure_exp(fcx.ccx, e.id, pres); } - expr_self_method(_) { ret pure_exp(fcx.ccx, e.id, pres); } expr_anon_obj(anon_obj) { alt anon_obj.inner_obj { some(wt) { ret find_pre_post_state_sub(fcx, pres, wt, e.id, none); } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 4265044c2960..8c413376f146 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -90,6 +90,7 @@ export mk_uint; export mk_uniq; export mk_var; export mk_opaque_closure; +export gen_ty; export mode; export mt; export node_type_table; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 03b7f40470d1..d697421bde46 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -8,7 +8,7 @@ import util::common::*; import syntax::codemap::span; import middle::ty; import middle::ty::{node_id_to_type, arg, bind_params_in_type, block_ty, - expr_ty, field, node_type_table, + expr_ty, field, node_type_table, mk_nil, ty_param_substs_opt_and_ty, ty_param_kinds_and_ty}; import util::ppaux::ty_to_str; import middle::ty::unify::{ures_ok, ures_err, fix_ok, fix_err}; @@ -25,17 +25,12 @@ type method_map = hashmap; type ty_table = hashmap; // Used for typechecking the methods of an object. -tag obj_info { - - // Regular objects have a node_id at compile time. - regular_obj([ast::obj_field], ast::node_id); - - // Anonymous objects only have a type at compile time. It's optional - // because not all anonymous objects have a inner_obj to attach to. - anon_obj([ast::obj_field], option::t); +tag self_info { + self_obj([ast::obj_field], ty::t); + self_impl(ty::t); } -type crate_ctxt = {mutable obj_infos: [obj_info], +type crate_ctxt = {mutable self_infos: [self_info], impl_map: resolve::impl_map, method_map: method_map, tcx: ty::ctxt}; @@ -93,7 +88,13 @@ fn ty_param_kinds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) -> let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node)); ret {kinds: [], ty: typ}; } - ast::def_self(id) { fail "FIXME[impl]"; } + ast::def_self(id) { + alt get_self_info(fcx.ccx) { + some(self_obj(_, obj_t)) | some(self_impl(obj_t)) { + ret {kinds: [], ty: obj_t}; + } + } + } ast::def_fn(id, _) { ret ty::lookup_item_type(fcx.ccx.tcx, id); } ast::def_native_fn(id, _) { ret ty::lookup_item_type(fcx.ccx.tcx, id); } ast::def_const(id) { ret ty::lookup_item_type(fcx.ccx.tcx, id); } @@ -696,7 +697,7 @@ mod collect { write::ty_only(cx.tcx, it.id, tpt.ty); get_tag_variant_types(cx, local_def(it.id), variants, ty_params); } - ast::item_impl(_, _, ms) { + ast::item_impl(_, selfty, ms) { for m in ms { let ty = ty::method_ty_to_fn_ty( cx.tcx, ty_of_method(cx.tcx, m_collect, m)); @@ -704,6 +705,8 @@ mod collect { {kinds: [], ty: ty}); write::ty_only(cx.tcx, m.node.id, ty); } + write::ty_only(cx.tcx, it.id, ast_ty_to_ty(cx.tcx, m_collect, + selfty)); } ast::item_obj(object, ty_params, ctor_id) { // Now we need to call ty_of_obj_ctor(); this is the type that @@ -1115,19 +1118,13 @@ fn gather_locals(ccx: @crate_ctxt, f: ast::_fn, id: ast::node_id, }; // Add object fields, if any. - let obj_fields = []; - alt get_obj_info(ccx) { - some(oinfo) { - alt oinfo { - regular_obj(ofs, _) { obj_fields = ofs; } - anon_obj(ofs, _) { obj_fields = ofs; } + alt get_self_info(ccx) { + some(self_obj(ofs, _)) { + for f in ofs { + assign(f.id, some(ty::node_id_to_type(ccx.tcx, f.id))); } } - none. {/* no fields */ } - } - for f: ast::obj_field in obj_fields { - let field_ty = ty::node_id_to_type(ccx.tcx, f.id); - assign(f.id, some(field_ty)); + _ {} } // Add formal parameters. @@ -1992,60 +1989,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, ast::expr_call(f, args, _) { bot = check_call_full(fcx, expr.span, f, args, expr.id); } - ast::expr_self_method(ident) { - let t = ty::mk_nil(tcx); - let this_obj_sty: option::t = - some(structure_of(fcx, expr.span, ty::mk_nil(tcx))); - let this_obj_info: option::t = get_obj_info(fcx.ccx); - alt this_obj_info { - some(oinfo) { - alt oinfo { - regular_obj(_, obj_id) { - let did = local_def(obj_id); - - // Try looking up the current object in the type - // cache. - alt tcx.tcache.find(did) { - some(tpt) { - // If we're typechecking a self-method on - // a regular object, this lookup should - // succeed. - this_obj_sty = some(structure_of(fcx, expr.span, tpt.ty)); - } - none. { - tcx.sess.bug("didn't find " + int::str(did.node) + - " in type cache"); - } - } - } - anon_obj(_, obj_sty) { this_obj_sty = obj_sty; } - } - } - none. { - // Shouldn't happen. - tcx.sess.span_err(expr.span, "self-call in non-object context"); - } - } - - // Grab this method's type out of the current object type. - alt this_obj_sty { - some(sty) { - alt sty { - ty::ty_obj(methods) { - for method: ty::method in methods { - if method.ident == ident { - t = ty::method_ty_to_fn_ty(tcx, method); - } - } - } - _ { fail; } - } - } - none. { } - } - write::ty_only_fixup(fcx, id, t); - require_impure(tcx.sess, fcx.purity, expr.span); - } ast::expr_cast(e, t) { bot = check_expr(fcx, e); let t_1 = ast_ty_to_ty_crate(fcx.ccx, t); @@ -2172,15 +2115,16 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, } result } + bot |= check_expr(fcx, base); let base_t = expr_ty(tcx, base); let iscope = fcx.ccx.impl_map.get(expr.id); alt lookup_method(fcx, iscope, field, base_t) { some(method) { let mt = ty_of_method(fcx.ccx.tcx, m_check, method); - let f_ty = ty::mk_fn(fcx.ccx.tcx, mt.proto, mt.inputs, - mt.output, mt.cf, mt.constrs); - write::ty_only_fixup(fcx, id, f_ty); + let fty = ty::mk_fn(fcx.ccx.tcx, mt.proto, mt.inputs, + mt.output, mt.cf, mt.constrs); + write::ty_only_fixup(fcx, id, fty); fcx.ccx.method_map.insert(id, local_def(method.node.id)); } _ { @@ -2255,15 +2199,15 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, // Typecheck 'inner_obj'. If it exists, it had better have object // type. let inner_obj_methods: [ty::method] = []; - let inner_obj_ty: ty::t = ty::mk_nil(tcx); let inner_obj_sty: option::t = none; alt ao.inner_obj { none. { } some(e) { - // If there's a inner_obj, we push it onto the obj_infos stack - // so that self-calls can be checked within its context later. + // If there's a inner_obj, we push it onto the self_infos + // stack so that self-calls can be checked within its context + // later. bot |= check_expr(fcx, e); - inner_obj_ty = expr_ty(tcx, e); + let inner_obj_ty = expr_ty(tcx, e); inner_obj_sty = some(structure_of(fcx, e.span, inner_obj_ty)); alt inner_obj_sty { @@ -2283,10 +2227,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, } } - fcx.ccx.obj_infos += - [anon_obj(vec::map(ast_util::obj_field_from_anon_obj_field, - fields), inner_obj_sty)]; - // Whenever an outer method overrides an inner, we need to remove // that inner from the type. Filter inner_obj_methods to remove // any methods that share a name with an outer method. @@ -2311,9 +2251,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, } let f = bind filtering_fn(fcx.ccx, _, ao.methods); - inner_obj_methods = - vec::filter_map::(f, inner_obj_methods); + inner_obj_methods = vec::filter_map(f, inner_obj_methods); method_types += inner_obj_methods; } @@ -2325,19 +2263,22 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, // Write the methods into the node type table. (This happens in // collect::convert for regular objects.) let i = 0u; - while i < vec::len::<@ast::method>(ao.methods) { + while i < vec::len(ao.methods) { write::ty_only(tcx, ao.methods[i].node.id, ty::method_ty_to_fn_ty(tcx, method_types[i])); i += 1u; } + fcx.ccx.self_infos += + [self_obj(vec::map(ast_util::obj_field_from_anon_obj_field, + fields), ot)]; // Typecheck the methods. for method: @ast::method in ao.methods { check_method(fcx.ccx, method); } // Now remove the info from the stack. - vec::pop::(fcx.ccx.obj_infos); + vec::pop(fcx.ccx.self_infos); } _ { tcx.sess.unimpl("expr type in typeck::check_expr"); } } @@ -2357,8 +2298,8 @@ fn next_ty_var(fcx: @fn_ctxt) -> ty::t { ret ty::mk_var(fcx.ccx.tcx, next_ty_var_id(fcx)); } -fn get_obj_info(ccx: @crate_ctxt) -> option::t { - ret vec::last::(ccx.obj_infos); +fn get_self_info(ccx: @crate_ctxt) -> option::t { + ret vec::last(ccx.self_infos); } fn check_decl_initializer(fcx: @fn_ctxt, nid: ast::node_id, @@ -2639,13 +2580,18 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) { ast::item_res(f, dtor_id, _, _) { check_fn(ccx, f, dtor_id, none); } ast::item_obj(ob, _, _) { // We're entering an object, so gather up the info we need. - ccx.obj_infos += [regular_obj(ob.fields, it.id)]; + ccx.self_infos += [self_obj(ob.fields, + ccx.tcx.tcache.get(local_def(it.id)).ty)]; // Typecheck the methods. for method: @ast::method in ob.methods { check_method(ccx, method); } // Now remove the info from the stack. - vec::pop::(ccx.obj_infos); + vec::pop(ccx.self_infos); + } + ast::item_impl(_, ty, ms) { + ccx.self_infos += [self_impl(ast_ty_to_ty(ccx.tcx, m_check, ty))]; + for m in ms { check_method(ccx, m); } + vec::pop(ccx.self_infos); } - ast::item_impl(_, _, ms) { for m in ms { check_method(ccx, m); } } _ {/* nothing to do */ } } } @@ -2701,9 +2647,7 @@ fn check_crate(tcx: ty::ctxt, impl_map: resolve::impl_map, crate: @ast::crate) -> method_map { collect::collect_item_types(tcx, crate); - let obj_infos: [obj_info] = []; - - let ccx = @{mutable obj_infos: obj_infos, + let ccx = @{mutable self_infos: [], impl_map: impl_map, method_map: std::map::new_int_hash(), tcx: tcx}; diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 0672e9de5c7e..8fb6d41c0a8a 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -28,13 +28,13 @@ type ty_param = {ident: ident, kind: kind}; tag def { def_fn(def_id, purity); def_obj_field(def_id, mutability); + def_self(def_id); def_mod(def_id); def_native_mod(def_id); def_const(def_id); def_arg(def_id, mode); def_local(def_id, let_style); def_variant(def_id /* tag */, def_id /* variant */); - def_self(def_id); def_ty(def_id); def_ty_param(uint, kind); def_binding(def_id); @@ -214,7 +214,6 @@ tag expr_ { expr_rec([field], option::t<@expr>); expr_call(@expr, [@expr], bool); expr_tup([@expr]); - expr_self_method(ident); expr_bind(@expr, [option::t<@expr>]); expr_binary(binop, @expr, @expr); expr_unary(unop, @expr); diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index 05a4893ccd00..6bb95f0cfc04 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -353,7 +353,6 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ { expr_call(fld.fold_expr(f), fld.map_exprs(fld.fold_expr, args), blk) } - expr_self_method(id) { expr_self_method(fld.fold_ident(id)) } expr_bind(f, args) { let opt_map_se = bind option::map(fld.fold_expr, _); expr_bind(fld.fold_expr(f), vec::map(opt_map_se, args)) diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index d1e11bf8700b..94a7c3e01b29 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -155,8 +155,7 @@ fn bad_expr_word_table() -> hashmap { "cont", "ret", "be", "fail", "type", "resource", "check", "assert", "claim", "native", "fn", "lambda", "pure", "unsafe", "block", "import", "export", "let", "const", - "log", "log_err", "tag", "obj", "self", "copy", "sendfn", - "impl"] { + "log", "log_err", "tag", "obj", "copy", "sendfn", "impl"] { words.insert(word, ()); } words @@ -942,15 +941,6 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { let e = parse_expr(p); ex = ast::expr_copy(e); hi = e.span.hi; - } else if is_word(p, "self") && p.look_ahead(1u) == token::DOT { - p.bump(); p.bump(); - // The rest is a call expression. - let f: @ast::expr = parse_self_method(p); - let es = - parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA), - parse_expr, p); - hi = es.span.hi; - ex = ast::expr_call(f, es.node, false); } else if p.peek() == token::MOD_SEP || is_ident(p.peek()) && !is_word(p, "true") && !is_word(p, "false") { @@ -998,12 +988,6 @@ fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr { ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, e, none)); } -fn parse_self_method(p: parser) -> @ast::expr { - let sp = p.get_span(); - let f_name: ast::ident = parse_ident(p); - ret mk_expr(p, sp.lo, sp.hi, ast::expr_self_method(f_name)); -} - fn parse_dot_or_call_expr(p: parser) -> @ast::expr { let b = parse_bottom_expr(p); if expr_has_value(b) { parse_dot_or_call_expr_with(p, b) } diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index 57720d8dc14d..25ba7e082f3d 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -736,10 +736,6 @@ fn print_expr(s: ps, &&expr: @ast::expr) { print_expr(s, option::get(blk)); } } - ast::expr_self_method(ident) { - word(s.s, "self."); - print_ident(s, ident); - } ast::expr_bind(func, args) { fn print_opt(s: ps, expr: option::t<@ast::expr>) { alt expr { diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index 35f81fe187ac..c3e8c65b15a1 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -251,7 +251,6 @@ fn visit_expr(ex: @expr, e: E, v: vt) { visit_exprs(args, e, v); v.visit_expr(callee, e, v); } - expr_self_method(_) { } expr_bind(callee, args) { v.visit_expr(callee, e, v); for eo: option::t<@expr> in args { visit_expr_opt(eo, e, v); } diff --git a/src/test/compile-fail/self-call-non-obj.rs b/src/test/compile-fail/self-call-non-obj.rs index 6261fda60ac1..8de59268482c 100644 --- a/src/test/compile-fail/self-call-non-obj.rs +++ b/src/test/compile-fail/self-call-non-obj.rs @@ -1,4 +1,4 @@ -// error-pattern:self-call in non-object context +// error-pattern:unresolved name: self // Fix for issue #707. fn main() { diff --git a/src/test/compile-fail/self-missing-method.rs b/src/test/compile-fail/self-missing-method.rs index af69d2ac1a4c..b9c7086f6e7b 100644 --- a/src/test/compile-fail/self-missing-method.rs +++ b/src/test/compile-fail/self-missing-method.rs @@ -1,4 +1,4 @@ -// error-pattern:expecting ., found ( +// error-pattern:attempted field access on type fn fn main() { obj foo() {