@@ -416,9 +416,13 @@ pub struct DetermineRpCtxt {
416416 item_id : ast:: node_id ,
417417
418418 // 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().
420420 anon_implies_rp : bool ,
421421
422+ // true when we are not within an &self method.
423+ // see long discussion on region_is_relevant().
424+ self_implies_rp : bool ,
425+
422426 // encodes the context of the current type; invariant if
423427 // mutable, covariant otherwise
424428 ambient_variance : region_variance ,
@@ -458,14 +462,14 @@ pub fn add_variance(+ambient_variance: region_variance,
458462}
459463
460464pub impl DetermineRpCtxt {
461- fn add_variance ( @ mut self , variance : region_variance ) -> region_variance {
465+ fn add_variance ( & self , variance : region_variance ) -> region_variance {
462466 add_variance ( self . ambient_variance , variance)
463467 }
464468
465469 /// Records that item `id` is region-parameterized with the
466470 /// variance `variance`. If `id` was already parameterized, then
467471 /// 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 ) {
469473 assert id != 0 ;
470474 let old_variance = self . region_paramd_items . find ( & id) ;
471475 let joined_variance = match old_variance {
@@ -490,7 +494,7 @@ pub impl DetermineRpCtxt {
490494 /// `from`. Put another way, it indicates that the current item
491495 /// contains a value of type `from`, so if `from` is
492496 /// 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 ) {
494498 debug ! ( "add dependency from %d -> %d (%s -> %s) with variance %?" ,
495499 from, self . item_id,
496500 ast_map:: node_id_to_str( self . ast_map, from,
@@ -515,42 +519,46 @@ pub impl DetermineRpCtxt {
515519 }
516520
517521 // 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
521524 // concrete.
522525 //
523526 // 1. impl foo for &int { ... }
524527 // 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 { ... } }
527531 //
528532 // In case 1, the anonymous region is being referenced,
529533 // 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 .
531535 //
532536 // In case 2, the self parameter is written explicitly.
533537 //
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.
538547 //
539- // In case 4 , the anonymous region is referenced, but it
548+ // In case 5 , the anonymous region is referenced, but it
540549 // bound by the method, so it does not refer to self. This impl
541550 // need not be region parameterized.
542551 //
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 {
550558 match r. node {
551559 ast:: re_static => false ,
552560 ast:: re_anon => self . anon_implies_rp ,
553- ast:: re_self => true ,
561+ ast:: re_self => self . self_implies_rp ,
554562 ast:: re_named( _) => false
555563 }
556564 }
@@ -561,7 +569,7 @@ pub impl DetermineRpCtxt {
561569 //
562570 // If the region is explicitly specified, then we follows the
563571 // normal rules.
564- fn opt_region_is_relevant ( @ mut self ,
572+ fn opt_region_is_relevant ( & self ,
565573 opt_r : Option < @ast:: region > )
566574 -> bool {
567575 debug ! ( "opt_region_is_relevant: %? (anon_implies_rp=%b)" ,
@@ -575,16 +583,23 @@ pub impl DetermineRpCtxt {
575583 fn with ( @mut self ,
576584 item_id : ast:: node_id ,
577585 anon_implies_rp : bool ,
586+ self_implies_rp : bool ,
578587 f : & fn ( ) ) {
579588 let old_item_id = self . item_id ;
580589 let old_anon_implies_rp = self . anon_implies_rp ;
590+ let old_self_implies_rp = self . self_implies_rp ;
581591 self . item_id = item_id;
582592 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) ;
584598 let _i = :: util:: common:: indenter ( ) ;
585599 f ( ) ;
586600 self . item_id = old_item_id;
587601 self . anon_implies_rp = old_anon_implies_rp;
602+ self . self_implies_rp = old_self_implies_rp;
588603 }
589604
590605 fn with_ambient_variance ( @mut self , variance : region_variance , f : & fn ( ) ) {
@@ -598,7 +613,7 @@ pub impl DetermineRpCtxt {
598613pub fn determine_rp_in_item ( item : @ast:: item ,
599614 & & cx: @mut DetermineRpCtxt ,
600615 visitor : visit:: vt < @mut DetermineRpCtxt > ) {
601- do cx. with ( item. id , true ) {
616+ do cx. with ( item. id , true , true ) {
602617 visit:: visit_item ( item, cx, visitor) ;
603618 }
604619}
@@ -610,7 +625,12 @@ pub fn determine_rp_in_fn(fk: &visit::fn_kind,
610625 _: ast:: node_id ,
611626 & & cx: @mut DetermineRpCtxt ,
612627 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) {
614634 do cx. with_ambient_variance ( rv_contravariant) {
615635 for decl. inputs. each |a| {
616636 ( visitor. visit_ty ) ( a. ty , cx, visitor) ;
@@ -626,7 +646,7 @@ pub fn determine_rp_in_fn(fk: &visit::fn_kind,
626646pub fn determine_rp_in_ty_method ( ty_m : & ast:: ty_method ,
627647 & & cx: @mut DetermineRpCtxt ,
628648 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 ( ) ) {
630650 visit:: visit_ty_method ( ty_m, cx, visitor) ;
631651 }
632652}
@@ -735,7 +755,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
735755 ast:: ty_bare_fn( @ast:: TyBareFn { decl : ref decl, _} ) => {
736756 // fn() binds the & region, so do not consider &T types that
737757 // 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 ) {
739759 // parameters are contravariant
740760 do cx. with_ambient_variance ( rv_contravariant) {
741761 for decl. inputs. each |a| {
@@ -796,6 +816,7 @@ pub fn determine_rp_in_crate(sess: Session,
796816 worklist : ~[ ] ,
797817 item_id : 0 ,
798818 anon_implies_rp : false ,
819+ self_implies_rp : true ,
799820 ambient_variance : rv_covariant
800821 } ;
801822
0 commit comments