@@ -530,13 +530,11 @@ impl<'tcx> Tree {
530
530
span : Span , // diagnostics
531
531
) -> InterpResult < ' tcx > {
532
532
self . perform_access (
533
- AccessKind :: Write ,
534
533
tag,
535
- Some ( access_range) ,
534
+ Some ( ( access_range, AccessKind :: Write , diagnostics :: AccessCause :: Dealloc ) ) ,
536
535
global,
537
536
alloc_id,
538
537
span,
539
- diagnostics:: AccessCause :: Dealloc ,
540
538
) ?;
541
539
for ( perms_range, perms) in self . rperms . iter_mut ( access_range. start , access_range. size ) {
542
540
TreeVisitor { nodes : & mut self . nodes , tag_mapping : & self . tag_mapping , perms }
@@ -570,12 +568,16 @@ impl<'tcx> Tree {
570
568
}
571
569
572
570
/// 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.
574
573
///
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
576
575
/// access that is applied on protector release:
577
576
/// - 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.
579
581
///
580
582
/// `LocationState::perform_access` will take care of raising transition
581
583
/// errors and updating the `initialized` status of each location,
@@ -585,13 +587,11 @@ impl<'tcx> Tree {
585
587
/// - recording the history.
586
588
pub fn perform_access (
587
589
& mut self ,
588
- access_kind : AccessKind ,
589
590
tag : BorTag ,
590
- access_range : Option < AllocRange > ,
591
+ access_range_and_kind : Option < ( AllocRange , AccessKind , diagnostics :: AccessCause ) > ,
591
592
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
595
595
) -> InterpResult < ' tcx > {
596
596
use std:: ops:: Range ;
597
597
// Performs the per-node work:
@@ -605,6 +605,8 @@ impl<'tcx> Tree {
605
605
// `perms_range` is only for diagnostics (it is the range of
606
606
// the `RangeMap` on which we are currently working).
607
607
let node_app = |perms_range : Range < u64 > ,
608
+ access_kind : AccessKind ,
609
+ access_cause : diagnostics:: AccessCause ,
608
610
args : NodeAppArgs < ' _ > |
609
611
-> Result < ContinueTraversal , TransitionError > {
610
612
let NodeAppArgs { node, mut perm, rel_pos } = args;
@@ -618,14 +620,13 @@ impl<'tcx> Tree {
618
620
619
621
let protected = global. borrow ( ) . protected_tags . contains_key ( & node. tag ) ;
620
622
let transition = old_state. perform_access ( access_kind, rel_pos, protected) ?;
621
-
622
623
// Record the event as part of the history
623
624
if !transition. is_noop ( ) {
624
625
node. debug_info . history . push ( diagnostics:: Event {
625
626
transition,
626
627
is_foreign : rel_pos. is_foreign ( ) ,
627
628
access_cause,
628
- access_range,
629
+ access_range : access_range_and_kind . map ( |x| x . 0 ) ,
629
630
transition_range : perms_range,
630
631
span,
631
632
} ) ;
@@ -636,6 +637,7 @@ impl<'tcx> Tree {
636
637
// Error handler in case `node_app` goes wrong.
637
638
// Wraps the faulty transition in more context for diagnostics.
638
639
let err_handler = |perms_range : Range < u64 > ,
640
+ access_cause : diagnostics:: AccessCause ,
639
641
args : ErrHandlerArgs < ' _ , TransitionError > |
640
642
-> InterpError < ' tcx > {
641
643
let ErrHandlerArgs { error_kind, conflicting_info, accessed_info } = args;
@@ -650,16 +652,16 @@ impl<'tcx> Tree {
650
652
. build ( )
651
653
} ;
652
654
653
- if let Some ( access_range) = access_range {
655
+ if let Some ( ( access_range, access_kind , access_cause ) ) = access_range_and_kind {
654
656
// Default branch: this is a "normal" access through a known range.
655
657
// We iterate over affected locations and traverse the tree for each of them.
656
658
for ( perms_range, perms) in self . rperms . iter_mut ( access_range. start , access_range. size )
657
659
{
658
660
TreeVisitor { nodes : & mut self . nodes , tag_mapping : & self . tag_mapping , perms }
659
661
. traverse_parents_this_children_others (
660
662
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) ,
663
665
) ?;
664
666
}
665
667
} else {
@@ -678,11 +680,14 @@ impl<'tcx> Tree {
678
680
if let Some ( p) = perms. get ( idx)
679
681
&& p. initialized
680
682
{
683
+ let access_kind =
684
+ if p. permission . is_active ( ) { AccessKind :: Write } else { AccessKind :: Read } ;
685
+ let access_cause = diagnostics:: AccessCause :: FnExit ( access_kind) ;
681
686
TreeVisitor { nodes : & mut self . nodes , tag_mapping : & self . tag_mapping , perms }
682
687
. traverse_nonchildren (
683
688
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) ,
686
691
) ?;
687
692
}
688
693
}
0 commit comments