@@ -79,15 +79,16 @@ import std::map::str_hash;
79
79
80
80
type self_info = {
81
81
self_ty : ty:: t ,
82
+ self_id : ast:: node_id ,
82
83
def_id : ast:: def_id ,
83
- explicit_self : ast:: self_ty_
84
+ explicit_self : ast:: self_ty
84
85
} ;
85
86
86
87
type fn_ctxt_ =
87
88
// var_bindings, locals and next_var_id are shared
88
89
// with any nested functions that capture the environment
89
90
// (and with any functions whose environment is being captured).
90
- { self_info : option < self_info > ,
91
+ { self_impl_def_id : option < ast :: def_id > ,
91
92
ret_ty : ty:: t ,
92
93
// Used by loop bodies that return from the outer function
93
94
indirect_ret_ty : option < ty:: t > ,
@@ -126,7 +127,7 @@ fn blank_fn_ctxt(ccx: @crate_ctxt, rty: ty::t,
126
127
region_bnd : ast:: node_id ) -> @fn_ctxt {
127
128
// It's kind of a kludge to manufacture a fake function context
128
129
// and statement context, but we might as well do write the code only once
129
- @fn_ctxt_ ( { self_info : none,
130
+ @fn_ctxt_ ( { self_impl_def_id : none,
130
131
ret_ty: rty,
131
132
indirect_ret_ty: none,
132
133
purity: ast:: pure_fn,
@@ -244,7 +245,7 @@ fn check_fn(ccx: @crate_ctxt,
244
245
}
245
246
} else { none } ;
246
247
247
- @fn_ctxt_ ( { self_info : self_info,
248
+ @fn_ctxt_ ( { self_impl_def_id : self_info. map ( |info| info . def_id ) ,
248
249
ret_ty: ret_ty,
249
250
indirect_ret_ty: indirect_ret_ty,
250
251
purity: purity,
@@ -257,7 +258,22 @@ fn check_fn(ccx: @crate_ctxt,
257
258
ccx: ccx} )
258
259
} ;
259
260
260
- gather_locals ( fcx, decl, body, arg_tys) ;
261
+ // Update the self_info to contain an accurate self type (taking
262
+ // into account explicit self).
263
+ let self_info = do self_info. chain |info| {
264
+ // If the self type is sty_static, we don't have a self ty.
265
+ if info. explicit_self . node == ast:: sty_static {
266
+ none
267
+ } else {
268
+ let self_region = fcx. in_scope_regions . find ( ty:: br_self) ;
269
+ let ty = method:: transform_self_type_for_method (
270
+ fcx. tcx ( ) , self_region,
271
+ info. self_ty , info. explicit_self . node ) ;
272
+ some ( { self_ty: ty with info} )
273
+ }
274
+ } ;
275
+
276
+ gather_locals ( fcx, decl, body, arg_tys, self_info) ;
261
277
check_block ( fcx, body) ;
262
278
263
279
// We unify the tail expr's type with the
@@ -270,10 +286,11 @@ fn check_fn(ccx: @crate_ctxt,
270
286
none => ( )
271
287
}
272
288
273
- let mut i = 0 u;
274
- do vec:: iter ( arg_tys) |arg| {
275
- fcx. write_ty ( decl. inputs [ i] . id , arg) ;
276
- i += 1 u;
289
+ for self_info. each |info| {
290
+ fcx. write_ty ( info. self_id , info. self_ty ) ;
291
+ }
292
+ do vec:: iter2 ( decl. inputs , arg_tys) |input, arg| {
293
+ fcx. write_ty ( input. id , arg) ;
277
294
}
278
295
279
296
// If we don't have any enclosing function scope, it is time to
@@ -283,13 +300,14 @@ fn check_fn(ccx: @crate_ctxt,
283
300
if option:: is_none ( old_fcx) {
284
301
vtable:: resolve_in_block ( fcx, body) ;
285
302
regionck:: regionck_fn ( fcx, decl, body) ;
286
- writeback:: resolve_type_vars_in_fn ( fcx, decl, body) ;
303
+ writeback:: resolve_type_vars_in_fn ( fcx, decl, body, self_info ) ;
287
304
}
288
305
289
306
fn gather_locals ( fcx : @fn_ctxt ,
290
307
decl : ast:: fn_decl ,
291
308
body : ast:: blk ,
292
- arg_tys : ~[ ty:: t ] ) {
309
+ arg_tys : ~[ ty:: t ] ,
310
+ self_info : option < self_info > ) {
293
311
let tcx = fcx. ccx . tcx ;
294
312
295
313
let assign = fn @( span: span, nid: ast:: node_id,
@@ -305,6 +323,14 @@ fn check_fn(ccx: @crate_ctxt,
305
323
}
306
324
} ;
307
325
326
+ // Add the self parameter
327
+ for self_info. each |info| {
328
+ assign ( info. explicit_self . span ,
329
+ info. self_id , some ( info. self_ty ) ) ;
330
+ debug ! { "self is assigned to %s" ,
331
+ fcx. locals. get( info. self_id) . to_str( ) } ;
332
+ }
333
+
308
334
// Add formal parameters.
309
335
do vec:: iter2 ( arg_tys, decl. inputs ) |arg_ty, input| {
310
336
assign ( input. ty . span , input. id , some ( arg_ty) ) ;
@@ -369,8 +395,11 @@ fn check_fn(ccx: @crate_ctxt,
369
395
}
370
396
371
397
fn check_method ( ccx : @crate_ctxt , method : @ast:: method ,
372
- self_info : self_info ) {
373
-
398
+ self_ty : ty:: t , self_impl_def_id : ast:: def_id ) {
399
+ let self_info = { self_ty: self_ty,
400
+ self_id: method. self_id ,
401
+ def_id: self_impl_def_id,
402
+ explicit_self: method. self_ty } ;
374
403
check_bare_fn ( ccx, method. decl , method. body , method. id , some ( self_info) ) ;
375
404
}
376
405
@@ -404,33 +433,31 @@ fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def,
404
433
405
434
do option:: iter ( struct_def. ctor ) |ctor| {
406
435
let class_t = { self_ty: self_ty,
436
+ self_id: ctor. node . self_id ,
407
437
def_id: local_def ( id) ,
408
- explicit_self: ast:: sty_by_ref} ;
438
+ explicit_self : { node : ast:: sty_by_ref,
439
+ span : ast_util:: dummy_sp ( ) } } ;
409
440
// typecheck the ctor
410
441
check_bare_fn ( ccx, ctor. node . dec ,
411
442
ctor. node . body , ctor. node . id ,
412
443
some ( class_t) ) ;
413
- // Write the ctor's self's type
414
- write_ty_to_tcx ( tcx, ctor. node . self_id , class_t. self_ty ) ;
415
444
}
416
445
417
446
do option:: iter ( struct_def. dtor ) |dtor| {
418
447
let class_t = { self_ty: self_ty,
448
+ self_id: dtor. node . self_id ,
419
449
def_id: local_def ( id) ,
420
- explicit_self: ast:: sty_by_ref} ;
450
+ explicit_self : { node : ast:: sty_by_ref,
451
+ span : ast_util:: dummy_sp ( ) } } ;
421
452
// typecheck the dtor
422
453
check_bare_fn ( ccx, ast_util:: dtor_dec ( ) ,
423
454
dtor. node . body , dtor. node . id ,
424
455
some ( class_t) ) ;
425
- // Write the dtor's self's type
426
- write_ty_to_tcx ( tcx, dtor. node . self_id , class_t. self_ty ) ;
427
456
} ;
428
457
429
458
// typecheck the methods
430
459
for struct_def. methods. each |m| {
431
- check_method( ccx, m, { self_ty: self_ty,
432
- def_id: local_def( id) ,
433
- explicit_self: m. self_ty. node} ) ;
460
+ check_method( ccx, m, self_ty, local_def( id) ) ;
434
461
}
435
462
// Check that there's at least one field
436
463
if struct_def. fields. len( ) < 1 u {
@@ -455,10 +482,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
455
482
* it. ident, it. id, rp} ;
456
483
let self_ty = ccx. to_ty ( rscope:: type_rscope ( rp) , ty) ;
457
484
for ms. each |m| {
458
- let self_info = { self_ty: self_ty,
459
- def_id: local_def( it. id) ,
460
- explicit_self: m. self_ty. node } ;
461
- check_method( ccx, m, self_info)
485
+ check_method( ccx, m, self_ty, local_def( it. id) ) ;
462
486
}
463
487
}
464
488
ast:: item_trait ( _, _, trait_methods) => {
@@ -469,10 +493,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
469
493
// bodies to check.
470
494
}
471
495
provided( m) => {
472
- let self_info = { self_ty: ty:: mk_self( ccx. tcx) ,
473
- def_id: local_def( it. id) ,
474
- explicit_self: m. self_ty. node} ;
475
- check_method( ccx, m, self_info) ;
496
+ check_method ( ccx, m, ty:: mk_self ( ccx. tcx ) , local_def ( it. id ) ) ;
476
497
}
477
498
}
478
499
}
@@ -1204,7 +1225,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
1204
1225
1205
1226
fcx. write_ty( expr. id, fty) ;
1206
1227
1207
- check_fn( fcx. ccx, fcx . self_info , & fn_ty, decl, body,
1228
+ check_fn( fcx. ccx, none , & fn_ty, decl, body,
1208
1229
is_loop_body, some( fcx) ) ;
1209
1230
}
1210
1231
@@ -2247,29 +2268,12 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
2247
2268
ty_param_bounds_and_ty {
2248
2269
2249
2270
match defn {
2250
- ast::def_arg(nid, _) => {
2271
+ ast::def_arg(nid, _) | ast::def_local(nid, _) |
2272
+ ast::def_self(nid) | ast::def_binding(nid, _) => {
2251
2273
assert (fcx.locals.contains_key(nid));
2252
2274
let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, nid));
2253
2275
return no_params(typ);
2254
2276
}
2255
- ast::def_local(nid, _) => {
2256
- assert (fcx.locals.contains_key(nid));
2257
- let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, nid));
2258
- return no_params(typ);
2259
- }
2260
- ast::def_self(_) => {
2261
- match fcx.self_info {
2262
- some(self_info) => {
2263
- let self_region = fcx.in_scope_regions.find(ty::br_self);
2264
- return no_params(method::transform_self_type_for_method(
2265
- fcx.tcx(), self_region,
2266
- self_info.self_ty, self_info.explicit_self));
2267
- }
2268
- none => {
2269
- fcx.ccx.tcx.sess.span_bug(sp, ~" def_self with no self_info");
2270
- }
2271
- }
2272
- }
2273
2277
ast::def_fn(id, ast::extern_fn) => {
2274
2278
// extern functions are just u8 pointers
2275
2279
return {
@@ -2296,20 +2300,15 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
2296
2300
ast::def_class(id, _) => {
2297
2301
return ty::lookup_item_type(fcx.ccx.tcx, id);
2298
2302
}
2299
- ast::def_binding(nid, _) => {
2300
- assert (fcx.locals.contains_key(nid));
2301
- let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, nid));
2302
- return no_params(typ);
2303
- }
2304
- ast::def_ty(_) | ast::def_prim_ty(_) => {
2305
- fcx.ccx.tcx.sess.span_fatal(sp, ~" expected value but found type ");
2306
- }
2307
2303
ast::def_upvar(_, inner, _, _) => {
2308
2304
return ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
2309
2305
}
2310
2306
ast::def_ty_param(did, n) => {
2311
2307
return no_params(ty::mk_param(fcx.ccx.tcx, n, did));
2312
2308
}
2309
+ ast::def_ty(_) | ast::def_prim_ty(_) => {
2310
+ fcx.ccx.tcx.sess.span_fatal(sp, ~" expected value but found type ");
2311
+ }
2313
2312
ast::def_mod(*) | ast::def_foreign_mod(*) => {
2314
2313
fcx.ccx.tcx.sess.span_fatal(sp, ~" expected value but found module");
2315
2314
}
0 commit comments