@@ -211,13 +211,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
211
211
debug ! ( "convert_place_derefs_to_mutable: exprs={:?}" , exprs) ;
212
212
213
213
// Fix up autoderefs and derefs.
214
+ let mut inside_union = false ;
214
215
for ( i, & expr) in exprs. iter ( ) . rev ( ) . enumerate ( ) {
215
216
debug ! ( "convert_place_derefs_to_mutable: i={} expr={:?}" , i, expr) ;
216
217
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
+ }
217
226
// Fix up the autoderefs. Autorefs can only occur immediately preceding
218
227
// overloaded place ops, and will be fixed by them in order to get
219
228
// the correct region.
220
- let mut source = self . node_ty ( expr. hir_id ) ;
221
229
// Do not mutate adjustments in place, but rather take them,
222
230
// and replace them after mutating them, to avoid having the
223
231
// typeck results borrowed during (`deref_mut`) method resolution.
@@ -238,17 +246,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
238
246
}
239
247
// If this is a union field, also throw an error.
240
248
// 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 ( ) ;
252
257
}
253
258
}
254
259
}
0 commit comments