@@ -11,13 +11,21 @@ import syntax::ast_map::node_id_to_str;
11
11
import syntax:: ast_util:: { dummy_sp, new_def_hash} ;
12
12
import dvec :: { DVec , dvec} ;
13
13
14
+ enum method_lookup_mode {
15
+ subtyping_mode,
16
+ assignability_mode,
17
+ immutable_reference_mode,
18
+ mutable_reference_mode
19
+ }
20
+
14
21
type candidate = {
15
- self_ty : ty:: t , // type of a in a.b()
16
- self_substs : ty:: substs , // values for any tvars def'd on the class
17
- rcvr_ty : ty:: t , // type of receiver in the method def
18
- n_tps_m : uint, // number of tvars defined on the method
19
- fty : ty:: t , // type of the method
20
- entry : method_map_entry
22
+ self_ty : ty:: t , // type of a in a.b()
23
+ self_substs : ty:: substs , // values for any tvars def'd on the class
24
+ rcvr_ty : ty:: t , // type of receiver in the method def
25
+ n_tps_m : uint, // number of tvars defined on the method
26
+ fty : ty:: t , // type of the method
27
+ entry : method_map_entry ,
28
+ mode : method_lookup_mode // the mode we used
21
29
} ;
22
30
23
31
fn transform_self_type_for_method
@@ -141,16 +149,33 @@ class lookup {
141
149
// it.
142
150
if self . candidates . len ( ) > 0 u { break ; }
143
151
144
- // Look for inherent methods.
152
+ // Look for inherent and extension methods, using subtyping .
145
153
self . add_inherent_and_extension_candidates
146
- ( optional_inherent_methods, false ) ;
154
+ ( optional_inherent_methods, subtyping_mode ) ;
147
155
148
156
// if we found anything, stop before trying borrows
149
157
if self . candidates . len ( ) > 0 u { break ; }
150
158
151
- // Again, look for inherent methods.
159
+ // Again, look for inherent and extension methods, this time using
160
+ // assignability.
161
+ self . add_inherent_and_extension_candidates
162
+ ( optional_inherent_methods, assignability_mode) ;
163
+
164
+ // If we found anything, stop before trying auto-ref.
165
+ if self . candidates . len ( ) > 0 u { break ; }
166
+
167
+ // Now look for inherent and extension methods, this time using an
168
+ // immutable reference.
152
169
self . add_inherent_and_extension_candidates
153
- ( optional_inherent_methods, true ) ;
170
+ ( optional_inherent_methods, immutable_reference_mode) ;
171
+
172
+ // if we found anything, stop before attempting auto-deref.
173
+ if self . candidates . len ( ) > 0 u { break ; }
174
+
175
+ // Now look for inherent and extension methods, this time using a
176
+ // mutable reference.
177
+ self . add_inherent_and_extension_candidates
178
+ ( optional_inherent_methods, mutable_reference_mode) ;
154
179
155
180
// if we found anything, stop before attempting auto-deref.
156
181
if self . candidates . len ( ) > 0 u { break ; }
@@ -362,9 +387,8 @@ class lookup {
362
387
}
363
388
364
389
// Returns true if any were added and false otherwise.
365
- fn add_candidates_from_impl ( im : @resolve3:: Impl ,
366
- use_assignability : bool ) -> bool {
367
-
390
+ fn add_candidates_from_impl ( im : @resolve3:: Impl , mode : method_lookup_mode )
391
+ -> bool {
368
392
let mut added_any = false ;
369
393
370
394
// Check whether this impl has a method with the right name.
@@ -382,15 +406,33 @@ class lookup {
382
406
self . tcx ( ) , impl_substs. self_r ,
383
407
impl_ty, m. self_type ) ;
384
408
385
- // Depending on our argument, we find potential
386
- // matches either by checking subtypability or
387
- // type assignability. Collect the matches.
388
- let matches = if use_assignability {
389
- self . fcx . can_mk_assignty ( self . self_expr , self . borrow_lb ,
390
- self . self_ty , impl_ty)
391
- } else {
392
- self . fcx . can_mk_subty ( self . self_ty , impl_ty)
393
- } ;
409
+ // Depending on our argument, we find potential matches by
410
+ // checking subtypability, type assignability, or reference
411
+ // subtypability. Collect the matches.
412
+ let matches;
413
+ match mode {
414
+ subtyping_mode =>
415
+ matches = self . fcx . can_mk_subty ( self . self_ty , impl_ty) ,
416
+ assignability_mode =>
417
+ matches = self . fcx . can_mk_assignty ( self . self_expr ,
418
+ self . borrow_lb ,
419
+ self . self_ty ,
420
+ impl_ty) ,
421
+ immutable_reference_mode => {
422
+ let region = self . fcx . infcx . next_region_var_with_scope_lb
423
+ ( self . self_expr . id ) ;
424
+ let tm = { ty: self . self_ty , mutbl: ast:: m_imm } ;
425
+ let ref_ty = ty:: mk_rptr ( self . tcx ( ) , region, tm) ;
426
+ matches = self . fcx . can_mk_subty ( ref_ty, impl_ty) ;
427
+ }
428
+ mutable_reference_mode => {
429
+ let region = self . fcx . infcx . next_region_var_with_scope_lb
430
+ ( self . self_expr . id ) ;
431
+ let tm = { ty: self . self_ty , mutbl: ast:: m_mutbl } ;
432
+ let ref_ty = ty:: mk_rptr ( self . tcx ( ) , region, tm) ;
433
+ matches = self . fcx . can_mk_subty ( ref_ty, impl_ty) ;
434
+ }
435
+ }
394
436
debug ! { "matches = %?" , matches} ;
395
437
match matches {
396
438
result:: err( _) => { /* keep looking */ }
@@ -404,7 +446,8 @@ class lookup {
404
446
n_tps_m: m. n_tps ,
405
447
fty: fty,
406
448
entry : { derefs : self . derefs ,
407
- origin : method_static ( m. did ) } } ) ;
449
+ origin : method_static ( m. did ) } ,
450
+ mode: mode} ) ;
408
451
self . candidate_impls . insert ( im. did , ( ) ) ;
409
452
added_any = true ;
410
453
}
@@ -431,12 +474,13 @@ class lookup {
431
474
rcvr_ty: self . self_ty ,
432
475
n_tps_m : ( * m. tps ) . len ( ) ,
433
476
fty: fty,
434
- entry : { derefs : self . derefs , origin : origin} } ) ;
477
+ entry : { derefs : self . derefs , origin : origin} ,
478
+ mode: subtyping_mode} ) ;
435
479
}
436
480
437
481
fn add_inherent_and_extension_candidates ( optional_inherent_methods :
438
482
option < @DVec < @Impl > > ,
439
- use_assignability : bool ) {
483
+ mode : method_lookup_mode ) {
440
484
441
485
// Add inherent methods.
442
486
match optional_inherent_methods {
@@ -451,8 +495,7 @@ class lookup {
451
495
adding candidates from impl: %s",
452
496
node_id_to_str( self . tcx( ) . items,
453
497
implementation. did. node) } ;
454
- self . add_candidates_from_impl ( implementation,
455
- use_assignability) ;
498
+ self . add_candidates_from_impl ( implementation, mode) ;
456
499
}
457
500
}
458
501
}
@@ -479,8 +522,7 @@ class lookup {
479
522
candidates) adding impl %s",
480
523
self . def_id_to_str
481
524
( implementation. did) } ;
482
- self . add_candidates_from_impl
483
- ( implementation, use_assignability) ;
525
+ self . add_candidates_from_impl ( implementation, mode) ;
484
526
}
485
527
}
486
528
}
@@ -505,19 +547,41 @@ class lookup {
505
547
self . fcx. infcx. ty_to_str( cand. fty) ,
506
548
cand. entry} ;
507
549
508
- // Make the actual receiver type (cand.self_ty) assignable to the
509
- // required receiver type (cand.rcvr_ty). If this method is not
510
- // from an impl, this'll basically be a no-nop.
511
- match self . fcx . mk_assignty ( self . self_expr , self . borrow_lb ,
512
- cand. self_ty , cand. rcvr_ty ) {
513
- result:: ok( _) => ( ) ,
514
- result:: err( _) => {
515
- self . tcx ( ) . sess . span_bug (
516
- self . expr . span ,
517
- fmt ! { "%s was assignable to %s but now is not?" ,
518
- self . fcx. infcx. ty_to_str( cand. self_ty) ,
519
- self . fcx. infcx. ty_to_str( cand. rcvr_ty) } ) ;
520
- }
550
+ match cand. mode {
551
+ subtyping_mode | assignability_mode => {
552
+ // Make the actual receiver type (cand.self_ty) assignable to
553
+ // the required receiver type (cand.rcvr_ty). If this method
554
+ // is not from an impl, this'll basically be a no-nop.
555
+ match self . fcx . mk_assignty ( self . self_expr , self . borrow_lb ,
556
+ cand. self_ty , cand. rcvr_ty ) {
557
+ result:: ok( _) => ( ) ,
558
+ result:: err( _) => {
559
+ self . tcx ( ) . sess . span_bug (
560
+ self . expr . span ,
561
+ fmt ! { "%s was assignable to %s but now is not?" ,
562
+ self . fcx. infcx. ty_to_str( cand. self_ty) ,
563
+ self . fcx. infcx. ty_to_str( cand. rcvr_ty) } ) ;
564
+ }
565
+ }
566
+ }
567
+ immutable_reference_mode => {
568
+ // Borrow as an immutable reference.
569
+ let region_var = self . fcx . infcx . next_region_var_with_scope_lb
570
+ ( self . self_expr . id ) ;
571
+ self . fcx . infcx . borrowings . push ( { expr_id: self . self_expr . id ,
572
+ span: self . self_expr . span ,
573
+ scope: region_var,
574
+ mutbl: ast:: m_imm} ) ;
575
+ }
576
+ mutable_reference_mode => {
577
+ // Borrow as a mutable reference.
578
+ let region_var = self . fcx . infcx . next_region_var_with_scope_lb
579
+ ( self . self_expr . id ) ;
580
+ self . fcx . infcx . borrowings . push ( { expr_id: self . self_expr . id ,
581
+ span: self . self_expr . span ,
582
+ scope: region_var,
583
+ mutbl: ast:: m_mutbl} ) ;
584
+ }
521
585
}
522
586
523
587
// Construct the full set of type parameters for the method,
@@ -546,7 +610,7 @@ class lookup {
546
610
let all_substs = { tps: vec:: append ( cand. self_substs . tps , m_substs)
547
611
with cand. self_substs } ;
548
612
549
- self . fcx . write_ty_substs ( self . node_id , cand. fty , all_substs) ;
613
+ self . fcx . write_ty_substs ( self . node_id , cand. fty , all_substs) ;
550
614
551
615
return cand. entry ;
552
616
}
0 commit comments