about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_typeck/src/check/place_op.rs29
1 files changed, 17 insertions, 12 deletions
diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs
index be2bc491c31..54b3fdd837e 100644
--- a/compiler/rustc_typeck/src/check/place_op.rs
+++ b/compiler/rustc_typeck/src/check/place_op.rs
@@ -211,13 +211,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         debug!("convert_place_derefs_to_mutable: exprs={:?}", exprs);
 
         // Fix up autoderefs and derefs.
+        let mut inside_union = false;
         for (i, &expr) in exprs.iter().rev().enumerate() {
             debug!("convert_place_derefs_to_mutable: i={} expr={:?}", i, expr);
 
+            let mut source = self.node_ty(expr.hir_id);
+            if matches!(expr.kind, hir::ExprKind::Unary(hir::UnOp::UnDeref, _)) {
+                // Clear previous flag; after a pointer indirection it does not apply any more.
+                inside_union = false;
+            }
+            if source.ty_adt_def().map_or(false, |adt| adt.is_union()) {
+                inside_union = true;
+            }
             // Fix up the autoderefs. Autorefs can only occur immediately preceding
             // overloaded place ops, and will be fixed by them in order to get
             // the correct region.
-            let mut source = self.node_ty(expr.hir_id);
             // Do not mutate adjustments in place, but rather take them,
             // and replace them after mutating them, to avoid having the
             // typeck results borrowed during (`deref_mut`) method resolution.
@@ -238,17 +246,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             }
                             // If this is a union field, also throw an error.
                             // Union fields should not get mutable auto-deref'd (see RFC 2514).
-                            if let hir::ExprKind::Field(ref outer_expr, _) = expr.kind {
-                                let ty = self.node_ty(outer_expr.hir_id);
-                                if ty.ty_adt_def().map_or(false, |adt| adt.is_union()) {
-                                    let mut err = self.tcx.sess.struct_span_err(
-                                        expr.span,
-                                        "not automatically applying `DerefMut` on union field",
-                                    );
-                                    err.help("writing to this field calls the destructor for the old value");
-                                    err.help("add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor");
-                                    err.emit();
-                                }
+                            if inside_union {
+                                let mut err = self.tcx.sess.struct_span_err(
+                                    expr.span,
+                                    "not automatically applying `DerefMut` on union field",
+                                );
+                                err.help("writing to this field calls the destructor for the old value");
+                                err.help("add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor");
+                                err.emit();
                             }
                         }
                     }