only emit error for ManuallyDrop derefs

This commit is contained in:
Ralf Jung 2020-08-16 10:32:37 +02:00
parent 44defaea3a
commit 97974e3cab
3 changed files with 18 additions and 13 deletions

View File

@ -244,14 +244,18 @@ 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 inside_union {
// If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514).
// This helps avoid accidental drops.
if inside_union
&& source.ty_adt_def().map_or(false, |adt| adt.is_manually_drop())
{
let mut err = self.tcx.sess.struct_span_err(
expr.span,
"not automatically applying `DerefMut` on union field",
"not automatically applying `DerefMut` on `ManuallyDrop` union field",
);
err.help(
"writing to this reference calls the destructor for the old value",
);
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();
}

View File

@ -1,3 +1,4 @@
// ignore-tidy-linelength
//! Test the part of RFC 2514 that is about not applying `DerefMut` coercions
//! of union fields.
#![feature(untagged_unions)]
@ -11,9 +12,9 @@ union U2<T> { x:(), f: (ManuallyDrop<(T,)>,) }
fn main() {
let mut u : U1<Vec<i32>> = U1 { x: () };
unsafe { (*u.f).0 = Vec::new() }; // explicit deref, this compiles
unsafe { u.f.0 = Vec::new() }; //~ERROR not automatically applying `DerefMut` on union field
unsafe { u.f.0 = Vec::new() }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field
let mut u : U2<Vec<i32>> = U2 { x: () };
unsafe { (*u.f.0).0 = Vec::new() }; // explicit deref, this compiles
unsafe { u.f.0.0 = Vec::new() }; //~ERROR not automatically applying `DerefMut` on union field
unsafe { u.f.0.0 = Vec::new() }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field
}

View File

@ -1,19 +1,19 @@
error: not automatically applying `DerefMut` on union field
--> $DIR/union-deref.rs:14:14
error: not automatically applying `DerefMut` on `ManuallyDrop` union field
--> $DIR/union-deref.rs:15:14
|
LL | unsafe { u.f.0 = Vec::new() };
| ^^^
|
= help: writing to this field calls the destructor for the old value
= help: writing to this reference calls the destructor for the old value
= help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
error: not automatically applying `DerefMut` on union field
--> $DIR/union-deref.rs:18:14
error: not automatically applying `DerefMut` on `ManuallyDrop` union field
--> $DIR/union-deref.rs:19:14
|
LL | unsafe { u.f.0.0 = Vec::new() };
| ^^^^^^^
|
= help: writing to this field calls the destructor for the old value
= help: writing to this reference calls the destructor for the old value
= help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
error: aborting due to 2 previous errors