diff options
| author | Ralf Jung <post@ralfj.de> | 2020-08-16 10:07:33 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2020-08-31 10:14:29 +0200 |
| commit | ec0924f9649ea472782df6d21595714cb594f038 (patch) | |
| tree | 469d6fd7fe103240d531fb4013f5a81cb0dd6e57 /compiler | |
| parent | 8ed5cb56b5e5cc216eb6820a44dd4f7ef65107b0 (diff) | |
| download | rust-ec0924f9649ea472782df6d21595714cb594f038.tar.gz rust-ec0924f9649ea472782df6d21595714cb594f038.zip | |
do not apply DerefMut on union field
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_typeck/src/check/place_op.rs | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs index 4bef9aecd2e..be2bc491c31 100644 --- a/compiler/rustc_typeck/src/check/place_op.rs +++ b/compiler/rustc_typeck/src/check/place_op.rs @@ -193,7 +193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Convert auto-derefs, indices, etc of an expression from `Deref` and `Index` /// into `DerefMut` and `IndexMut` respectively. /// - /// This is a second pass of typechecking derefs/indices. We need this we do not + /// This is a second pass of typechecking derefs/indices. We need this because we do not /// always know whether a place needs to be mutable or not in the first pass. /// This happens whether there is an implicit mutable reborrow, e.g. when the type /// is used as the receiver of a method call. @@ -236,6 +236,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::Ref(region, _, mutbl) = method.sig.output().kind { *deref = OverloadedDeref { region, mutbl }; } + // 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(); + } + } } } source = adjustment.target; |
