@@ -12,16 +12,46 @@ use crate::borrow_tracker::tree_borrows::{
1212use crate :: borrow_tracker:: { AccessKind , ProtectorKind } ;
1313use crate :: * ;
1414
15+ /// Cause of an access: either a real access or one
16+ /// inserted by Tree Borrows due to a reborrow or a deallocation.
17+ #[ derive( Clone , Copy , Debug ) ]
18+ pub enum AccessCause {
19+ Explicit ( AccessKind ) ,
20+ Reborrow ,
21+ Dealloc ,
22+ }
23+
24+ impl fmt:: Display for AccessCause {
25+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
26+ match self {
27+ Self :: Explicit ( kind) => write ! ( f, "{kind}" ) ,
28+ Self :: Reborrow => write ! ( f, "reborrow" ) ,
29+ Self :: Dealloc => write ! ( f, "deallocation" ) ,
30+ }
31+ }
32+ }
33+
34+ impl AccessCause {
35+ fn print_as_access ( self , is_foreign : bool ) -> String {
36+ let rel = if is_foreign { "foreign" } else { "child" } ;
37+ match self {
38+ Self :: Explicit ( kind) => format ! ( "{rel} {kind}" ) ,
39+ Self :: Reborrow => format ! ( "reborrow (acting as a {rel} read access)" ) ,
40+ Self :: Dealloc => format ! ( "deallocation (acting as a {rel} write access)" ) ,
41+ }
42+ }
43+ }
44+
1545/// Complete data for an event:
1646#[ derive( Clone , Debug ) ]
1747pub struct Event {
18- /// Transformation of permissions that occured because of this event
48+ /// Transformation of permissions that occured because of this event.
1949 pub transition : PermTransition ,
20- /// Kind of the access that triggered this event
21- pub access_kind : AccessKind ,
22- /// Relative position of the tag to the one used for the access
50+ /// Kind of the access that triggered this event.
51+ pub access_cause : AccessCause ,
52+ /// Relative position of the tag to the one used for the access.
2353 pub is_foreign : bool ,
24- /// User-visible range of the access
54+ /// User-visible range of the access.
2555 pub access_range : AllocRange ,
2656 /// The transition recorded by this event only occured on a subrange of
2757 /// `access_range`: a single access on `access_range` triggers several events,
@@ -36,7 +66,7 @@ pub struct Event {
3666 /// the `TbError`, which should satisfy
3767 /// `event.transition_range.contains(error.error_offset)`.
3868 pub transition_range : Range < u64 > ,
39- /// Line of code that triggered this event
69+ /// Line of code that triggered this event.
4070 pub span : Span ,
4171}
4272
@@ -83,17 +113,19 @@ impl HistoryData {
83113 self . events . push ( ( Some ( created. 0 . data ( ) ) , msg_creation) ) ;
84114 for & Event {
85115 transition,
86- access_kind,
87116 is_foreign,
117+ access_cause,
88118 access_range,
89119 span,
90120 transition_range : _,
91121 } in & events
92122 {
93123 // NOTE: `transition_range` is explicitly absent from the error message, it has no significance
94124 // to the user. The meaningful one is `access_range`.
95- self . events . push ( ( Some ( span. data ( ) ) , format ! ( "{this} later transitioned to {endpoint} due to a {rel} {access_kind} at offsets {access_range:?}" , endpoint = transition. endpoint( ) , rel = if is_foreign { "foreign" } else { "child" } ) ) ) ;
96- self . events . push ( ( None , format ! ( "this corresponds to {}" , transition. summary( ) ) ) ) ;
125+ let access = access_cause. print_as_access ( is_foreign) ;
126+ self . events . push ( ( Some ( span. data ( ) ) , format ! ( "{this} later transitioned to {endpoint} due to a {access} at offsets {access_range:?}" , endpoint = transition. endpoint( ) ) ) ) ;
127+ self . events
128+ . push ( ( None , format ! ( "this transition corresponds to {}" , transition. summary( ) ) ) ) ;
97129 }
98130 }
99131}
@@ -238,9 +270,8 @@ pub(super) struct TbError<'node> {
238270 /// On accesses rejected due to insufficient permissions, this is the
239271 /// tag that lacked those permissions.
240272 pub conflicting_info : & ' node NodeDebugInfo ,
241- /// Whether this was a Read or Write access. This field is ignored
242- /// when the error was triggered by a deallocation.
243- pub access_kind : AccessKind ,
273+ // What kind of access caused this error (read, write, reborrow, deallocation)
274+ pub access_cause : AccessCause ,
244275 /// Which tag the access that caused this error was made through, i.e.
245276 /// which tag was used to read/write/deallocate.
246277 pub accessed_info : & ' node NodeDebugInfo ,
@@ -250,46 +281,46 @@ impl TbError<'_> {
250281 /// Produce a UB error.
251282 pub fn build < ' tcx > ( self ) -> InterpError < ' tcx > {
252283 use TransitionError :: * ;
253- let kind = self . access_kind ;
284+ let cause = self . access_cause ;
254285 let accessed = self . accessed_info ;
255286 let conflicting = self . conflicting_info ;
256287 let accessed_is_conflicting = accessed. tag == conflicting. tag ;
288+ let title = format ! ( "{cause} through {accessed} is forbidden" ) ;
257289 let ( title, details, conflicting_tag_name) = match self . error_kind {
258290 ChildAccessForbidden ( perm) => {
259291 let conflicting_tag_name =
260292 if accessed_is_conflicting { "accessed" } else { "conflicting" } ;
261- let title = format ! ( "{kind} through {accessed} is forbidden" ) ;
262293 let mut details = Vec :: new ( ) ;
263294 if !accessed_is_conflicting {
264295 details. push ( format ! (
265296 "the accessed tag {accessed} is a child of the conflicting tag {conflicting}"
266297 ) ) ;
267298 }
299+ let access = cause. print_as_access ( /* is_foreign */ false ) ;
268300 details. push ( format ! (
269- "the {conflicting_tag_name} tag {conflicting} has state {perm} which forbids child {kind}es "
301+ "the {conflicting_tag_name} tag {conflicting} has state {perm} which forbids this {access} "
270302 ) ) ;
271303 ( title, details, conflicting_tag_name)
272304 }
273305 ProtectedTransition ( transition) => {
274306 let conflicting_tag_name = "protected" ;
275- let title = format ! ( "{kind} through {accessed} is forbidden" ) ;
307+ let access = cause . print_as_access ( /* is_foreign */ true ) ;
276308 let details = vec ! [
277309 format!(
278310 "the accessed tag {accessed} is foreign to the {conflicting_tag_name} tag {conflicting} (i.e., it is not a child)"
279311 ) ,
280312 format!(
281- "the access would cause the {conflicting_tag_name} tag {conflicting} to transition {transition}"
313+ "this { access} would cause the {conflicting_tag_name} tag {conflicting} to transition {transition}"
282314 ) ,
283315 format!(
284- "this is {loss}, which is not allowed for protected tags" ,
316+ "this transition would be {loss}, which is not allowed for protected tags" ,
285317 loss = transition. summary( ) ,
286318 ) ,
287319 ] ;
288320 ( title, details, conflicting_tag_name)
289321 }
290322 ProtectedDealloc => {
291323 let conflicting_tag_name = "strongly protected" ;
292- let title = format ! ( "deallocation through {accessed} is forbidden" ) ;
293324 let details = vec ! [
294325 format!(
295326 "the allocation of the accessed tag {accessed} also contains the {conflicting_tag_name} tag {conflicting}"
0 commit comments