@@ -190,6 +190,16 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
190190 }
191191
192192 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+
193203 for ( i, elem) in place. projection . iter ( ) . enumerate ( ) {
194204 let proj_base = & place. projection [ ..i] ;
195205
@@ -216,21 +226,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
216226 ) ;
217227 }
218228 }
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- }
234229 let old_source_info = self . source_info ;
235230 if let ( local, [ ] ) = ( & place. local , proj_base) {
236231 let decl = & self . body . local_decls [ * local] ;
@@ -412,6 +407,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
412407 cursor = proj_base;
413408
414409 match elem {
410+ // Modifications behind a dereference don't affect the value of
411+ // the pointer.
412+ ProjectionElem :: Deref => return ,
415413 ProjectionElem :: Field ( ..) => {
416414 let ty =
417415 Place :: ty_from ( & place. local , proj_base, & self . body . local_decls , self . tcx )
@@ -426,14 +424,23 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
426424 "mutating layout constrained fields cannot statically be \
427425 checked for valid values",
428426 )
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+ ) {
430435 (
431436 "borrow of layout constrained field with interior \
432437 mutability",
433438 "references to fields of layout constrained fields \
434439 lose the constraints. Coupled with interior mutability, \
435440 the field can be changed to invalid values",
436441 )
442+ } else {
443+ continue ;
437444 } ;
438445 let source_info = self . source_info ;
439446 self . register_violations (
0 commit comments