@@ -544,7 +544,9 @@ impl<'tcx> Tree {
544544 ) -> InterpResult < ' tcx > {
545545 self . perform_access (
546546 prov,
547- Some ( ( access_range, AccessKind :: Write , diagnostics:: AccessCause :: Dealloc ) ) ,
547+ access_range,
548+ AccessKind :: Write ,
549+ diagnostics:: AccessCause :: Dealloc ,
548550 global,
549551 alloc_id,
550552 span,
@@ -620,14 +622,6 @@ impl<'tcx> Tree {
620622 /// to each location of the first component of `access_range_and_kind`,
621623 /// on every tag of the allocation.
622624 ///
623- /// If `access_range_and_kind` is `None`, this is interpreted as the special
624- /// access that is applied on protector release:
625- /// - the access will be applied only to accessed locations of the allocation,
626- /// - it will not be visible to children,
627- /// - it will be recorded as a `FnExit` diagnostic access
628- /// - and it will be a read except if the location is `Unique`, i.e. has been written to,
629- /// in which case it will be a write.
630- ///
631625 /// `LocationState::perform_access` will take care of raising transition
632626 /// errors and updating the `accessed` status of each location,
633627 /// this traversal adds to that:
@@ -637,7 +631,9 @@ impl<'tcx> Tree {
637631 pub fn perform_access (
638632 & mut self ,
639633 prov : ProvenanceExtra ,
640- access_range_and_kind : Option < ( AllocRange , AccessKind , diagnostics:: AccessCause ) > ,
634+ access_range : AllocRange ,
635+ access_kind : AccessKind ,
636+ access_cause : AccessCause , // diagnostics
641637 global : & GlobalState ,
642638 alloc_id : AllocId , // diagnostics
643639 span : Span , // diagnostics
@@ -651,61 +647,75 @@ impl<'tcx> Tree {
651647 ProvenanceExtra :: Concrete ( tag) => Some ( self . tag_mapping . get ( & tag) . unwrap ( ) ) ,
652648 ProvenanceExtra :: Wildcard => None ,
653649 } ;
654- if let Some ( ( access_range, access_kind, access_cause) ) = access_range_and_kind {
655- // Default branch: this is a "normal" access through a known range.
656- // We iterate over affected locations and traverse the tree for each of them.
657- for ( loc_range, loc) in self . locations . iter_mut ( access_range. start , access_range. size ) {
650+ // We iterate over affected locations and traverse the tree for each of them.
651+ for ( loc_range, loc) in self . locations . iter_mut ( access_range. start , access_range. size ) {
652+ loc. perform_access (
653+ self . roots . iter ( ) . copied ( ) ,
654+ & mut self . nodes ,
655+ source_idx,
656+ loc_range,
657+ Some ( access_range) ,
658+ access_kind,
659+ access_cause,
660+ global,
661+ alloc_id,
662+ span,
663+ ChildrenVisitMode :: VisitChildrenOfAccessed ,
664+ ) ?;
665+ }
666+ interp_ok ( ( ) )
667+ }
668+ /// This is the special access that is applied on protector release:
669+ /// - the access will be applied only to accessed locations of the allocation,
670+ /// - it will not be visible to children,
671+ /// - it will be recorded as a `FnExit` diagnostic access
672+ /// - and it will be a read except if the location is `Unique`, i.e. has been written to,
673+ /// in which case it will be a write.
674+ /// - otherwise identical to `Tree::perform_access`
675+ pub fn perform_protector_end_access (
676+ & mut self ,
677+ tag : BorTag ,
678+ global : & GlobalState ,
679+ alloc_id : AllocId , // diagnostics
680+ span : Span , // diagnostics
681+ ) -> InterpResult < ' tcx > {
682+ #[ cfg( feature = "expensive-consistency-checks" ) ]
683+ if self . roots . len ( ) > 1 {
684+ self . verify_wildcard_consistency ( global) ;
685+ }
686+
687+ let source_idx = self . tag_mapping . get ( & tag) . unwrap ( ) ;
688+
689+ // This is a special access through the entire allocation.
690+ // It actually only affects `accessed` locations, so we need
691+ // to filter on those before initiating the traversal.
692+ //
693+ // In addition this implicit access should not be visible to children,
694+ // thus the use of `traverse_nonchildren`.
695+ // See the test case `returned_mut_is_usable` from
696+ // `tests/pass/tree_borrows/tree-borrows.rs` for an example of
697+ // why this is important.
698+ for ( loc_range, loc) in self . locations . iter_mut_all ( ) {
699+ // Only visit accessed permissions
700+ if let Some ( p) = loc. perms . get ( source_idx)
701+ && let Some ( access_kind) = p. permission . protector_end_access ( )
702+ && p. accessed
703+ {
704+ let access_cause = diagnostics:: AccessCause :: FnExit ( access_kind) ;
658705 loc. perform_access (
659706 self . roots . iter ( ) . copied ( ) ,
660707 & mut self . nodes ,
661- source_idx,
708+ Some ( source_idx) ,
662709 loc_range,
663- Some ( access_range ) ,
710+ None ,
664711 access_kind,
665712 access_cause,
666713 global,
667714 alloc_id,
668715 span,
669- ChildrenVisitMode :: VisitChildrenOfAccessed ,
716+ ChildrenVisitMode :: SkipChildrenOfAccessed ,
670717 ) ?;
671718 }
672- } else {
673- // This is a special access through the entire allocation.
674- // It actually only affects `accessed` locations, so we need
675- // to filter on those before initiating the traversal.
676- //
677- // In addition this implicit access should not be visible to children,
678- // thus the use of `traverse_nonchildren`.
679- // See the test case `returned_mut_is_usable` from
680- // `tests/pass/tree_borrows/tree-borrows.rs` for an example of
681- // why this is important.
682-
683- // Wildcard references are never protected. So this can never be
684- // called with a wildcard reference.
685- let source_idx = source_idx. unwrap ( ) ;
686-
687- for ( loc_range, loc) in self . locations . iter_mut_all ( ) {
688- // Only visit accessed permissions
689- if let Some ( p) = loc. perms . get ( source_idx)
690- && let Some ( access_kind) = p. permission . protector_end_access ( )
691- && p. accessed
692- {
693- let access_cause = diagnostics:: AccessCause :: FnExit ( access_kind) ;
694- loc. perform_access (
695- self . roots . iter ( ) . copied ( ) ,
696- & mut self . nodes ,
697- Some ( source_idx) ,
698- loc_range,
699- None ,
700- access_kind,
701- access_cause,
702- global,
703- alloc_id,
704- span,
705- ChildrenVisitMode :: SkipChildrenOfAccessed ,
706- ) ?;
707- }
708- }
709719 }
710720 interp_ok ( ( ) )
711721 }
0 commit comments