Skip to content

Commit 2eb4762

Browse files
committed
Typechecking self-calls in anon objs. Closes #540.
1 parent 64fb39c commit 2eb4762

File tree

3 files changed

+51
-34
lines changed

3 files changed

+51
-34
lines changed

src/comp/middle/typeck.rs

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ type ty_table = hashmap[ast::def_id, ty::t];
5555
tag obj_info {
5656
// Regular objects have a node_id at compile time.
5757
regular_obj(ast::obj_field[], ast::node_id);
58-
// Anonymous objects only have a type at compile time.
59-
anon_obj(ast::obj_field[], ty::t);
58+
// Anonymous objects only have a type at compile time. It's optional
59+
// because not all anonymous objects have a with_obj to attach to.
60+
anon_obj(ast::obj_field[], option::t[ty::sty]);
6061
}
6162

6263
type crate_ctxt = rec(mutable obj_info[] obj_infos, ty::ctxt tcx);
@@ -2114,7 +2115,8 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
21142115
}
21152116
case (ast::expr_self_method(?ident)) {
21162117
auto t = ty::mk_nil(fcx.ccx.tcx);
2117-
let ty::t this_obj_ty = ty::mk_nil(fcx.ccx.tcx);
2118+
let option::t[ty::sty] this_obj_sty =
2119+
some(structure_of(fcx, expr.span, ty::mk_nil(fcx.ccx.tcx)));
21182120
let option::t[obj_info] this_obj_info = get_obj_info(fcx.ccx);
21192121
alt (this_obj_info) {
21202122
case (some(?oinfo)) {
@@ -2128,7 +2130,10 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
21282130
// If we're typechecking a self-method on
21292131
// a regular object, this lookup should
21302132
// succeed.
2131-
this_obj_ty = tpt._1;
2133+
this_obj_sty =
2134+
some(structure_of(fcx,
2135+
expr.span,
2136+
tpt._1));
21322137
}
21332138
case (none) {
21342139
fcx.ccx.tcx.sess.bug(
@@ -2137,8 +2142,8 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
21372142
}
21382143
}
21392144
}
2140-
case (anon_obj(_, ?obj_ty)) {
2141-
this_obj_ty = obj_ty;
2145+
case (anon_obj(_, ?obj_sty)) {
2146+
this_obj_sty = obj_sty;
21422147
}
21432148
}
21442149
}
@@ -2151,15 +2156,21 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
21512156
}
21522157

21532158
// Grab this method's type out of the current object type.
2154-
alt (structure_of(fcx, expr.span, this_obj_ty)) {
2155-
case (ty::ty_obj(?methods)) {
2156-
for (ty::method method in methods) {
2157-
if (method.ident == ident) {
2158-
t = ty::method_ty_to_fn_ty(fcx.ccx.tcx, method);
2159+
alt (this_obj_sty) {
2160+
case (some(?sty)) {
2161+
alt (sty) {
2162+
case (ty::ty_obj(?methods)) {
2163+
for (ty::method method in methods) {
2164+
if (method.ident == ident) {
2165+
t = ty::method_ty_to_fn_ty(fcx.ccx.tcx,
2166+
method);
2167+
}
2168+
}
21592169
}
2170+
case (_) { fail; }
21602171
}
21612172
}
2162-
case (_) { fail; }
2173+
case (none) { }
21632174
}
21642175
write::ty_only_fixup(fcx, id, t);
21652176
require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
@@ -2442,40 +2453,49 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
24422453
// Typecheck 'with_obj'. If it exists, it had better have
24432454
// object type.
24442455
let ty::method[] with_obj_methods = ~[];
2445-
auto with_obj_ty = ty::mk_nil(fcx.ccx.tcx);
2456+
let ty::t with_obj_ty = ty::mk_nil(fcx.ccx.tcx);
2457+
let option::t[ty::sty] with_obj_sty = none;
24462458
alt (ao.with_obj) {
24472459
case (none) { }
24482460
case (some(?e)) {
2461+
// If there's a with_obj, we push it onto the
2462+
// obj_infos stack so that self-calls can be checked
2463+
// within its context later.
24492464
check_expr(fcx, e);
24502465
with_obj_ty = expr_ty(fcx.ccx.tcx, e);
2451-
2452-
alt (structure_of(fcx, e.span, with_obj_ty)) {
2453-
case (ty::ty_obj(?ms)) {
2454-
with_obj_methods = ms;
2455-
}
2456-
case (_) {
2457-
// The user is trying to extend a non-object.
2458-
fcx.ccx.tcx.sess.span_fatal(
2459-
e.span,
2460-
syntax::print::pprust::expr_to_str(e) +
2461-
" does not have object type");
2466+
with_obj_sty = some(structure_of(fcx, e.span,
2467+
with_obj_ty));
2468+
2469+
alt (with_obj_sty) {
2470+
case (none) { }
2471+
case (some(?sty)) {
2472+
alt (sty) {
2473+
case (ty::ty_obj(?ms)) {
2474+
with_obj_methods = ms;
2475+
}
2476+
case (_) {
2477+
// The user is trying to extend a
2478+
// non-object.
2479+
fcx.ccx.tcx.sess.span_fatal(
2480+
e.span,
2481+
syntax::print::pprust::expr_to_str(e) +
2482+
" does not have object type");
2483+
}
2484+
}
24622485
}
24632486
}
24642487
}
24652488
}
24662489

2467-
log_err "Pushing an anon obj onto the obj_infos stack...";
2468-
fn anon_obj_field_to_obj_field(&ast::anon_obj_field f)
2490+
fn ao_field_to_o_field(&ast::anon_obj_field f)
24692491
-> ast::obj_field {
24702492
ret rec(mut=f.mut, ty=f.ty, ident=f.ident, id=f.id);
24712493
}
24722494
fcx.ccx.obj_infos +=
2473-
~[anon_obj(ivec::map(anon_obj_field_to_obj_field,
2474-
fields),
2475-
with_obj_ty)];
2495+
~[anon_obj(ivec::map(ao_field_to_o_field, fields),
2496+
with_obj_sty)];
24762497

24772498
methods += with_obj_methods;
2478-
24792499
ret methods;
24802500
}
24812501

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
//xfail-stage0
2-
//xfail-stage1
3-
//xfail-stage2
42

53
// Reduced test case for issue #540.
64
fn main() {

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//xfail-stage0
2-
//xfail-stage1
3-
//xfail-stage2
2+
43
use std;
54

65
fn main() {

0 commit comments

Comments
 (0)