@@ -6,11 +6,19 @@ use rustc_span::{Span, SpanData};
66use rustc_target:: abi:: Size ;
77
88use crate :: borrow_tracker:: {
9- stacked_borrows:: { err_sb_ub, Permission } ,
10- AccessKind , GlobalStateInner , ProtectorKind ,
9+ stacked_borrows:: Permission , AccessKind , GlobalStateInner , ProtectorKind ,
1110} ;
1211use crate :: * ;
1312
13+ /// Error reporting
14+ fn err_sb_ub < ' tcx > (
15+ msg : String ,
16+ help : Vec < String > ,
17+ history : Option < TagHistory > ,
18+ ) -> InterpError < ' tcx > {
19+ err_machine_stop ! ( TerminationInfo :: StackedBorrowsUb { msg, help, history } )
20+ }
21+
1422#[ derive( Clone , Debug ) ]
1523pub struct AllocHistory {
1624 id : AllocId ,
@@ -61,12 +69,15 @@ struct Invalidation {
6169#[ derive( Clone , Debug ) ]
6270enum InvalidationCause {
6371 Access ( AccessKind ) ,
64- Retag ( Permission , RetagCause ) ,
72+ Retag ( Permission , RetagInfo ) ,
6573}
6674
6775impl Invalidation {
6876 fn generate_diagnostic ( & self ) -> ( String , SpanData ) {
69- let message = if let InvalidationCause :: Retag ( _, RetagCause :: FnEntry ) = self . cause {
77+ let message = if matches ! (
78+ self . cause,
79+ InvalidationCause :: Retag ( _, RetagInfo { cause: RetagCause :: FnEntry , .. } )
80+ ) {
7081 // For a FnEntry retag, our Span points at the caller.
7182 // See `DiagnosticCx::log_invalidation`.
7283 format ! (
@@ -87,8 +98,8 @@ impl fmt::Display for InvalidationCause {
8798 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
8899 match self {
89100 InvalidationCause :: Access ( kind) => write ! ( f, "{kind}" ) ,
90- InvalidationCause :: Retag ( perm, kind ) =>
91- write ! ( f, "{perm:?} {retag}" , retag = kind . summary( ) ) ,
101+ InvalidationCause :: Retag ( perm, info ) =>
102+ write ! ( f, "{perm:?} {retag}" , retag = info . summary( ) ) ,
92103 }
93104 }
94105}
@@ -129,13 +140,13 @@ impl<'ecx, 'mir, 'tcx> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
129140
130141 pub fn retag (
131142 machine : & ' ecx MiriMachine < ' mir , ' tcx > ,
132- cause : RetagCause ,
143+ info : RetagInfo ,
133144 new_tag : BorTag ,
134145 orig_tag : ProvenanceExtra ,
135146 range : AllocRange ,
136147 ) -> Self {
137148 let operation =
138- Operation :: Retag ( RetagOp { cause , new_tag, orig_tag, range, permission : None } ) ;
149+ Operation :: Retag ( RetagOp { info , new_tag, orig_tag, range, permission : None } ) ;
139150
140151 DiagnosticCxBuilder { machine, operation }
141152 }
@@ -179,13 +190,19 @@ enum Operation {
179190
180191#[ derive( Debug , Clone ) ]
181192struct RetagOp {
182- cause : RetagCause ,
193+ info : RetagInfo ,
183194 new_tag : BorTag ,
184195 orig_tag : ProvenanceExtra ,
185196 range : AllocRange ,
186197 permission : Option < Permission > ,
187198}
188199
200+ #[ derive( Debug , Clone , Copy , PartialEq ) ]
201+ pub struct RetagInfo {
202+ pub cause : RetagCause ,
203+ pub in_field : bool ,
204+ }
205+
189206#[ derive( Debug , Clone , Copy , PartialEq ) ]
190207pub enum RetagCause {
191208 Normal ,
@@ -258,11 +275,11 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
258275 pub fn log_invalidation ( & mut self , tag : BorTag ) {
259276 let mut span = self . machine . current_span ( ) ;
260277 let ( range, cause) = match & self . operation {
261- Operation :: Retag ( RetagOp { cause , range, permission, .. } ) => {
262- if * cause == RetagCause :: FnEntry {
278+ Operation :: Retag ( RetagOp { info , range, permission, .. } ) => {
279+ if info . cause == RetagCause :: FnEntry {
263280 span = self . machine . caller_span ( ) ;
264281 }
265- ( * range, InvalidationCause :: Retag ( permission. unwrap ( ) , * cause ) )
282+ ( * range, InvalidationCause :: Retag ( permission. unwrap ( ) , * info ) )
266283 }
267284 Operation :: Access ( AccessOp { kind, range, .. } ) =>
268285 ( * range, InvalidationCause :: Access ( * kind) ) ,
@@ -372,9 +389,13 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
372389 self . history. id,
373390 self . offset. bytes( ) ,
374391 ) ;
392+ let mut helps = vec ! [ operation_summary( & op. info. summary( ) , self . history. id, op. range) ] ;
393+ if op. info . in_field {
394+ helps. push ( format ! ( "errors for retagging in fields are fairly new; please reach out to us (e.g. at <https://rust-lang.zulipchat.com/#narrow/stream/269128-miri>) if you find this error troubling" ) ) ;
395+ }
375396 err_sb_ub (
376397 format ! ( "{action}{}" , error_cause( stack, op. orig_tag) ) ,
377- Some ( operation_summary ( & op . cause . summary ( ) , self . history . id , op . range ) ) ,
398+ helps ,
378399 op. orig_tag . and_then ( |orig_tag| self . get_logs_relevant_to ( orig_tag, None ) ) ,
379400 )
380401 }
@@ -397,7 +418,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
397418 ) ;
398419 err_sb_ub (
399420 format ! ( "{action}{}" , error_cause( stack, op. tag) ) ,
400- Some ( operation_summary ( "an access" , self . history . id , op. range ) ) ,
421+ vec ! [ operation_summary( "an access" , self . history. id, op. range) ] ,
401422 op. tag . and_then ( |tag| self . get_logs_relevant_to ( tag, None ) ) ,
402423 )
403424 }
@@ -423,7 +444,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
423444 Operation :: Dealloc ( _) =>
424445 err_sb_ub (
425446 format ! ( "deallocating while item {item:?} is {protected} by call {call_id:?}" , ) ,
426- None ,
447+ vec ! [ ] ,
427448 None ,
428449 ) ,
429450 Operation :: Retag ( RetagOp { orig_tag : tag, .. } )
@@ -432,7 +453,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
432453 format ! (
433454 "not granting access to tag {tag:?} because that would remove {item:?} which is {protected} because it is an argument of call {call_id:?}" ,
434455 ) ,
435- None ,
456+ vec ! [ ] ,
436457 tag. and_then ( |tag| self . get_logs_relevant_to ( tag, Some ( item. tag ( ) ) ) ) ,
437458 ) ,
438459 }
@@ -450,7 +471,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
450471 alloc_id = self . history. id,
451472 cause = error_cause( stack, op. tag) ,
452473 ) ,
453- None ,
474+ vec ! [ ] ,
454475 op. tag . and_then ( |tag| self . get_logs_relevant_to ( tag, None ) ) ,
455476 )
456477 }
@@ -496,14 +517,18 @@ fn error_cause(stack: &Stack, prov_extra: ProvenanceExtra) -> &'static str {
496517 }
497518}
498519
499- impl RetagCause {
520+ impl RetagInfo {
500521 fn summary ( & self ) -> String {
501- match self {
522+ let mut s = match self . cause {
502523 RetagCause :: Normal => "retag" ,
503524 RetagCause :: FnEntry => "function-entry retag" ,
504525 RetagCause :: InPlaceFnPassing => "in-place function argument/return passing protection" ,
505526 RetagCause :: TwoPhase => "two-phase retag" ,
506527 }
507- . to_string ( )
528+ . to_string ( ) ;
529+ if self . in_field {
530+ s. push_str ( " (of a reference/box inside this compound value)" ) ;
531+ }
532+ s
508533 }
509534}
0 commit comments