@@ -416,9 +416,13 @@ pub struct DetermineRpCtxt {
416
416
item_id : ast:: node_id ,
417
417
418
418
// true when we are within an item but not within a method.
419
- // see long discussion on region_is_relevant()
419
+ // see long discussion on region_is_relevant().
420
420
anon_implies_rp : bool ,
421
421
422
+ // true when we are not within an &self method.
423
+ // see long discussion on region_is_relevant().
424
+ self_implies_rp : bool ,
425
+
422
426
// encodes the context of the current type; invariant if
423
427
// mutable, covariant otherwise
424
428
ambient_variance : region_variance ,
@@ -458,14 +462,14 @@ pub fn add_variance(+ambient_variance: region_variance,
458
462
}
459
463
460
464
pub impl DetermineRpCtxt {
461
- fn add_variance ( @ mut self , variance : region_variance ) -> region_variance {
465
+ fn add_variance ( & self , variance : region_variance ) -> region_variance {
462
466
add_variance ( self . ambient_variance , variance)
463
467
}
464
468
465
469
/// Records that item `id` is region-parameterized with the
466
470
/// variance `variance`. If `id` was already parameterized, then
467
471
/// the new variance is joined with the old variance.
468
- fn add_rp ( @ mut self , id : ast:: node_id , variance : region_variance ) {
472
+ fn add_rp ( & mut self , id : ast:: node_id , variance : region_variance ) {
469
473
assert id != 0 ;
470
474
let old_variance = self . region_paramd_items . find ( & id) ;
471
475
let joined_variance = match old_variance {
@@ -490,7 +494,7 @@ pub impl DetermineRpCtxt {
490
494
/// `from`. Put another way, it indicates that the current item
491
495
/// contains a value of type `from`, so if `from` is
492
496
/// region-parameterized, so is the current item.
493
- fn add_dep ( @ mut self , from : ast:: node_id ) {
497
+ fn add_dep ( & mut self , from : ast:: node_id ) {
494
498
debug ! ( "add dependency from %d -> %d (%s -> %s) with variance %?" ,
495
499
from, self . item_id,
496
500
ast_map:: node_id_to_str( self . ast_map, from,
@@ -515,42 +519,46 @@ pub impl DetermineRpCtxt {
515
519
}
516
520
517
521
// Determines whether a reference to a region that appears in the
518
- // AST implies that the enclosing type is region-parameterized.
519
- //
520
- // This point is subtle. Here are four examples to make it more
522
+ // AST implies that the enclosing type is region-parameterized (RP).
523
+ // This point is subtle. Here are some examples to make it more
521
524
// concrete.
522
525
//
523
526
// 1. impl foo for &int { ... }
524
527
// 2. impl foo for &self/int { ... }
525
- // 3. impl foo for bar { fn m() -> &self/int { ... } }
526
- // 4. impl foo for bar { fn m() -> &int { ... } }
528
+ // 3. impl foo for bar { fn m(@self) -> &self/int { ... } }
529
+ // 4. impl foo for bar { fn m(&self) -> &self/int { ... } }
530
+ // 5. impl foo for bar { fn m(&self) -> &int { ... } }
527
531
//
528
532
// In case 1, the anonymous region is being referenced,
529
533
// but it appears in a context where the anonymous region
530
- // resolves to self, so the impl foo is region-parameterized .
534
+ // resolves to self, so the impl foo is RP .
531
535
//
532
536
// In case 2, the self parameter is written explicitly.
533
537
//
534
- // In case 3, the method refers to self, so that implies that the
535
- // impl must be region parameterized. (If the type bar is not
536
- // region parameterized, that is an error, because the self region
537
- // is effectively unconstrained, but that is detected elsewhere).
538
+ // In case 3, the method refers to the region `self`, so that
539
+ // implies that the impl must be region parameterized. (If the
540
+ // type bar is not region parameterized, that is an error, because
541
+ // the self region is effectively unconstrained, but that is
542
+ // detected elsewhere).
543
+ //
544
+ // In case 4, the method refers to the region `self`, but the
545
+ // `self` region is bound by the `&self` receiver, and so this
546
+ // does not require that `bar` be RP.
538
547
//
539
- // In case 4 , the anonymous region is referenced, but it
548
+ // In case 5 , the anonymous region is referenced, but it
540
549
// bound by the method, so it does not refer to self. This impl
541
550
// need not be region parameterized.
542
551
//
543
- // So the rules basically are: the `self` region always implies
544
- // that the enclosing type is region parameterized. The anonymous
545
- // region also does, unless it appears within a method, in which
546
- // case it is bound. We handle this by setting a flag
547
- // (anon_implies_rp) to true when we enter an item and setting
548
- // that flag to false when we enter a method.
549
- fn region_is_relevant ( @mut self , r : @ast:: region ) -> bool {
552
+ // Normally, & or &self implies that the enclosing item is RP.
553
+ // However, within a function, & is always bound. Within a method
554
+ // with &self type, &self is also bound. We detect those last two
555
+ // cases via flags (anon_implies_rp and self_implies_rp) that are
556
+ // true when the anon or self region implies RP.
557
+ fn region_is_relevant ( & self , r : @ast:: region ) -> bool {
550
558
match r. node {
551
559
ast:: re_static => false ,
552
560
ast:: re_anon => self . anon_implies_rp ,
553
- ast:: re_self => true ,
561
+ ast:: re_self => self . self_implies_rp ,
554
562
ast:: re_named( _) => false
555
563
}
556
564
}
@@ -561,7 +569,7 @@ pub impl DetermineRpCtxt {
561
569
//
562
570
// If the region is explicitly specified, then we follows the
563
571
// normal rules.
564
- fn opt_region_is_relevant ( @ mut self ,
572
+ fn opt_region_is_relevant ( & self ,
565
573
opt_r : Option < @ast:: region > )
566
574
-> bool {
567
575
debug ! ( "opt_region_is_relevant: %? (anon_implies_rp=%b)" ,
@@ -575,16 +583,23 @@ pub impl DetermineRpCtxt {
575
583
fn with ( @mut self ,
576
584
item_id : ast:: node_id ,
577
585
anon_implies_rp : bool ,
586
+ self_implies_rp : bool ,
578
587
f : & fn ( ) ) {
579
588
let old_item_id = self . item_id ;
580
589
let old_anon_implies_rp = self . anon_implies_rp ;
590
+ let old_self_implies_rp = self . self_implies_rp ;
581
591
self . item_id = item_id;
582
592
self . anon_implies_rp = anon_implies_rp;
583
- debug ! ( "with_item_id(%d, %b)" , item_id, anon_implies_rp) ;
593
+ self . self_implies_rp = self_implies_rp;
594
+ debug ! ( "with_item_id(%d, %b, %b)" ,
595
+ item_id,
596
+ anon_implies_rp,
597
+ self_implies_rp) ;
584
598
let _i = :: util:: common:: indenter ( ) ;
585
599
f ( ) ;
586
600
self . item_id = old_item_id;
587
601
self . anon_implies_rp = old_anon_implies_rp;
602
+ self . self_implies_rp = old_self_implies_rp;
588
603
}
589
604
590
605
fn with_ambient_variance ( @mut self , variance : region_variance , f : & fn ( ) ) {
@@ -598,7 +613,7 @@ pub impl DetermineRpCtxt {
598
613
pub fn determine_rp_in_item ( item : @ast:: item ,
599
614
& & cx: @mut DetermineRpCtxt ,
600
615
visitor : visit:: vt < @mut DetermineRpCtxt > ) {
601
- do cx. with ( item. id , true ) {
616
+ do cx. with ( item. id , true , true ) {
602
617
visit:: visit_item ( item, cx, visitor) ;
603
618
}
604
619
}
@@ -610,7 +625,12 @@ pub fn determine_rp_in_fn(fk: &visit::fn_kind,
610
625
_: ast:: node_id ,
611
626
& & cx: @mut DetermineRpCtxt ,
612
627
visitor : visit:: vt < @mut DetermineRpCtxt > ) {
613
- do cx. with ( cx. item_id , false ) {
628
+ let self_implies_rp = match fk {
629
+ & visit:: fk_method( _, _, m) => !m. self_ty . node . is_borrowed ( ) ,
630
+ _ => true
631
+ } ;
632
+
633
+ do cx. with ( cx. item_id , false , self_implies_rp) {
614
634
do cx. with_ambient_variance ( rv_contravariant) {
615
635
for decl. inputs. each |a| {
616
636
( visitor. visit_ty ) ( a. ty , cx, visitor) ;
@@ -626,7 +646,7 @@ pub fn determine_rp_in_fn(fk: &visit::fn_kind,
626
646
pub fn determine_rp_in_ty_method ( ty_m : & ast:: ty_method ,
627
647
& & cx: @mut DetermineRpCtxt ,
628
648
visitor : visit:: vt < @mut DetermineRpCtxt > ) {
629
- do cx. with ( cx. item_id , false ) {
649
+ do cx. with ( cx. item_id , false , !ty_m . self_ty . node . is_borrowed ( ) ) {
630
650
visit:: visit_ty_method ( ty_m, cx, visitor) ;
631
651
}
632
652
}
@@ -735,7 +755,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
735
755
ast:: ty_bare_fn( @ast:: TyBareFn { decl : ref decl, _} ) => {
736
756
// fn() binds the & region, so do not consider &T types that
737
757
// appear *inside* a fn() type to affect the enclosing item:
738
- do cx. with ( cx. item_id , false ) {
758
+ do cx. with ( cx. item_id , false , true ) {
739
759
// parameters are contravariant
740
760
do cx. with_ambient_variance ( rv_contravariant) {
741
761
for decl. inputs. each |a| {
@@ -796,6 +816,7 @@ pub fn determine_rp_in_crate(sess: Session,
796
816
worklist : ~[ ] ,
797
817
item_id : 0 ,
798
818
anon_implies_rp : false ,
819
+ self_implies_rp : true ,
799
820
ambient_variance : rv_covariant
800
821
} ;
801
822
0 commit comments