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
This commit is contained in:
parent
1dd2f1ec03
commit
7efef98901
17 changed files with 137 additions and 203 deletions
|
@ -240,7 +240,7 @@ fn check_call(cx: ctx, sc: scope, f: @ast::expr, args: [@ast::expr])
|
||||||
}
|
}
|
||||||
let f_may_close =
|
let f_may_close =
|
||||||
alt f.node {
|
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 }
|
_ { true }
|
||||||
};
|
};
|
||||||
if f_may_close {
|
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,
|
fn check_var(cx: ctx, ex: @ast::expr, p: @ast::path, id: ast::node_id,
|
||||||
assign: bool, sc: scope) {
|
assign: bool, sc: scope) {
|
||||||
let def = cx.tcx.def_map.get(id);
|
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_defnum = ast_util::def_id_of_def(def).node;
|
||||||
let my_local_id = local_id_of_node(cx, my_defnum);
|
let my_local_id = local_id_of_node(cx, my_defnum);
|
||||||
let var_t = ty::expr_ty(cx.tcx, ex);
|
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);
|
ret helper(cx.tcx, needle, haystack, mut);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn def_is_local(d: ast::def, objfields_count: bool) -> bool {
|
fn def_is_local(d: ast::def) -> bool {
|
||||||
ret alt d {
|
alt d {
|
||||||
ast::def_local(_, _) | ast::def_arg(_, _) | ast::def_binding(_) |
|
ast::def_local(_, _) | ast::def_arg(_, _) | ast::def_binding(_) |
|
||||||
ast::def_upvar(_, _, _) | ast::def_self(_) {
|
ast::def_upvar(_, _, _) | ast::def_self(_) |
|
||||||
true
|
ast::def_obj_field(_, _) { true }
|
||||||
}
|
_ { false }
|
||||||
ast::def_obj_field(_, _) { objfields_count }
|
}
|
||||||
_ { false }
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn local_id_of_node(cx: ctx, id: node_id) -> uint {
|
fn local_id_of_node(cx: ctx, id: node_id) -> uint {
|
||||||
alt cx.tcx.items.get(id) {
|
alt cx.tcx.items.find(id) {
|
||||||
ast_map::node_arg(_, id) | ast_map::node_local(id) { id }
|
some(ast_map::node_arg(_, id)) | some(ast_map::node_local(id)) { id }
|
||||||
|
_ { 0u }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -203,6 +203,9 @@ fn check_move_rhs(cx: @ctx, src: @expr) {
|
||||||
def_obj_field(_, _) {
|
def_obj_field(_, _) {
|
||||||
mk_err(cx, src.span, msg_move_out, "object 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);
|
check_lval(cx, src, msg_move_out);
|
||||||
|
|
|
@ -37,6 +37,7 @@ tag scope {
|
||||||
scope_loop(@ast::local); // there's only 1 decl per loop.
|
scope_loop(@ast::local); // there's only 1 decl per loop.
|
||||||
scope_block(ast::blk, @mutable uint, @mutable uint);
|
scope_block(ast::blk, @mutable uint, @mutable uint);
|
||||||
scope_arm(ast::arm);
|
scope_arm(ast::arm);
|
||||||
|
scope_self(ast::node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
type scopes = list<scope>;
|
type scopes = list<scope>;
|
||||||
|
@ -437,6 +438,9 @@ fn visit_expr_with_scope(x: @ast::expr, sc: scopes, v: vt<scopes>) {
|
||||||
v.visit_local(decl, new_sc, v);
|
v.visit_local(decl, new_sc, v);
|
||||||
v.visit_block(blk, 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); }
|
_ { 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 {
|
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 {
|
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) {
|
scope_item(it) {
|
||||||
alt it.node {
|
alt it.node {
|
||||||
ast::item_obj(ob, ty_params, _) {
|
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(_, _, _) {
|
ast::item_impl(_, _, _) {
|
||||||
if (name == "self" && ns == ns_value) {
|
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) {
|
scope_native_item(it) {
|
||||||
alt it.node {
|
alt it.node {
|
||||||
ast::native_item_fn(decl, ty_params) {
|
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],
|
fn lookup_in_obj(name: ident, ob: ast::_obj, ty_params: [ast::ty_param],
|
||||||
ns: namespace) -> option::t<def> {
|
ns: namespace, id: node_id) -> option::t<def> {
|
||||||
alt ns {
|
alt ns {
|
||||||
ns_value. {
|
ns_value. {
|
||||||
|
if name == "self" { ret some(ast::def_self(local_def(id))); }
|
||||||
for f: ast::obj_field in ob.fields {
|
for f: ast::obj_field in ob.fields {
|
||||||
if str::eq(f.ident, name) {
|
if str::eq(f.ident, name) {
|
||||||
ret some(ast::def_obj_field(local_def(f.id), f.mut));
|
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
|
// External lookups
|
||||||
fn ns_for_def(d: def) -> namespace {
|
fn ns_for_def(d: def) -> namespace {
|
||||||
ret alt d {
|
alt d {
|
||||||
ast::def_fn(_, _) { ns_value }
|
ast::def_fn(_, _) | ast::def_obj_field(_, _) | ast::def_self(_) |
|
||||||
ast::def_obj_field(_, _) { ns_value }
|
ast::def_const(_) | ast::def_arg(_, _) | ast::def_local(_, _) |
|
||||||
ast::def_mod(_) { ns_module }
|
ast::def_upvar(_, _, _) | ast::def_variant(_, _) |
|
||||||
ast::def_native_mod(_) { ns_module }
|
ast::def_native_fn(_, _) | ast::def_self(_) { ns_value }
|
||||||
ast::def_const(_) { ns_value }
|
|
||||||
ast::def_arg(_, _) { ns_value }
|
ast::def_mod(_) | ast::def_native_mod(_) { ns_module }
|
||||||
ast::def_local(_, _) { ns_value }
|
|
||||||
ast::def_upvar(_, _, _) { ns_value }
|
ast::def_ty(_) | ast::def_binding(_) | ast::def_use(_) |
|
||||||
ast::def_variant(_, _) { ns_value }
|
ast::def_native_ty(_) { ns_type }
|
||||||
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 }
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_external(e: env, cnum: int, ids: [ident], ns: namespace) ->
|
fn lookup_external(e: env, cnum: int, ids: [ident], ns: namespace) ->
|
||||||
|
|
|
@ -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 };
|
ret { val: cx.fcx.llobjfields.get(did.node), kind: owned };
|
||||||
}
|
}
|
||||||
ast::def_self(did) {
|
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
|
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);
|
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.
|
// This is for impl methods, not obj methods.
|
||||||
fn trans_method_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
|
fn trans_method_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
|
||||||
did: ast::def_id) -> lval_maybe_callee {
|
did: ast::def_id) -> lval_maybe_callee {
|
||||||
let bcx = trans_expr(bcx, base, ignore); // FIXME pass self
|
let tz = [], tr = [];
|
||||||
lval_static_fn(bcx, did, e.id)
|
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 {
|
fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
|
||||||
alt e.node {
|
alt e.node {
|
||||||
ast::expr_path(p) { ret trans_path(bcx, p, e.id); }
|
ast::expr_path(p) { ret trans_path(bcx, p, e.id); }
|
||||||
ast::expr_field(base, ident) {
|
ast::expr_field(base, ident) {
|
||||||
let method_map = bcx_ccx(bcx).method_map;
|
|
||||||
// Lval means this is a record field, so not a method
|
// Lval means this is a record field, so not a method
|
||||||
if !ty::expr_is_lval(method_map, bcx_tcx(bcx), e) {
|
if !expr_is_lval(bcx, e) {
|
||||||
alt method_map.find(e.id) {
|
alt bcx_ccx(bcx).method_map.find(e.id) {
|
||||||
some(did) { // An impl method
|
some(did) { // An impl method
|
||||||
ret trans_method_callee(bcx, e, base, did);
|
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);
|
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.
|
// use trans_temp_expr.
|
||||||
fn trans_temp_lval(bcx: @block_ctxt, e: @ast::expr) -> lval_result {
|
fn trans_temp_lval(bcx: @block_ctxt, e: @ast::expr) -> lval_result {
|
||||||
let bcx = bcx;
|
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);
|
ret trans_lval(bcx, e);
|
||||||
} else {
|
} else {
|
||||||
let tcx = bcx_tcx(bcx);
|
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
|
// - exprs with non-immediate type never get dest=by_val
|
||||||
fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
||||||
let tcx = bcx_tcx(bcx);
|
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);
|
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);
|
ret trans_closure::trans_bind(bcx, f, args, e.id, dest);
|
||||||
}
|
}
|
||||||
ast::expr_copy(a) {
|
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);
|
ret trans_expr(bcx, a, dest);
|
||||||
}
|
}
|
||||||
else { ret lval_to_dps(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;
|
let bcx = bcx;
|
||||||
alt local.node.init {
|
alt local.node.init {
|
||||||
some(init) {
|
some(init) {
|
||||||
if init.op == ast::init_assign ||
|
if init.op == ast::init_assign || !expr_is_lval(bcx, init.expr) {
|
||||||
!ty::expr_is_lval(bcx_ccx(bcx).method_map, bcx_tcx(bcx),
|
|
||||||
init.expr) {
|
|
||||||
bcx = trans_expr_save_in(bcx, init.expr, llptr);
|
bcx = trans_expr_save_in(bcx, init.expr, llptr);
|
||||||
} else { // This is a move from an lval, must perform an actual move
|
} else { // This is a move from an lval, must perform an actual move
|
||||||
let sub = trans_lval(bcx, init.expr);
|
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
|
// 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
|
// the function's fn_ctxt). create_llargs_for_fn_args populates the llargs
|
||||||
// field of the fn_ctxt with
|
// field of the fn_ctxt with
|
||||||
fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: option::t<ty::t>,
|
fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: self_arg,
|
||||||
args: [ast::arg], ty_params: [ast::ty_param]) {
|
args: [ast::arg], ty_params: [ast::ty_param]) {
|
||||||
// Skip the implicit arguments 0, and 1. TODO: Pull out 2u and define
|
// 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
|
// it as a constant, since we're using it in several places in trans this
|
||||||
// way.
|
// way.
|
||||||
let arg_n = 2u;
|
let arg_n = 2u;
|
||||||
alt ty_self {
|
alt ty_self {
|
||||||
some(tt) { cx.llself = some::<val_self_pair>({v: cx.llenv, t: tt}); }
|
obj_self(tt) | impl_self(tt) { cx.llself = some({v: cx.llenv, t: tt}); }
|
||||||
none. {
|
no_self. {
|
||||||
let i = 0u;
|
let i = 0u;
|
||||||
for tp: ast::ty_param in ty_params {
|
for tp: ast::ty_param in ty_params {
|
||||||
let llarg = llvm::LLVMGetParam(cx.llfn, arg_n);
|
let llarg = llvm::LLVMGetParam(cx.llfn, arg_n);
|
||||||
|
@ -4473,19 +4472,23 @@ fn finish_fn(fcx: @fn_ctxt, lltop: BasicBlockRef) {
|
||||||
RetVoid(ret_cx);
|
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.
|
// trans_closure: Builds an LLVM function out of a source function.
|
||||||
// If the function closes over its environment a closure will be
|
// If the function closes over its environment a closure will be
|
||||||
// returned.
|
// returned.
|
||||||
fn trans_closure(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef,
|
fn trans_closure(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef,
|
||||||
ty_self: option::t<ty::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)) {
|
id: ast::node_id, maybe_load_env: block(@fn_ctxt)) {
|
||||||
set_uwtable(llfndecl);
|
set_uwtable(llfndecl);
|
||||||
|
|
||||||
// Set up arguments to the function.
|
// Set up arguments to the function.
|
||||||
let fcx = new_fn_ctxt_w_id(cx, sp, llfndecl, id, f.decl.cf);
|
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);
|
create_llargs_for_fn_args(fcx, ty_self, f.decl.inputs, ty_params);
|
||||||
alt fcx.llself {
|
alt ty_self {
|
||||||
some(llself) { populate_fn_ctxt_from_llself(fcx, llself); }
|
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
|
// trans_fn: creates an LLVM function corresponding to a source language
|
||||||
// function.
|
// function.
|
||||||
fn trans_fn(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef,
|
fn trans_fn(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef,
|
||||||
ty_self: option::t<ty::t>, ty_params: [ast::ty_param],
|
ty_self: self_arg, ty_params: [ast::ty_param],
|
||||||
id: ast::node_id) {
|
id: ast::node_id) {
|
||||||
let do_time = cx.ccx.sess.get_opts().stats;
|
let do_time = cx.ccx.sess.get_opts().stats;
|
||||||
let start = do_time ? time::get_time() : {sec: 0u32, usec: 0u32};
|
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 fcx = new_fn_ctxt(cx, sp, llctor_decl);
|
||||||
let ret_t = ty::ret_ty_of_fn(cx.ccx.tcx, ctor_id);
|
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 bcx = new_top_block_ctxt(fcx);
|
||||||
let lltop = bcx.llbb;
|
let lltop = bcx.llbb;
|
||||||
let arg_t = arg_tys_of_fn(ccx, ctor_id)[0].ty;
|
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);
|
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] = [];
|
let ty_param_substs: [ty::t] = [];
|
||||||
i = 0u;
|
i = 0u;
|
||||||
for tp: ast::ty_param in ty_params {
|
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);
|
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);
|
let sub_cx = extend_path(cx, name);
|
||||||
for m in methods {
|
for m in methods {
|
||||||
alt cx.ccx.item_ids.find(m.node.id) {
|
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,
|
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);
|
let sub_cx = extend_path(cx, item.ident);
|
||||||
alt cx.ccx.item_ids.find(item.id) {
|
alt cx.ccx.item_ids.find(item.id) {
|
||||||
some(llfndecl) {
|
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,
|
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)};
|
with *extend_path(cx, item.ident)};
|
||||||
trans_obj(sub_cx, item.span, ob, ctor_id, tps);
|
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) {
|
ast::item_res(dtor, dtor_id, tps, ctor_id) {
|
||||||
trans_res_ctor(cx, item.span, dtor, ctor_id, tps);
|
trans_res_ctor(cx, item.span, dtor, ctor_id, tps);
|
||||||
|
|
||||||
// Create a function for the destructor
|
// Create a function for the destructor
|
||||||
alt cx.ccx.item_ids.find(item.id) {
|
alt cx.ccx.item_ids.find(item.id) {
|
||||||
some(lldtor_decl) {
|
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");
|
cx.ccx.sess.span_fatal(item.span, "unbound dtor in trans_item");
|
||||||
|
|
|
@ -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 trans_closure_env = lambda(ck: ty::closure_kind) -> ValueRef {
|
||||||
let upvars = get_freevars(ccx.tcx, id);
|
let upvars = get_freevars(ccx.tcx, id);
|
||||||
let {llbox, box_ty, bcx} = build_closure(bcx, upvars, ck);
|
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);
|
load_environment(bcx, fcx, box_ty, upvars, ck);
|
||||||
});
|
});
|
||||||
llbox
|
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_send. { trans_closure_env(ty::closure_send) }
|
||||||
ast::proto_bare. {
|
ast::proto_bare. {
|
||||||
let closure = C_null(T_opaque_boxed_closure_ptr(ccx));
|
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
|
closure
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,7 +52,7 @@ fn trans_obj(cx: @local_ctxt, sp: span, ob: ast::_obj, ctor_id: ast::node_id,
|
||||||
let lltop = bcx.llbb;
|
let lltop = bcx.llbb;
|
||||||
|
|
||||||
// Both regular arguments and type parameters are handled here.
|
// Both regular arguments and type parameters are handled here.
|
||||||
create_llargs_for_fn_args(fcx, none::<ty::t>, 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);
|
let arg_tys: [ty::arg] = arg_tys_of_fn(ccx, ctor_id);
|
||||||
bcx = copy_args_to_allocas(fcx, bcx, fn_args, arg_tys);
|
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.
|
// method's definition will be in the executable.
|
||||||
ccx.item_ids.insert(m.node.id, llfn);
|
ccx.item_ids.insert(m.node.id, llfn);
|
||||||
ccx.item_symbols.insert(m.node.id, s);
|
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);
|
m.node.id);
|
||||||
|
|
||||||
ret llfn;
|
ret llfn;
|
||||||
|
|
|
@ -335,7 +335,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
|
||||||
clear_pp(rslt);
|
clear_pp(rslt);
|
||||||
handle_var(fcx, rslt, e.id, path_to_ident(fcx.ccx.tcx, p));
|
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) {
|
expr_log(_, arg) {
|
||||||
find_pre_post_expr(fcx, arg);
|
find_pre_post_expr(fcx, arg);
|
||||||
copy_pre_post(fcx.ccx, e.id, arg);
|
copy_pre_post(fcx.ccx, e.id, arg);
|
||||||
|
|
|
@ -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_break. { ret pure_exp(fcx.ccx, e.id, pres); }
|
||||||
expr_cont. { 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) {
|
expr_anon_obj(anon_obj) {
|
||||||
alt anon_obj.inner_obj {
|
alt anon_obj.inner_obj {
|
||||||
some(wt) { ret find_pre_post_state_sub(fcx, pres, wt, e.id, none); }
|
some(wt) { ret find_pre_post_state_sub(fcx, pres, wt, e.id, none); }
|
||||||
|
|
|
@ -90,6 +90,7 @@ export mk_uint;
|
||||||
export mk_uniq;
|
export mk_uniq;
|
||||||
export mk_var;
|
export mk_var;
|
||||||
export mk_opaque_closure;
|
export mk_opaque_closure;
|
||||||
|
export gen_ty;
|
||||||
export mode;
|
export mode;
|
||||||
export mt;
|
export mt;
|
||||||
export node_type_table;
|
export node_type_table;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import util::common::*;
|
||||||
import syntax::codemap::span;
|
import syntax::codemap::span;
|
||||||
import middle::ty;
|
import middle::ty;
|
||||||
import middle::ty::{node_id_to_type, arg, bind_params_in_type, block_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};
|
ty_param_substs_opt_and_ty, ty_param_kinds_and_ty};
|
||||||
import util::ppaux::ty_to_str;
|
import util::ppaux::ty_to_str;
|
||||||
import middle::ty::unify::{ures_ok, ures_err, fix_ok, fix_err};
|
import middle::ty::unify::{ures_ok, ures_err, fix_ok, fix_err};
|
||||||
|
@ -25,17 +25,12 @@ type method_map = hashmap<ast::node_id, ast::def_id>;
|
||||||
type ty_table = hashmap<ast::def_id, ty::t>;
|
type ty_table = hashmap<ast::def_id, ty::t>;
|
||||||
|
|
||||||
// Used for typechecking the methods of an object.
|
// Used for typechecking the methods of an object.
|
||||||
tag obj_info {
|
tag self_info {
|
||||||
|
self_obj([ast::obj_field], ty::t);
|
||||||
// Regular objects have a node_id at compile time.
|
self_impl(ty::t);
|
||||||
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<ty::sty>);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type crate_ctxt = {mutable obj_infos: [obj_info],
|
type crate_ctxt = {mutable self_infos: [self_info],
|
||||||
impl_map: resolve::impl_map,
|
impl_map: resolve::impl_map,
|
||||||
method_map: method_map,
|
method_map: method_map,
|
||||||
tcx: ty::ctxt};
|
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));
|
let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
|
||||||
ret {kinds: [], ty: typ};
|
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_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_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); }
|
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);
|
write::ty_only(cx.tcx, it.id, tpt.ty);
|
||||||
get_tag_variant_types(cx, local_def(it.id), variants, ty_params);
|
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 {
|
for m in ms {
|
||||||
let ty = ty::method_ty_to_fn_ty(
|
let ty = ty::method_ty_to_fn_ty(
|
||||||
cx.tcx, ty_of_method(cx.tcx, m_collect, m));
|
cx.tcx, ty_of_method(cx.tcx, m_collect, m));
|
||||||
|
@ -704,6 +705,8 @@ mod collect {
|
||||||
{kinds: [], ty: ty});
|
{kinds: [], ty: ty});
|
||||||
write::ty_only(cx.tcx, m.node.id, 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) {
|
ast::item_obj(object, ty_params, ctor_id) {
|
||||||
// Now we need to call ty_of_obj_ctor(); this is the type that
|
// 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.
|
// Add object fields, if any.
|
||||||
let obj_fields = [];
|
alt get_self_info(ccx) {
|
||||||
alt get_obj_info(ccx) {
|
some(self_obj(ofs, _)) {
|
||||||
some(oinfo) {
|
for f in ofs {
|
||||||
alt oinfo {
|
assign(f.id, some(ty::node_id_to_type(ccx.tcx, f.id)));
|
||||||
regular_obj(ofs, _) { obj_fields = ofs; }
|
|
||||||
anon_obj(ofs, _) { obj_fields = ofs; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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.
|
// 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, _) {
|
ast::expr_call(f, args, _) {
|
||||||
bot = check_call_full(fcx, expr.span, f, args, expr.id);
|
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<ty::sty> =
|
|
||||||
some(structure_of(fcx, expr.span, ty::mk_nil(tcx)));
|
|
||||||
let this_obj_info: option::t<obj_info> = 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) {
|
ast::expr_cast(e, t) {
|
||||||
bot = check_expr(fcx, e);
|
bot = check_expr(fcx, e);
|
||||||
let t_1 = ast_ty_to_ty_crate(fcx.ccx, t);
|
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
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
bot |= check_expr(fcx, base);
|
bot |= check_expr(fcx, base);
|
||||||
let base_t = expr_ty(tcx, base);
|
let base_t = expr_ty(tcx, base);
|
||||||
let iscope = fcx.ccx.impl_map.get(expr.id);
|
let iscope = fcx.ccx.impl_map.get(expr.id);
|
||||||
alt lookup_method(fcx, iscope, field, base_t) {
|
alt lookup_method(fcx, iscope, field, base_t) {
|
||||||
some(method) {
|
some(method) {
|
||||||
let mt = ty_of_method(fcx.ccx.tcx, m_check, 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,
|
let fty = ty::mk_fn(fcx.ccx.tcx, mt.proto, mt.inputs,
|
||||||
mt.output, mt.cf, mt.constrs);
|
mt.output, mt.cf, mt.constrs);
|
||||||
write::ty_only_fixup(fcx, id, f_ty);
|
write::ty_only_fixup(fcx, id, fty);
|
||||||
fcx.ccx.method_map.insert(id, local_def(method.node.id));
|
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
|
// Typecheck 'inner_obj'. If it exists, it had better have object
|
||||||
// type.
|
// type.
|
||||||
let inner_obj_methods: [ty::method] = [];
|
let inner_obj_methods: [ty::method] = [];
|
||||||
let inner_obj_ty: ty::t = ty::mk_nil(tcx);
|
|
||||||
let inner_obj_sty: option::t<ty::sty> = none;
|
let inner_obj_sty: option::t<ty::sty> = none;
|
||||||
alt ao.inner_obj {
|
alt ao.inner_obj {
|
||||||
none. { }
|
none. { }
|
||||||
some(e) {
|
some(e) {
|
||||||
// If there's a inner_obj, we push it onto the obj_infos stack
|
// If there's a inner_obj, we push it onto the self_infos
|
||||||
// so that self-calls can be checked within its context later.
|
// stack so that self-calls can be checked within its context
|
||||||
|
// later.
|
||||||
bot |= check_expr(fcx, e);
|
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));
|
inner_obj_sty = some(structure_of(fcx, e.span, inner_obj_ty));
|
||||||
|
|
||||||
alt inner_obj_sty {
|
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
|
// Whenever an outer method overrides an inner, we need to remove
|
||||||
// that inner from the type. Filter inner_obj_methods to remove
|
// that inner from the type. Filter inner_obj_methods to remove
|
||||||
// any methods that share a name with an outer method.
|
// 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);
|
let f = bind filtering_fn(fcx.ccx, _, ao.methods);
|
||||||
inner_obj_methods =
|
inner_obj_methods = vec::filter_map(f, inner_obj_methods);
|
||||||
vec::filter_map::<ty::method,
|
|
||||||
ty::method>(f, inner_obj_methods);
|
|
||||||
|
|
||||||
method_types += 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
|
// Write the methods into the node type table. (This happens in
|
||||||
// collect::convert for regular objects.)
|
// collect::convert for regular objects.)
|
||||||
let i = 0u;
|
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,
|
write::ty_only(tcx, ao.methods[i].node.id,
|
||||||
ty::method_ty_to_fn_ty(tcx, method_types[i]));
|
ty::method_ty_to_fn_ty(tcx, method_types[i]));
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fcx.ccx.self_infos +=
|
||||||
|
[self_obj(vec::map(ast_util::obj_field_from_anon_obj_field,
|
||||||
|
fields), ot)];
|
||||||
// Typecheck the methods.
|
// Typecheck the methods.
|
||||||
for method: @ast::method in ao.methods {
|
for method: @ast::method in ao.methods {
|
||||||
check_method(fcx.ccx, method);
|
check_method(fcx.ccx, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now remove the info from the stack.
|
// Now remove the info from the stack.
|
||||||
vec::pop::<obj_info>(fcx.ccx.obj_infos);
|
vec::pop(fcx.ccx.self_infos);
|
||||||
}
|
}
|
||||||
_ { tcx.sess.unimpl("expr type in typeck::check_expr"); }
|
_ { 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));
|
ret ty::mk_var(fcx.ccx.tcx, next_ty_var_id(fcx));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_obj_info(ccx: @crate_ctxt) -> option::t<obj_info> {
|
fn get_self_info(ccx: @crate_ctxt) -> option::t<self_info> {
|
||||||
ret vec::last::<obj_info>(ccx.obj_infos);
|
ret vec::last(ccx.self_infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_decl_initializer(fcx: @fn_ctxt, nid: ast::node_id,
|
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_res(f, dtor_id, _, _) { check_fn(ccx, f, dtor_id, none); }
|
||||||
ast::item_obj(ob, _, _) {
|
ast::item_obj(ob, _, _) {
|
||||||
// We're entering an object, so gather up the info we need.
|
// 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.
|
// Typecheck the methods.
|
||||||
for method: @ast::method in ob.methods { check_method(ccx, method); }
|
for method: @ast::method in ob.methods { check_method(ccx, method); }
|
||||||
// Now remove the info from the stack.
|
// Now remove the info from the stack.
|
||||||
vec::pop::<obj_info>(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 */ }
|
_ {/* nothing to do */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2701,9 +2647,7 @@ fn check_crate(tcx: ty::ctxt, impl_map: resolve::impl_map,
|
||||||
crate: @ast::crate) -> method_map {
|
crate: @ast::crate) -> method_map {
|
||||||
collect::collect_item_types(tcx, crate);
|
collect::collect_item_types(tcx, crate);
|
||||||
|
|
||||||
let obj_infos: [obj_info] = [];
|
let ccx = @{mutable self_infos: [],
|
||||||
|
|
||||||
let ccx = @{mutable obj_infos: obj_infos,
|
|
||||||
impl_map: impl_map,
|
impl_map: impl_map,
|
||||||
method_map: std::map::new_int_hash(),
|
method_map: std::map::new_int_hash(),
|
||||||
tcx: tcx};
|
tcx: tcx};
|
||||||
|
|
|
@ -28,13 +28,13 @@ type ty_param = {ident: ident, kind: kind};
|
||||||
tag def {
|
tag def {
|
||||||
def_fn(def_id, purity);
|
def_fn(def_id, purity);
|
||||||
def_obj_field(def_id, mutability);
|
def_obj_field(def_id, mutability);
|
||||||
|
def_self(def_id);
|
||||||
def_mod(def_id);
|
def_mod(def_id);
|
||||||
def_native_mod(def_id);
|
def_native_mod(def_id);
|
||||||
def_const(def_id);
|
def_const(def_id);
|
||||||
def_arg(def_id, mode);
|
def_arg(def_id, mode);
|
||||||
def_local(def_id, let_style);
|
def_local(def_id, let_style);
|
||||||
def_variant(def_id /* tag */, def_id /* variant */);
|
def_variant(def_id /* tag */, def_id /* variant */);
|
||||||
def_self(def_id);
|
|
||||||
def_ty(def_id);
|
def_ty(def_id);
|
||||||
def_ty_param(uint, kind);
|
def_ty_param(uint, kind);
|
||||||
def_binding(def_id);
|
def_binding(def_id);
|
||||||
|
@ -214,7 +214,6 @@ tag expr_ {
|
||||||
expr_rec([field], option::t<@expr>);
|
expr_rec([field], option::t<@expr>);
|
||||||
expr_call(@expr, [@expr], bool);
|
expr_call(@expr, [@expr], bool);
|
||||||
expr_tup([@expr]);
|
expr_tup([@expr]);
|
||||||
expr_self_method(ident);
|
|
||||||
expr_bind(@expr, [option::t<@expr>]);
|
expr_bind(@expr, [option::t<@expr>]);
|
||||||
expr_binary(binop, @expr, @expr);
|
expr_binary(binop, @expr, @expr);
|
||||||
expr_unary(unop, @expr);
|
expr_unary(unop, @expr);
|
||||||
|
|
|
@ -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),
|
expr_call(fld.fold_expr(f), fld.map_exprs(fld.fold_expr, args),
|
||||||
blk)
|
blk)
|
||||||
}
|
}
|
||||||
expr_self_method(id) { expr_self_method(fld.fold_ident(id)) }
|
|
||||||
expr_bind(f, args) {
|
expr_bind(f, args) {
|
||||||
let opt_map_se = bind option::map(fld.fold_expr, _);
|
let opt_map_se = bind option::map(fld.fold_expr, _);
|
||||||
expr_bind(fld.fold_expr(f), vec::map(opt_map_se, args))
|
expr_bind(fld.fold_expr(f), vec::map(opt_map_se, args))
|
||||||
|
|
|
@ -155,8 +155,7 @@ fn bad_expr_word_table() -> hashmap<str, ()> {
|
||||||
"cont", "ret", "be", "fail", "type", "resource", "check",
|
"cont", "ret", "be", "fail", "type", "resource", "check",
|
||||||
"assert", "claim", "native", "fn", "lambda", "pure",
|
"assert", "claim", "native", "fn", "lambda", "pure",
|
||||||
"unsafe", "block", "import", "export", "let", "const",
|
"unsafe", "block", "import", "export", "let", "const",
|
||||||
"log", "log_err", "tag", "obj", "self", "copy", "sendfn",
|
"log", "log_err", "tag", "obj", "copy", "sendfn", "impl"] {
|
||||||
"impl"] {
|
|
||||||
words.insert(word, ());
|
words.insert(word, ());
|
||||||
}
|
}
|
||||||
words
|
words
|
||||||
|
@ -942,15 +941,6 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
||||||
let e = parse_expr(p);
|
let e = parse_expr(p);
|
||||||
ex = ast::expr_copy(e);
|
ex = ast::expr_copy(e);
|
||||||
hi = e.span.hi;
|
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 ||
|
} else if p.peek() == token::MOD_SEP ||
|
||||||
is_ident(p.peek()) && !is_word(p, "true") &&
|
is_ident(p.peek()) && !is_word(p, "true") &&
|
||||||
!is_word(p, "false") {
|
!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));
|
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 {
|
fn parse_dot_or_call_expr(p: parser) -> @ast::expr {
|
||||||
let b = parse_bottom_expr(p);
|
let b = parse_bottom_expr(p);
|
||||||
if expr_has_value(b) { parse_dot_or_call_expr_with(p, b) }
|
if expr_has_value(b) { parse_dot_or_call_expr_with(p, b) }
|
||||||
|
|
|
@ -736,10 +736,6 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
||||||
print_expr(s, option::get(blk));
|
print_expr(s, option::get(blk));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::expr_self_method(ident) {
|
|
||||||
word(s.s, "self.");
|
|
||||||
print_ident(s, ident);
|
|
||||||
}
|
|
||||||
ast::expr_bind(func, args) {
|
ast::expr_bind(func, args) {
|
||||||
fn print_opt(s: ps, expr: option::t<@ast::expr>) {
|
fn print_opt(s: ps, expr: option::t<@ast::expr>) {
|
||||||
alt expr {
|
alt expr {
|
||||||
|
|
|
@ -251,7 +251,6 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
||||||
visit_exprs(args, e, v);
|
visit_exprs(args, e, v);
|
||||||
v.visit_expr(callee, e, v);
|
v.visit_expr(callee, e, v);
|
||||||
}
|
}
|
||||||
expr_self_method(_) { }
|
|
||||||
expr_bind(callee, args) {
|
expr_bind(callee, args) {
|
||||||
v.visit_expr(callee, e, v);
|
v.visit_expr(callee, e, v);
|
||||||
for eo: option::t<@expr> in args { visit_expr_opt(eo, e, v); }
|
for eo: option::t<@expr> in args { visit_expr_opt(eo, e, v); }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// error-pattern:self-call in non-object context
|
// error-pattern:unresolved name: self
|
||||||
|
|
||||||
// Fix for issue #707.
|
// Fix for issue #707.
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// error-pattern:expecting ., found (
|
// error-pattern:attempted field access on type fn
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
obj foo() {
|
obj foo() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue