Skip to content

Commit a5d9f0a

Browse files
committed
---
yaml --- r: 4003 b: refs/heads/master c: 18162d3 h: refs/heads/master i: 4001: 170316f 3999: 63cf1dc v: v3
1 parent 9c442bb commit a5d9f0a

File tree

3 files changed

+77
-47
lines changed

3 files changed

+77
-47
lines changed

[refs]

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: a14e5e70462fed497ce8e12e52c1ef099678a8de
2+
refs/heads/master: 18162d3261e4214c0f55479b3fba29d1ed5e634a

trunk/src/comp/middle/typeck.rs

+76-44
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,13 @@ export check_crate;
5252

5353
type ty_table = hashmap[ast::def_id, ty::t];
5454

55-
type obj_info = rec(ast::obj_field[] obj_fields, ast::node_id this_obj);
55+
// Used for typechecking the methods of an object.
56+
tag obj_info {
57+
// Regular objects have a node_id at compile time.
58+
regular_obj(ast::obj_field[], ast::node_id);
59+
// Anonymous objects only have a type at compile time.
60+
anon_obj(ast::obj_field[], ty::t);
61+
}
5662

5763
type crate_ctxt = rec(mutable obj_info[] obj_infos, ty::ctxt tcx);
5864

@@ -622,8 +628,8 @@ mod collect {
622628
ret ty_of_fn_decl(cx, convert, f, fn_info.decl, fn_info.proto,
623629
tps, some(local_def(it.id)));
624630
}
625-
case (ast::item_obj(?obj_info, ?tps, _)) {
626-
auto t_obj = ty_of_obj(cx, it.ident, obj_info, tps);
631+
case (ast::item_obj(?ob, ?tps, _)) {
632+
auto t_obj = ty_of_obj(cx, it.ident, ob, tps);
627633
cx.tcx.tcache.insert(local_def(it.id), t_obj);
628634
ret t_obj;
629635
}
@@ -1196,10 +1202,21 @@ fn gather_locals(&@crate_ctxt ccx, &ast::_fn f,
11961202
// Add object fields, if any.
11971203
alt (get_obj_info(ccx)) {
11981204
case (option::some(?oinfo)) {
1199-
for (ast::obj_field f in oinfo.obj_fields) {
1200-
auto field_ty = ty::node_id_to_type(ccx.tcx, f.id);
1201-
assign(ccx.tcx, vb, locals, local_names, nvi, f.id,
1202-
f.ident, some(field_ty));
1205+
alt (oinfo) {
1206+
case (regular_obj(?obj_fields, _)) {
1207+
for (ast::obj_field f in obj_fields) {
1208+
auto field_ty = ty::node_id_to_type(ccx.tcx, f.id);
1209+
assign(ccx.tcx, vb, locals, local_names, nvi, f.id,
1210+
f.ident, some(field_ty));
1211+
}
1212+
}
1213+
case (anon_obj(?obj_fields, _)) {
1214+
for (ast::obj_field f in obj_fields) {
1215+
auto field_ty = ty::node_id_to_type(ccx.tcx, f.id);
1216+
assign(ccx.tcx, vb, locals, local_names, nvi, f.id,
1217+
f.ident, some(field_ty));
1218+
}
1219+
}
12031220
}
12041221
}
12051222
case (option::none) {/* no fields */ }
@@ -2095,16 +2112,30 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
20952112
let ty::t this_obj_ty = ty::mk_nil(fcx.ccx.tcx);
20962113
let option::t[obj_info] this_obj_info = get_obj_info(fcx.ccx);
20972114
alt (this_obj_info) {
2098-
case (
2099-
// If we're inside a current object, grab its type.
2100-
some(?obj_info)) {
2101-
// FIXME: In the case of anonymous objects with methods
2102-
// containing self-calls, this lookup fails because
2103-
// obj_info.this_obj is not in the type cache
2104-
2105-
this_obj_ty =
2106-
ty::lookup_item_type(fcx.ccx.tcx,
2107-
local_def(obj_info.this_obj))._1;
2115+
case (some(?oinfo)) {
2116+
alt (oinfo) {
2117+
case (regular_obj(_, ?obj_id)) {
2118+
auto did = local_def(obj_id);
2119+
// Try looking up the current object in the type
2120+
// cache.
2121+
alt (fcx.ccx.tcx.tcache.find(did)) {
2122+
case (some(?tpt)) {
2123+
// If we're typechecking a self-method on
2124+
// a regular object, this lookup should
2125+
// succeed.
2126+
this_obj_ty = tpt._1;
2127+
}
2128+
case (none) {
2129+
fcx.ccx.tcx.sess.bug(
2130+
"didn't find " + int::str(did._1) +
2131+
" in type cache");
2132+
}
2133+
}
2134+
}
2135+
case (anon_obj(_, ?obj_ty)) {
2136+
this_obj_ty = obj_ty;
2137+
}
2138+
}
21082139
}
21092140
case (none) {
21102141
// Shouldn't happen.
@@ -2353,36 +2384,21 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
23532384
}
23542385
}
23552386
}
2356-
case (ast::expr_anon_obj(?anon_obj, ?tps)) {
2357-
// TODO: We probably need to do more work here to be able to
2358-
// handle additional methods that use 'self'
2359-
2360-
// We're entering an object, so gather up the info we need.
2387+
case (ast::expr_anon_obj(?ao, ?tps)) {
23612388

23622389
let ast::anon_obj_field[] fields = ~[];
2363-
alt (anon_obj.fields) {
2390+
alt (ao.fields) {
23642391
case (none) { }
23652392
case (some(?v)) { fields = v; }
23662393
}
23672394

2368-
// FIXME: this is duplicated between here and trans -- it should
2369-
// appear in one place
2370-
fn anon_obj_field_to_obj_field(&ast::anon_obj_field f)
2371-
-> ast::obj_field {
2372-
ret rec(mut=f.mut, ty=f.ty, ident=f.ident, id=f.id);
2373-
}
2374-
2375-
fcx.ccx.obj_infos +=
2376-
~[rec(obj_fields=ivec::map(anon_obj_field_to_obj_field,
2377-
fields),
2378-
this_obj=id)];
2379-
23802395
// FIXME: These next three functions are largely ripped off from
23812396
// similar ones in collect::. Is there a better way to do this?
23822397
fn ty_of_arg(@crate_ctxt ccx, &ast::arg a) -> ty::arg {
23832398
auto ty_mode = ast_mode_to_mode(a.mode);
23842399
ret rec(mode=ty_mode, ty=ast_ty_to_ty_crate(ccx, a.ty));
23852400
}
2401+
23862402
fn ty_of_method(@crate_ctxt ccx, &@ast::method m) -> ty::method {
23872403
auto convert = bind ast_ty_to_ty_crate(ccx, _);
23882404

@@ -2402,14 +2418,17 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
24022418
inputs=inputs, output=output, cf=m.node.meth.decl.cf,
24032419
constrs=out_constrs);
24042420
}
2421+
24052422
fn get_anon_obj_method_types(@fn_ctxt fcx,
2406-
&ast::anon_obj anon_obj)
2423+
&ast::anon_obj ao,
2424+
&ast::anon_obj_field[] fields,
2425+
&ast::ty_param[] tps)
24072426
-> ty::method[] {
24082427

24092428
let ty::method[] methods = ~[];
24102429

24112430
// Outer methods.
2412-
for (@ast::method m in anon_obj.methods) {
2431+
for (@ast::method m in ao.methods) {
24132432
methods += ~[ty_of_method(fcx.ccx, m)];
24142433
}
24152434

@@ -2418,11 +2437,12 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
24182437
// Typecheck 'with_obj'. If it exists, it had better have
24192438
// object type.
24202439
let ty::method[] with_obj_methods = ~[];
2421-
alt (anon_obj.with_obj) {
2440+
auto with_obj_ty = ty::mk_nil(fcx.ccx.tcx);
2441+
alt (ao.with_obj) {
24222442
case (none) { }
24232443
case (some(?e)) {
24242444
check_expr(fcx, e);
2425-
auto with_obj_ty = expr_ty(fcx.ccx.tcx, e);
2445+
with_obj_ty = expr_ty(fcx.ccx.tcx, e);
24262446

24272447
alt (structure_of(fcx, e.span, with_obj_ty)) {
24282448
case (ty::ty_obj(?ms)) {
@@ -2438,28 +2458,40 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
24382458
}
24392459
}
24402460
}
2461+
2462+
log_err "Pushing an anon obj onto the obj_infos stack...";
2463+
fn anon_obj_field_to_obj_field(&ast::anon_obj_field f)
2464+
-> ast::obj_field {
2465+
ret rec(mut=f.mut, ty=f.ty, ident=f.ident, id=f.id);
2466+
}
2467+
fcx.ccx.obj_infos +=
2468+
~[anon_obj(ivec::map(anon_obj_field_to_obj_field,
2469+
fields),
2470+
with_obj_ty)];
2471+
24412472
methods += with_obj_methods;
24422473

24432474
ret methods;
24442475
}
24452476

2446-
auto method_types = get_anon_obj_method_types(fcx, anon_obj);
2477+
auto method_types = get_anon_obj_method_types(fcx, ao,
2478+
fields, tps);
24472479
auto ot = ty::mk_obj(fcx.ccx.tcx, ty::sort_methods(method_types));
24482480

24492481
write::ty_only_fixup(fcx, id, ot);
24502482
// Write the methods into the node type table. (This happens in
24512483
// collect::convert for regular objects.)
24522484

24532485
auto i = 0u;
2454-
while (i < ivec::len[@ast::method](anon_obj.methods)) {
2455-
write::ty_only(fcx.ccx.tcx, anon_obj.methods.(i).node.id,
2486+
while (i < ivec::len[@ast::method](ao.methods)) {
2487+
write::ty_only(fcx.ccx.tcx, ao.methods.(i).node.id,
24562488
ty::method_ty_to_fn_ty(fcx.ccx.tcx,
24572489
method_types.(i)));
24582490
i += 1u;
24592491
}
24602492

24612493
// Typecheck the methods.
2462-
for (@ast::method method in anon_obj.methods) {
2494+
for (@ast::method method in ao.methods) {
24632495
check_method(fcx.ccx, method);
24642496
}
24652497
next_ty_var(fcx);
@@ -2654,8 +2686,8 @@ fn check_item(@crate_ctxt ccx, &@ast::item it) {
26542686
}
26552687
case (ast::item_obj(?ob, _, _)) {
26562688
// We're entering an object, so gather up the info we need.
2689+
ccx.obj_infos += ~[regular_obj(ob.fields, it.id)];
26572690

2658-
ccx.obj_infos += ~[rec(obj_fields=ob.fields, this_obj=it.id)];
26592691
// Typecheck the methods.
26602692
for (@ast::method method in ob.methods) {
26612693
check_method(ccx, method);

trunk/src/test/run-pass/anon-obj-with-self-call.rs

-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ fn main() {
1919
// Extending an object with a new method that contains a simple
2020
// self-call. Adding support for this is issue #540.
2121

22-
// Right now, this fails with a failed lookup in a hashmap; not
23-
// sure where, but I think it might be during typeck.
2422
auto my_b = obj {
2523
fn baz() -> int {
2624
ret self.foo();

0 commit comments

Comments
 (0)