@@ -530,13 +530,11 @@ impl<'tcx> Tree {
530530 span : Span , // diagnostics
531531 ) -> InterpResult < ' tcx > {
532532 self . perform_access (
533- AccessKind :: Write ,
534533 tag,
535- Some ( access_range) ,
534+ Some ( ( access_range, AccessKind :: Write , diagnostics :: AccessCause :: Dealloc ) ) ,
536535 global,
537536 alloc_id,
538537 span,
539- diagnostics:: AccessCause :: Dealloc ,
540538 ) ?;
541539 for ( perms_range, perms) in self . rperms . iter_mut ( access_range. start , access_range. size ) {
542540 TreeVisitor { nodes : & mut self . nodes , tag_mapping : & self . tag_mapping , perms }
@@ -570,12 +568,16 @@ impl<'tcx> Tree {
570568 }
571569
572570 /// Map the per-node and per-location `LocationState::perform_access`
573- /// to each location of `access_range`, on every tag of the allocation.
571+ /// to each location of the first component of `access_range_and_kind`,
572+ /// on every tag of the allocation.
574573 ///
575- /// If `access_range ` is `None`, this is interpreted as the special
574+ /// If `access_range_and_kind ` is `None`, this is interpreted as the special
576575 /// access that is applied on protector release:
577576 /// - the access will be applied only to initialized locations of the allocation,
578- /// - and it will not be visible to children.
577+ /// - it will not be visible to children,
578+ /// - it will be recorded as a `FnExit` diagnostic access
579+ /// - and it will be a read except if the location is `Active`, i.e. has been written to,
580+ /// in which case it will be a write.
579581 ///
580582 /// `LocationState::perform_access` will take care of raising transition
581583 /// errors and updating the `initialized` status of each location,
@@ -585,13 +587,11 @@ impl<'tcx> Tree {
585587 /// - recording the history.
586588 pub fn perform_access (
587589 & mut self ,
588- access_kind : AccessKind ,
589590 tag : BorTag ,
590- access_range : Option < AllocRange > ,
591+ access_range_and_kind : Option < ( AllocRange , AccessKind , diagnostics :: AccessCause ) > ,
591592 global : & GlobalState ,
592- alloc_id : AllocId , // diagnostics
593- span : Span , // diagnostics
594- access_cause : diagnostics:: AccessCause , // diagnostics
593+ alloc_id : AllocId , // diagnostics
594+ span : Span , // diagnostics
595595 ) -> InterpResult < ' tcx > {
596596 use std:: ops:: Range ;
597597 // Performs the per-node work:
@@ -605,6 +605,8 @@ impl<'tcx> Tree {
605605 // `perms_range` is only for diagnostics (it is the range of
606606 // the `RangeMap` on which we are currently working).
607607 let node_app = |perms_range : Range < u64 > ,
608+ access_kind : AccessKind ,
609+ access_cause : diagnostics:: AccessCause ,
608610 args : NodeAppArgs < ' _ > |
609611 -> Result < ContinueTraversal , TransitionError > {
610612 let NodeAppArgs { node, mut perm, rel_pos } = args;
@@ -618,14 +620,13 @@ impl<'tcx> Tree {
618620
619621 let protected = global. borrow ( ) . protected_tags . contains_key ( & node. tag ) ;
620622 let transition = old_state. perform_access ( access_kind, rel_pos, protected) ?;
621-
622623 // Record the event as part of the history
623624 if !transition. is_noop ( ) {
624625 node. debug_info . history . push ( diagnostics:: Event {
625626 transition,
626627 is_foreign : rel_pos. is_foreign ( ) ,
627628 access_cause,
628- access_range,
629+ access_range : access_range_and_kind . map ( |x| x . 0 ) ,
629630 transition_range : perms_range,
630631 span,
631632 } ) ;
@@ -636,6 +637,7 @@ impl<'tcx> Tree {
636637 // Error handler in case `node_app` goes wrong.
637638 // Wraps the faulty transition in more context for diagnostics.
638639 let err_handler = |perms_range : Range < u64 > ,
640+ access_cause : diagnostics:: AccessCause ,
639641 args : ErrHandlerArgs < ' _ , TransitionError > |
640642 -> InterpError < ' tcx > {
641643 let ErrHandlerArgs { error_kind, conflicting_info, accessed_info } = args;
@@ -650,16 +652,16 @@ impl<'tcx> Tree {
650652 . build ( )
651653 } ;
652654
653- if let Some ( access_range) = access_range {
655+ if let Some ( ( access_range, access_kind , access_cause ) ) = access_range_and_kind {
654656 // Default branch: this is a "normal" access through a known range.
655657 // We iterate over affected locations and traverse the tree for each of them.
656658 for ( perms_range, perms) in self . rperms . iter_mut ( access_range. start , access_range. size )
657659 {
658660 TreeVisitor { nodes : & mut self . nodes , tag_mapping : & self . tag_mapping , perms }
659661 . traverse_parents_this_children_others (
660662 tag,
661- |args| node_app ( perms_range. clone ( ) , args) ,
662- |args| err_handler ( perms_range. clone ( ) , args) ,
663+ |args| node_app ( perms_range. clone ( ) , access_kind , access_cause , args) ,
664+ |args| err_handler ( perms_range. clone ( ) , access_cause , args) ,
663665 ) ?;
664666 }
665667 } else {
@@ -678,11 +680,14 @@ impl<'tcx> Tree {
678680 if let Some ( p) = perms. get ( idx)
679681 && p. initialized
680682 {
683+ let access_kind =
684+ if p. permission . is_active ( ) { AccessKind :: Write } else { AccessKind :: Read } ;
685+ let access_cause = diagnostics:: AccessCause :: FnExit ( access_kind) ;
681686 TreeVisitor { nodes : & mut self . nodes , tag_mapping : & self . tag_mapping , perms }
682687 . traverse_nonchildren (
683688 tag,
684- |args| node_app ( perms_range. clone ( ) , args) ,
685- |args| err_handler ( perms_range. clone ( ) , args) ,
689+ |args| node_app ( perms_range. clone ( ) , access_kind , access_cause , args) ,
690+ |args| err_handler ( perms_range. clone ( ) , access_cause , args) ,
686691 ) ?;
687692 }
688693 }
0 commit comments