@@ -68,17 +68,31 @@ mod transition {
68
68
fn foreign_read ( state : PermissionPriv , protected : bool ) -> Option < PermissionPriv > {
69
69
use Option :: * ;
70
70
Some ( match state {
71
+ // Non-writeable states just ignore foreign reads.
72
+ non_writeable @ ( Frozen | Disabled ) => non_writeable,
73
+ // Writeable states are more tricky, and depend on whether things are protected.
71
74
// The inner data `ty_is_freeze` of `Reserved` is always irrelevant for Read
72
75
// accesses, since the data is not being mutated. Hence the `{ .. }`
73
- res @ Reserved { .. } if !protected => res,
74
- Reserved { .. } => Frozen , // protected reserved
76
+ res @ Reserved { .. } =>
77
+ if protected {
78
+ // Someone else read, make sure we won't write.
79
+ // We could make this `Disabled` but it doesn't look like we get anything out of that extra UB.
80
+ Frozen
81
+ } else {
82
+ // Before activation and without protectors, foreign reads are fine.
83
+ // That's the entire point of 2-phase borrows.
84
+ res
85
+ } ,
75
86
Active =>
76
87
if protected {
88
+ // We wrote, someone else reads -- that's bad.
89
+ // (If this is initialized, this move-to-protected will mean insta-UB.)
77
90
Disabled
78
91
} else {
92
+ // We don't want to disable here to allow read-read reordering: it is crucial
93
+ // that the foreign read does not invalidate future reads through this tag.
79
94
Frozen
80
95
} ,
81
- non_writeable @ ( Frozen | Disabled ) => non_writeable,
82
96
} )
83
97
}
84
98
0 commit comments