Skip to content

Commit 97974e3

Browse files
committed
only emit error for ManuallyDrop derefs
1 parent 44defae commit 97974e3

File tree

3 files changed

+18
-13
lines changed

3 files changed

+18
-13
lines changed

compiler/rustc_typeck/src/check/place_op.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -244,14 +244,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
244244
if let ty::Ref(region, _, mutbl) = method.sig.output().kind {
245245
*deref = OverloadedDeref { region, mutbl };
246246
}
247-
// If this is a union field, also throw an error.
248-
// Union fields should not get mutable auto-deref'd (see RFC 2514).
249-
if inside_union {
247+
// If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514).
248+
// This helps avoid accidental drops.
249+
if inside_union
250+
&& source.ty_adt_def().map_or(false, |adt| adt.is_manually_drop())
251+
{
250252
let mut err = self.tcx.sess.struct_span_err(
251253
expr.span,
252-
"not automatically applying `DerefMut` on union field",
254+
"not automatically applying `DerefMut` on `ManuallyDrop` union field",
255+
);
256+
err.help(
257+
"writing to this reference calls the destructor for the old value",
253258
);
254-
err.help("writing to this field calls the destructor for the old value");
255259
err.help("add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor");
256260
err.emit();
257261
}

src/test/ui/union/union-deref.rs

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

1617
let mut u : U2<Vec<i32>> = U2 { x: () };
1718
unsafe { (*u.f.0).0 = Vec::new() }; // explicit deref, this compiles
18-
unsafe { u.f.0.0 = Vec::new() }; //~ERROR not automatically applying `DerefMut` on union field
19+
unsafe { u.f.0.0 = Vec::new() }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field
1920
}

src/test/ui/union/union-deref.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
error: not automatically applying `DerefMut` on union field
2-
--> $DIR/union-deref.rs:14:14
1+
error: not automatically applying `DerefMut` on `ManuallyDrop` union field
2+
--> $DIR/union-deref.rs:15:14
33
|
44
LL | unsafe { u.f.0 = Vec::new() };
55
| ^^^
66
|
7-
= help: writing to this field calls the destructor for the old value
7+
= help: writing to this reference calls the destructor for the old value
88
= help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
99

10-
error: not automatically applying `DerefMut` on union field
11-
--> $DIR/union-deref.rs:18:14
10+
error: not automatically applying `DerefMut` on `ManuallyDrop` union field
11+
--> $DIR/union-deref.rs:19:14
1212
|
1313
LL | unsafe { u.f.0.0 = Vec::new() };
1414
| ^^^^^^^
1515
|
16-
= help: writing to this field calls the destructor for the old value
16+
= help: writing to this reference calls the destructor for the old value
1717
= help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
1818

1919
error: aborting due to 2 previous errors

0 commit comments

Comments
 (0)