@@ -52,7 +52,13 @@ export check_crate;
52
52
53
53
type ty_table = hashmap [ ast:: def_id, ty:: t] ;
54
54
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
+ }
56
62
57
63
type crate_ctxt = rec( mutable obj_info[ ] obj_infos, ty:: ctxt tcx) ;
58
64
@@ -622,8 +628,8 @@ mod collect {
622
628
ret ty_of_fn_decl( cx, convert, f, fn_info. decl, fn_info. proto,
623
629
tps, some( local_def( it. id) ) ) ;
624
630
}
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) ;
627
633
cx. tcx. tcache. insert( local_def( it. id) , t_obj) ;
628
634
ret t_obj;
629
635
}
@@ -1196,10 +1202,21 @@ fn gather_locals(&@crate_ctxt ccx, &ast::_fn f,
1196
1202
// Add object fields, if any.
1197
1203
alt ( get_obj_info( ccx) ) {
1198
1204
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
+ }
1203
1220
}
1204
1221
}
1205
1222
case ( option:: none) { /* no fields * / }
@@ -2095,16 +2112,30 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
2095
2112
let ty:: t this_obj_ty = ty:: mk_nil( fcx. ccx. tcx) ;
2096
2113
let option:: t[ obj_info] this_obj_info = get_obj_info( fcx. ccx) ;
2097
2114
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
+ }
2108
2139
}
2109
2140
case ( none) {
2110
2141
// Shouldn't happen.
@@ -2353,36 +2384,21 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
2353
2384
}
2354
2385
}
2355
2386
}
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) ) {
2361
2388
2362
2389
let ast:: anon_obj_field[ ] fields = ~[ ] ;
2363
- alt ( anon_obj . fields) {
2390
+ alt ( ao . fields) {
2364
2391
case ( none) { }
2365
2392
case ( some( ?v) ) { fields = v; }
2366
2393
}
2367
2394
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
-
2380
2395
// FIXME: These next three functions are largely ripped off from
2381
2396
// similar ones in collect::. Is there a better way to do this?
2382
2397
fn ty_of_arg( @crate_ctxt ccx, & ast:: arg a) -> ty:: arg {
2383
2398
auto ty_mode = ast_mode_to_mode( a. mode) ;
2384
2399
ret rec( mode=ty_mode, ty=ast_ty_to_ty_crate( ccx, a. ty) ) ;
2385
2400
}
2401
+
2386
2402
fn ty_of_method( @crate_ctxt ccx, & @ast:: method m) -> ty:: method {
2387
2403
auto convert = bind ast_ty_to_ty_crate( ccx, _) ;
2388
2404
@@ -2402,14 +2418,17 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
2402
2418
inputs=inputs, output=output, cf=m. node. meth. decl. cf,
2403
2419
constrs=out_constrs) ;
2404
2420
}
2421
+
2405
2422
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)
2407
2426
-> ty:: method[ ] {
2408
2427
2409
2428
let ty:: method[ ] methods = ~[ ] ;
2410
2429
2411
2430
// Outer methods.
2412
- for ( @ast:: method m in anon_obj . methods) {
2431
+ for ( @ast:: method m in ao . methods) {
2413
2432
methods += ~[ ty_of_method( fcx. ccx, m) ] ;
2414
2433
}
2415
2434
@@ -2418,11 +2437,12 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
2418
2437
// Typecheck 'with_obj'. If it exists, it had better have
2419
2438
// object type.
2420
2439
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) {
2422
2442
case ( none) { }
2423
2443
case ( some( ?e) ) {
2424
2444
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) ;
2426
2446
2427
2447
alt ( structure_of( fcx, e. span, with_obj_ty) ) {
2428
2448
case ( ty:: ty_obj( ?ms) ) {
@@ -2438,28 +2458,40 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
2438
2458
}
2439
2459
}
2440
2460
}
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
+
2441
2472
methods += with_obj_methods;
2442
2473
2443
2474
ret methods;
2444
2475
}
2445
2476
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) ;
2447
2479
auto ot = ty:: mk_obj( fcx. ccx. tcx, ty:: sort_methods( method_types) ) ;
2448
2480
2449
2481
write:: ty_only_fixup( fcx, id, ot) ;
2450
2482
// Write the methods into the node type table. (This happens in
2451
2483
// collect::convert for regular objects.)
2452
2484
2453
2485
auto i = 0 u;
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 ,
2456
2488
ty:: method_ty_to_fn_ty ( fcx. ccx . tcx ,
2457
2489
method_types. ( i) ) ) ;
2458
2490
i += 1 u;
2459
2491
}
2460
2492
2461
2493
// Typecheck the methods.
2462
- for ( @ast:: method method in anon_obj . methods) {
2494
+ for ( @ast:: method method in ao . methods) {
2463
2495
check_method ( fcx. ccx , method) ;
2464
2496
}
2465
2497
next_ty_var ( fcx) ;
@@ -2654,8 +2686,8 @@ fn check_item(@crate_ctxt ccx, &@ast::item it) {
2654
2686
}
2655
2687
case ( ast:: item_obj ( ?ob, _, _) ) {
2656
2688
// We're entering an object, so gather up the info we need.
2689
+ ccx. obj_infos += ~[ regular_obj ( ob. fields , it. id ) ] ;
2657
2690
2658
- ccx. obj_infos += ~[ rec ( obj_fields=ob. fields , this_obj=it. id ) ] ;
2659
2691
// Typecheck the methods.
2660
2692
for ( @ast:: method method in ob. methods) {
2661
2693
check_method ( ccx, method) ;
0 commit comments