@@ -68,17 +68,31 @@ mod transition {
6868 fn foreign_read ( state : PermissionPriv , protected : bool ) -> Option < PermissionPriv > {
6969 use Option :: * ;
7070 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.
7174 // The inner data `ty_is_freeze` of `Reserved` is always irrelevant for Read
7275 // 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+ } ,
7586 Active =>
7687 if protected {
88+ // We wrote, someone else reads -- that's bad.
89+ // (If this is initialized, this move-to-protected will mean insta-UB.)
7790 Disabled
7891 } 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.
7994 Frozen
8095 } ,
81- non_writeable @ ( Frozen | Disabled ) => non_writeable,
8296 } )
8397 }
8498
0 commit comments