@@ -211,13 +211,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
211211 debug ! ( "convert_place_derefs_to_mutable: exprs={:?}" , exprs) ;
212212
213213 // Fix up autoderefs and derefs.
214+ let mut inside_union = false ;
214215 for ( i, & expr) in exprs. iter ( ) . rev ( ) . enumerate ( ) {
215216 debug ! ( "convert_place_derefs_to_mutable: i={} expr={:?}" , i, expr) ;
216217
218+ let mut source = self . node_ty ( expr. hir_id ) ;
219+ if matches ! ( expr. kind, hir:: ExprKind :: Unary ( hir:: UnOp :: UnDeref , _) ) {
220+ // Clear previous flag; after a pointer indirection it does not apply any more.
221+ inside_union = false ;
222+ }
223+ if source. ty_adt_def ( ) . map_or ( false , |adt| adt. is_union ( ) ) {
224+ inside_union = true ;
225+ }
217226 // Fix up the autoderefs. Autorefs can only occur immediately preceding
218227 // overloaded place ops, and will be fixed by them in order to get
219228 // the correct region.
220- let mut source = self . node_ty ( expr. hir_id ) ;
221229 // Do not mutate adjustments in place, but rather take them,
222230 // and replace them after mutating them, to avoid having the
223231 // typeck results borrowed during (`deref_mut`) method resolution.
@@ -238,17 +246,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
238246 }
239247 // If this is a union field, also throw an error.
240248 // Union fields should not get mutable auto-deref'd (see RFC 2514).
241- if let hir:: ExprKind :: Field ( ref outer_expr, _) = expr. kind {
242- let ty = self . node_ty ( outer_expr. hir_id ) ;
243- if ty. ty_adt_def ( ) . map_or ( false , |adt| adt. is_union ( ) ) {
244- let mut err = self . tcx . sess . struct_span_err (
245- expr. span ,
246- "not automatically applying `DerefMut` on union field" ,
247- ) ;
248- err. help ( "writing to this field calls the destructor for the old value" ) ;
249- err. help ( "add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor" ) ;
250- err. emit ( ) ;
251- }
249+ if inside_union {
250+ let mut err = self . tcx . sess . struct_span_err (
251+ expr. span ,
252+ "not automatically applying `DerefMut` on union field" ,
253+ ) ;
254+ err. help ( "writing to this field calls the destructor for the old value" ) ;
255+ err. help ( "add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor" ) ;
256+ err. emit ( ) ;
252257 }
253258 }
254259 }
0 commit comments