@@ -193,7 +193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
193193 /// Convert auto-derefs, indices, etc of an expression from `Deref` and `Index`
194194 /// into `DerefMut` and `IndexMut` respectively.
195195 ///
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
197197 /// always know whether a place needs to be mutable or not in the first pass.
198198 /// This happens whether there is an implicit mutable reborrow, e.g. when the type
199199 /// is used as the receiver of a method call.
@@ -236,6 +236,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
236236 if let ty:: Ref ( region, _, mutbl) = method. sig . output ( ) . kind {
237237 * deref = OverloadedDeref { region, mutbl } ;
238238 }
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+ }
239253 }
240254 }
241255 source = adjustment. target ;
0 commit comments