@@ -190,6 +190,16 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
190
190
}
191
191
192
192
fn visit_place ( & mut self , place : & Place < ' tcx > , context : PlaceContext , _location : Location ) {
193
+ // prevent
194
+ // * `&mut x.field`
195
+ // * `x.field = y;`
196
+ // * `&x.field` if `field`'s type has interior mutability
197
+ // because either of these would allow modifying the layout constrained field and
198
+ // insert values that violate the layout constraints.
199
+ if context. is_mutating_use ( ) || context. is_borrow ( ) {
200
+ self . check_mut_borrowing_layout_constrained_field ( place, context. is_mutating_use ( ) ) ;
201
+ }
202
+
193
203
for ( i, elem) in place. projection . iter ( ) . enumerate ( ) {
194
204
let proj_base = & place. projection [ ..i] ;
195
205
@@ -216,21 +226,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
216
226
) ;
217
227
}
218
228
}
219
- let is_borrow_of_interior_mut = context. is_borrow ( )
220
- && !Place :: ty_from ( & place. local , proj_base, self . body , self . tcx ) . ty . is_freeze (
221
- self . tcx ,
222
- self . param_env ,
223
- self . source_info . span ,
224
- ) ;
225
- // prevent
226
- // * `&mut x.field`
227
- // * `x.field = y;`
228
- // * `&x.field` if `field`'s type has interior mutability
229
- // because either of these would allow modifying the layout constrained field and
230
- // insert values that violate the layout constraints.
231
- if context. is_mutating_use ( ) || is_borrow_of_interior_mut {
232
- self . check_mut_borrowing_layout_constrained_field ( place, context. is_mutating_use ( ) ) ;
233
- }
234
229
let old_source_info = self . source_info ;
235
230
if let ( local, [ ] ) = ( & place. local , proj_base) {
236
231
let decl = & self . body . local_decls [ * local] ;
@@ -412,6 +407,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
412
407
cursor = proj_base;
413
408
414
409
match elem {
410
+ // Modifications behind a dereference don't affect the value of
411
+ // the pointer.
412
+ ProjectionElem :: Deref => return ,
415
413
ProjectionElem :: Field ( ..) => {
416
414
let ty =
417
415
Place :: ty_from ( & place. local , proj_base, & self . body . local_decls , self . tcx )
@@ -426,14 +424,23 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
426
424
"mutating layout constrained fields cannot statically be \
427
425
checked for valid values",
428
426
)
429
- } else {
427
+
428
+ // Check `is_freeze` as late as possible to avoid cycle errors
429
+ // with opaque types.
430
+ } else if !place. ty ( self . body , self . tcx ) . ty . is_freeze (
431
+ self . tcx ,
432
+ self . param_env ,
433
+ self . source_info . span ,
434
+ ) {
430
435
(
431
436
"borrow of layout constrained field with interior \
432
437
mutability",
433
438
"references to fields of layout constrained fields \
434
439
lose the constraints. Coupled with interior mutability, \
435
440
the field can be changed to invalid values",
436
441
)
442
+ } else {
443
+ continue ;
437
444
} ;
438
445
let source_info = self . source_info ;
439
446
self . register_violations (
0 commit comments