@@ -178,6 +178,16 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
178
178
}
179
179
180
180
fn visit_place ( & mut self , place : & Place < ' tcx > , context : PlaceContext , _location : Location ) {
181
+ // prevent
182
+ // * `&mut x.field`
183
+ // * `x.field = y;`
184
+ // * `&x.field` if `field`'s type has interior mutability
185
+ // because either of these would allow modifying the layout constrained field and
186
+ // insert values that violate the layout constraints.
187
+ if context. is_mutating_use ( ) || context. is_borrow ( ) {
188
+ self . check_mut_borrowing_layout_constrained_field ( place, context. is_mutating_use ( ) ) ;
189
+ }
190
+
181
191
for ( i, elem) in place. projection . iter ( ) . enumerate ( ) {
182
192
let proj_base = & place. projection [ ..i] ;
183
193
@@ -198,24 +208,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
198
208
) ;
199
209
}
200
210
}
201
- let is_borrow_of_interior_mut = context. is_borrow ( )
202
- && !Place :: ty_from ( place. local , proj_base, self . body , self . tcx ) . ty . is_freeze (
203
- self . tcx ,
204
- self . param_env ,
205
- self . source_info . span ,
206
- ) ;
207
- // prevent
208
- // * `&mut x.field`
209
- // * `x.field = y;`
210
- // * `&x.field` if `field`'s type has interior mutability
211
- // because either of these would allow modifying the layout constrained field and
212
- // insert values that violate the layout constraints.
213
- if context. is_mutating_use ( ) || is_borrow_of_interior_mut {
214
- self . check_mut_borrowing_layout_constrained_field ( place, context. is_mutating_use ( ) ) ;
215
- }
216
211
let old_source_info = self . source_info ;
217
- if let ( local , [ ] ) = ( & place . local , proj_base) {
218
- let decl = & self . body . local_decls [ * local] ;
212
+ if let [ ] = proj_base {
213
+ let decl = & self . body . local_decls [ place . local ] ;
219
214
if decl. internal {
220
215
if let LocalInfo :: StaticRef { def_id, .. } = decl. local_info {
221
216
if self . tcx . is_mutable_static ( def_id) {
@@ -240,7 +235,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
240
235
// Internal locals are used in the `move_val_init` desugaring.
241
236
// We want to check unsafety against the source info of the
242
237
// desugaring, rather than the source info of the RHS.
243
- self . source_info = self . body . local_decls [ * local] . source_info ;
238
+ self . source_info = self . body . local_decls [ place . local ] . source_info ;
244
239
}
245
240
}
246
241
}
@@ -396,6 +391,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
396
391
cursor = proj_base;
397
392
398
393
match elem {
394
+ // Modifications behind a dereference don't affect the value of
395
+ // the pointer.
396
+ ProjectionElem :: Deref => return ,
399
397
ProjectionElem :: Field ( ..) => {
400
398
let ty =
401
399
Place :: ty_from ( place. local , proj_base, & self . body . local_decls , self . tcx ) . ty ;
@@ -409,14 +407,23 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
409
407
"mutating layout constrained fields cannot statically be \
410
408
checked for valid values",
411
409
)
412
- } else {
410
+
411
+ // Check `is_freeze` as late as possible to avoid cycle errors
412
+ // with opaque types.
413
+ } else if !place. ty ( self . body , self . tcx ) . ty . is_freeze (
414
+ self . tcx ,
415
+ self . param_env ,
416
+ self . source_info . span ,
417
+ ) {
413
418
(
414
419
"borrow of layout constrained field with interior \
415
420
mutability",
416
421
"references to fields of layout constrained fields \
417
422
lose the constraints. Coupled with interior mutability, \
418
423
the field can be changed to invalid values",
419
424
)
425
+ } else {
426
+ continue ;
420
427
} ;
421
428
self . require_unsafe (
422
429
description,
0 commit comments