@@ -6519,17 +6519,20 @@ fn recv_val(&@block_ctxt cx, ValueRef to, &@ast::expr from, &ty::t unit_ty,
6519
6519
// itself.
6520
6520
fn trans_anon_obj( @block_ctxt bcx, & span sp, & ast:: anon_obj anon_obj,
6521
6521
& vec[ ast:: ty_param] ty_params, ast:: node_id oid,
6522
- ast:: node_id id ) -> result {
6522
+ ast:: node_id type_id ) -> result {
6523
6523
6524
6524
// Right now, we're assuming that anon objs don't take ty params, even
6525
6525
// though the AST supports it. It's nonsensical to write an expression
6526
6526
// like "obj[T](){ ... with ... }", since T is never instantiated;
6527
- // nevertheless, such an expression will parse. FIXME for the future:
6528
- // support typarams (issue #n) .
6527
+ // nevertheless, such an expression will parse. Idea for the future:
6528
+ // support typarams.
6529
6529
6530
6530
assert ( vec:: len( ty_params) == 0 u) ;
6531
6531
auto ccx = bcx. fcx. lcx. ccx;
6532
6532
6533
+ // Fields.
6534
+ // FIXME (part of issue #538): Where do we fill in the field *values* from
6535
+ // the outer object?
6533
6536
let vec[ ast:: anon_obj_field] additional_fields = [ ] ;
6534
6537
let vec[ result] additional_field_vals = [ ] ;
6535
6538
let vec[ ty:: t] additional_field_tys = [ ] ;
@@ -6544,63 +6547,86 @@ fn trans_anon_obj(@block_ctxt bcx, &span sp, &ast::anon_obj anon_obj,
6544
6547
}
6545
6548
}
6546
6549
6547
- // If with_obj (the object being extended) exists, translate it, producing
6548
- // a result.
6549
- let option:: t[ result] with_obj_val = none;
6550
- let ty:: t with_obj_ty = ty:: mk_type( ccx. tcx) ;
6551
- alt ( anon_obj. with_obj) {
6552
- case ( none) { }
6553
- case ( some( ?e) ) {
6554
- // Translating with_obj returns a ValueRef (pointer to a 2-word
6555
- // value) wrapped in a result.
6556
- with_obj_val = some[ result] ( trans_expr( bcx, e) ) ;
6557
- with_obj_ty = ty:: expr_ty( ccx. tcx, e) ;
6558
- }
6559
- }
6560
- // FIXME (part of issue #538): much of the following code is copypasta
6561
- // from trans_obj for translating the anonymous wrapper object.
6562
- // Eventually we might want to abstract this code out of trans_anon_obj
6563
- // and trans_obj.
6550
+ // Get the type of the eventual entire anonymous object, possibly with
6551
+ // extensions.
6552
+ auto outer_obj_ty = ty:: node_id_to_type( ccx. tcx, type_id) ;
6553
+ auto llouter_obj_ty = type_of( ccx, sp, outer_obj_ty) ;
6564
6554
6565
- auto self_ty = ty:: node_id_to_type( ccx. tcx, id) ;
6566
- auto llself_ty = type_of( ccx, sp, self_ty) ;
6567
6555
// Allocate the object that we're going to return. It's a two-word pair
6568
6556
// containing a vtable pointer and a body pointer.
6557
+ auto pair = alloca( bcx, llouter_obj_ty) ;
6569
6558
6570
- auto pair = alloca( bcx, llself_ty) ;
6571
6559
// Grab onto the first and second elements of the pair.
6572
6560
// abi::obj_field_vtbl and abi::obj_field_box simply specify words 0 and 1
6573
6561
// of 'pair'.
6574
-
6575
6562
auto pair_vtbl =
6576
6563
bcx. build. GEP ( pair, [ C_int ( 0 ) , C_int ( abi:: obj_field_vtbl) ] ) ;
6577
6564
auto pair_box =
6578
6565
bcx. build. GEP ( pair, [ C_int ( 0 ) , C_int ( abi:: obj_field_box) ] ) ;
6579
- // Make a vtable for the outer object. create_vtbl() wants an ast::_obj
6580
- // and all we have is an ast::anon_obj, so we need to roll our own.
6581
6566
6582
- fn anon_obj_field_to_obj_field( & ast:: anon_obj_field f) -> ast:: obj_field {
6567
+ // Create a vtable for the anonymous object.
6568
+
6569
+ // create_vtbl() wants an ast::_obj and all we have is an ast::anon_obj,
6570
+ // so we need to roll our own.
6571
+ fn anon_obj_field_to_obj_field( & ast:: anon_obj_field f)
6572
+ -> ast:: obj_field {
6583
6573
ret rec( mut =f. mut , ty=f. ty, ident=f. ident, id=f. id) ;
6584
6574
}
6585
6575
let ast:: _obj wrapper_obj = rec(
6586
- fields = vec:: map( anon_obj_field_to_obj_field, additional_fields) ,
6576
+ fields = vec:: map( anon_obj_field_to_obj_field,
6577
+ additional_fields) ,
6587
6578
methods = anon_obj. methods,
6588
6579
dtor = none[ @ast:: method] ) ;
6589
- auto vtbl = create_vtbl( bcx. fcx. lcx, llself_ty, self_ty, wrapper_obj,
6590
- ty_params) ;
6591
6580
6592
- bcx. build. Store ( vtbl, pair_vtbl) ;
6593
- // FIXME (part of issue #538): Where do we fill in the field *values* from
6594
- // the outer object?
6595
6581
6596
- // FIXME (part of issue #539): This vtable needs to contain "forwarding
6597
- // slots" for the methods that exist in the with_obj, as well. How do we
6598
- // do that?
6582
+ // If with_obj (the object being extended) exists, translate it, producing
6583
+ // a result.
6584
+ let option:: t[ result] with_obj_val = none;
6585
+ let ty:: t with_obj_ty = ty:: mk_type( ccx. tcx) ;
6586
+ let TypeRef llwith_obj_ty;
6587
+ auto vtbl;
6588
+ alt ( anon_obj. with_obj) {
6589
+ case ( none) {
6590
+ // If there's no with_obj -- that is, if we aren't extending our
6591
+ // object with any fields -- then we just pass the outer object to
6592
+ // create_vtbl(). This vtable won't need to have any forwarding
6593
+ // slots.
6594
+ vtbl = create_vtbl( bcx. fcx. lcx, llouter_obj_ty, outer_obj_ty,
6595
+ wrapper_obj, ty_params, none) ;
6596
+ }
6597
+ case ( some( ?e) ) {
6598
+ // Translating with_obj returns a ValueRef (pointer to a 2-word
6599
+ // value) wrapped in a result.
6600
+ with_obj_val = some[ result] ( trans_expr( bcx, e) ) ;
6601
+
6602
+ // TODO: What makes more sense to get the type of an expr --
6603
+ // calling ty::expr_ty(ccx.tcx, e) on it or calling
6604
+ // ty::node_id_to_type(ccx.tcx, id) on its id?
6605
+ with_obj_ty = ty:: expr_ty( ccx. tcx, e) ;
6606
+ //with_obj_ty = ty::node_id_to_type(ccx.tcx, e.id);
6607
+
6608
+ llwith_obj_ty = type_of( ccx, sp, with_obj_ty) ;
6609
+
6610
+ // If there's a with_obj, we pass it as the main argument to
6611
+ // create_vtbl(), but we're also passing along the additional
6612
+ // methods as the last argument. Part of what create_vtbl() will
6613
+ // do is take the set difference of methods defined on the
6614
+ // original and methods being added. For every method defined on
6615
+ // the original that does *not* have one with a matching name and
6616
+ // type being added, we'll need to create a forwarding slot. And,
6617
+ // of course, we need to create a normal vtable entry for every
6618
+ // method being added.
6619
+ vtbl = create_vtbl( bcx. fcx. lcx, llwith_obj_ty, with_obj_ty,
6620
+ wrapper_obj, ty_params,
6621
+ some( anon_obj. methods) ) ;
6622
+ }
6623
+ }
6624
+
6625
+ bcx. build. Store ( vtbl, pair_vtbl) ;
6599
6626
6600
6627
// Next we have to take care of the other half of the pair we're
6601
6628
// returning: a boxed (reference-counted) tuple containing a tydesc,
6602
6629
// typarams, fields, and a pointer to our with_obj.
6603
-
6604
6630
let TypeRef llbox_ty = T_opaque_obj_ptr ( ccx. tn) ;
6605
6631
6606
6632
if ( vec:: len[ ast:: ty_param] ( ty_params) == 0 u &&
@@ -7330,11 +7356,13 @@ fn trans_fn(@local_ctxt cx, &span sp, &ast::_fn f, ValueRef llfndecl,
7330
7356
finish_fn( fcx, lltop) ;
7331
7357
}
7332
7358
7333
-
7334
7359
// Create a vtable for an object being translated. Returns a pointer into
7335
7360
// read-only memory.
7336
7361
fn create_vtbl( @local_ctxt cx, TypeRef llself_ty, ty:: t self_ty,
7337
- & ast:: _obj ob, & vec[ ast:: ty_param] ty_params) -> ValueRef {
7362
+ & ast:: _obj ob, & vec[ ast:: ty_param] ty_params,
7363
+ option:: t[ vec[ @ast:: method] ] additional_methods) -> ValueRef {
7364
+ // FIXME (issue #539): Implement forwarding slots.
7365
+
7338
7366
auto dtor = C_null ( T_ptr ( T_i8 ( ) ) ) ;
7339
7367
alt ( ob. dtor) {
7340
7368
case ( some( ?d) ) {
@@ -7364,10 +7392,10 @@ fn create_vtbl(@local_ctxt cx, TypeRef llself_ty, ty::t self_ty,
7364
7392
let str s = mangle_internal_name_by_path( mcx. ccx, mcx. path) ;
7365
7393
let ValueRef llfn =
7366
7394
decl_internal_fastcall_fn( cx. ccx. llmod, s, llfnty) ;
7367
- // Every method on an object gets its def_id inserted into the
7395
+
7396
+ // Every method on an object gets its node_id inserted into the
7368
7397
// crate-wide item_ids map, together with the ValueRef that points to
7369
7398
// where that method's definition will be in the executable.
7370
-
7371
7399
cx. ccx. item_ids. insert( m. node. id, llfn) ;
7372
7400
cx. ccx. item_symbols. insert( m. node. id, s) ;
7373
7401
trans_fn( mcx, m. span, m. node. meth, llfn,
@@ -7459,7 +7487,7 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::node_id ctor_id,
7459
7487
// creating and will contain ValueRefs for all of this object's methods.
7460
7488
// create_vtbl returns a pointer to the vtable, which we store.
7461
7489
7462
- auto vtbl = create_vtbl( cx, llself_ty, self_ty, ob, ty_params) ;
7490
+ auto vtbl = create_vtbl( cx, llself_ty, self_ty, ob, ty_params, none ) ;
7463
7491
bcx. build. Store ( vtbl, pair_vtbl) ;
7464
7492
// Next we have to take care of the other half of the pair we're
7465
7493
// returning: a boxed (reference-counted) tuple containing a tydesc,
0 commit comments