@@ -6,11 +6,19 @@ use rustc_span::{Span, SpanData};
6
6
use rustc_target:: abi:: Size ;
7
7
8
8
use crate :: borrow_tracker:: {
9
- stacked_borrows:: { err_sb_ub, Permission } ,
10
- AccessKind , GlobalStateInner , ProtectorKind ,
9
+ stacked_borrows:: Permission , AccessKind , GlobalStateInner , ProtectorKind ,
11
10
} ;
12
11
use crate :: * ;
13
12
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
+
14
22
#[ derive( Clone , Debug ) ]
15
23
pub struct AllocHistory {
16
24
id : AllocId ,
@@ -61,12 +69,15 @@ struct Invalidation {
61
69
#[ derive( Clone , Debug ) ]
62
70
enum InvalidationCause {
63
71
Access ( AccessKind ) ,
64
- Retag ( Permission , RetagCause ) ,
72
+ Retag ( Permission , RetagInfo ) ,
65
73
}
66
74
67
75
impl Invalidation {
68
76
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
+ ) {
70
81
// For a FnEntry retag, our Span points at the caller.
71
82
// See `DiagnosticCx::log_invalidation`.
72
83
format ! (
@@ -87,8 +98,8 @@ impl fmt::Display for InvalidationCause {
87
98
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
88
99
match self {
89
100
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( ) ) ,
92
103
}
93
104
}
94
105
}
@@ -129,13 +140,13 @@ impl<'ecx, 'mir, 'tcx> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
129
140
130
141
pub fn retag (
131
142
machine : & ' ecx MiriMachine < ' mir , ' tcx > ,
132
- cause : RetagCause ,
143
+ info : RetagInfo ,
133
144
new_tag : BorTag ,
134
145
orig_tag : ProvenanceExtra ,
135
146
range : AllocRange ,
136
147
) -> Self {
137
148
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 } ) ;
139
150
140
151
DiagnosticCxBuilder { machine, operation }
141
152
}
@@ -179,13 +190,19 @@ enum Operation {
179
190
180
191
#[ derive( Debug , Clone ) ]
181
192
struct RetagOp {
182
- cause : RetagCause ,
193
+ info : RetagInfo ,
183
194
new_tag : BorTag ,
184
195
orig_tag : ProvenanceExtra ,
185
196
range : AllocRange ,
186
197
permission : Option < Permission > ,
187
198
}
188
199
200
+ #[ derive( Debug , Clone , Copy , PartialEq ) ]
201
+ pub struct RetagInfo {
202
+ pub cause : RetagCause ,
203
+ pub in_field : bool ,
204
+ }
205
+
189
206
#[ derive( Debug , Clone , Copy , PartialEq ) ]
190
207
pub enum RetagCause {
191
208
Normal ,
@@ -258,11 +275,11 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
258
275
pub fn log_invalidation ( & mut self , tag : BorTag ) {
259
276
let mut span = self . machine . current_span ( ) ;
260
277
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 {
263
280
span = self . machine . caller_span ( ) ;
264
281
}
265
- ( * range, InvalidationCause :: Retag ( permission. unwrap ( ) , * cause ) )
282
+ ( * range, InvalidationCause :: Retag ( permission. unwrap ( ) , * info ) )
266
283
}
267
284
Operation :: Access ( AccessOp { kind, range, .. } ) =>
268
285
( * range, InvalidationCause :: Access ( * kind) ) ,
@@ -372,9 +389,13 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
372
389
self . history. id,
373
390
self . offset. bytes( ) ,
374
391
) ;
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
+ }
375
396
err_sb_ub (
376
397
format ! ( "{action}{}" , error_cause( stack, op. orig_tag) ) ,
377
- Some ( operation_summary ( & op . cause . summary ( ) , self . history . id , op . range ) ) ,
398
+ helps ,
378
399
op. orig_tag . and_then ( |orig_tag| self . get_logs_relevant_to ( orig_tag, None ) ) ,
379
400
)
380
401
}
@@ -397,7 +418,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
397
418
) ;
398
419
err_sb_ub (
399
420
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) ] ,
401
422
op. tag . and_then ( |tag| self . get_logs_relevant_to ( tag, None ) ) ,
402
423
)
403
424
}
@@ -423,7 +444,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
423
444
Operation :: Dealloc ( _) =>
424
445
err_sb_ub (
425
446
format ! ( "deallocating while item {item:?} is {protected} by call {call_id:?}" , ) ,
426
- None ,
447
+ vec ! [ ] ,
427
448
None ,
428
449
) ,
429
450
Operation :: Retag ( RetagOp { orig_tag : tag, .. } )
@@ -432,7 +453,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
432
453
format ! (
433
454
"not granting access to tag {tag:?} because that would remove {item:?} which is {protected} because it is an argument of call {call_id:?}" ,
434
455
) ,
435
- None ,
456
+ vec ! [ ] ,
436
457
tag. and_then ( |tag| self . get_logs_relevant_to ( tag, Some ( item. tag ( ) ) ) ) ,
437
458
) ,
438
459
}
@@ -450,7 +471,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
450
471
alloc_id = self . history. id,
451
472
cause = error_cause( stack, op. tag) ,
452
473
) ,
453
- None ,
474
+ vec ! [ ] ,
454
475
op. tag . and_then ( |tag| self . get_logs_relevant_to ( tag, None ) ) ,
455
476
)
456
477
}
@@ -496,14 +517,18 @@ fn error_cause(stack: &Stack, prov_extra: ProvenanceExtra) -> &'static str {
496
517
}
497
518
}
498
519
499
- impl RetagCause {
520
+ impl RetagInfo {
500
521
fn summary ( & self ) -> String {
501
- match self {
522
+ let mut s = match self . cause {
502
523
RetagCause :: Normal => "retag" ,
503
524
RetagCause :: FnEntry => "function-entry retag" ,
504
525
RetagCause :: InPlaceFnPassing => "in-place function argument/return passing protection" ,
505
526
RetagCause :: TwoPhase => "two-phase retag" ,
506
527
}
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
508
533
}
509
534
}
0 commit comments