@@ -193,7 +193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
193
193
/// Convert auto-derefs, indices, etc of an expression from `Deref` and `Index`
194
194
/// into `DerefMut` and `IndexMut` respectively.
195
195
///
196
- /// This is a second pass of typechecking derefs/indices. We need this we do not
196
+ /// This is a second pass of typechecking derefs/indices. We need this because we do not
197
197
/// always know whether a place needs to be mutable or not in the first pass.
198
198
/// This happens whether there is an implicit mutable reborrow, e.g. when the type
199
199
/// is used as the receiver of a method call.
@@ -236,6 +236,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
236
236
if let ty:: Ref ( region, _, mutbl) = method. sig . output ( ) . kind {
237
237
* deref = OverloadedDeref { region, mutbl } ;
238
238
}
239
+ // If this is a union field, also throw an error.
240
+ // 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
+ }
252
+ }
239
253
}
240
254
}
241
255
source = adjustment. target ;
0 commit comments