assigning to a union field can never drop now
This commit is contained in:
parent
5bf6017b87
commit
e4593ef0f2
6 changed files with 14 additions and 57 deletions
|
@ -35,7 +35,6 @@ pub enum UnsafetyViolationDetails {
|
||||||
UseOfMutableStatic,
|
UseOfMutableStatic,
|
||||||
UseOfExternStatic,
|
UseOfExternStatic,
|
||||||
DerefOfRawPointer,
|
DerefOfRawPointer,
|
||||||
AssignToDroppingUnionField,
|
|
||||||
AccessToUnionField,
|
AccessToUnionField,
|
||||||
MutationOfLayoutConstrainedField,
|
MutationOfLayoutConstrainedField,
|
||||||
BorrowOfLayoutConstrainedField,
|
BorrowOfLayoutConstrainedField,
|
||||||
|
@ -78,11 +77,6 @@ impl UnsafetyViolationDetails {
|
||||||
"raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
|
"raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
|
||||||
and cause data races: all of these are undefined behavior",
|
and cause data races: all of these are undefined behavior",
|
||||||
),
|
),
|
||||||
AssignToDroppingUnionField => (
|
|
||||||
"assignment to union field that might need dropping",
|
|
||||||
"the previous content of the field will be dropped, which causes undefined \
|
|
||||||
behavior if the field was not properly initialized",
|
|
||||||
),
|
|
||||||
AccessToUnionField => (
|
AccessToUnionField => (
|
||||||
"access to union field",
|
"access to union field",
|
||||||
"the field may not be properly initialized: using uninitialized data will cause \
|
"the field may not be properly initialized: using uninitialized data will cause \
|
||||||
|
|
|
@ -431,16 +431,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
||||||
let lhs = &self.thir[lhs];
|
let lhs = &self.thir[lhs];
|
||||||
if let ty::Adt(adt_def, _) = lhs.ty.kind() && adt_def.is_union() {
|
if let ty::Adt(adt_def, _) = lhs.ty.kind() && adt_def.is_union() {
|
||||||
if let Some((assigned_ty, assignment_span)) = self.assignment_info {
|
if let Some((assigned_ty, assignment_span)) = self.assignment_info {
|
||||||
// To avoid semver hazard, we only consider `Copy` and `ManuallyDrop` non-dropping.
|
if assigned_ty.needs_drop(self.tcx, self.tcx.param_env(adt_def.did())) {
|
||||||
if !(assigned_ty
|
// This would be unsafe, but should be outright impossible since we reject such unions.
|
||||||
.ty_adt_def()
|
self.tcx.sess.delay_span_bug(assignment_span, "union fields that need dropping should be impossible");
|
||||||
.map_or(false, |adt| adt.is_manually_drop())
|
|
||||||
|| assigned_ty
|
|
||||||
.is_copy_modulo_regions(self.tcx.at(expr.span), self.param_env))
|
|
||||||
{
|
|
||||||
self.requires_unsafe(assignment_span, AssignToDroppingUnionField);
|
|
||||||
} else {
|
|
||||||
// write to non-drop union field, safe
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.requires_unsafe(expr.span, AccessToUnionField);
|
self.requires_unsafe(expr.span, AccessToUnionField);
|
||||||
|
@ -537,7 +530,6 @@ enum UnsafeOpKind {
|
||||||
UseOfMutableStatic,
|
UseOfMutableStatic,
|
||||||
UseOfExternStatic,
|
UseOfExternStatic,
|
||||||
DerefOfRawPointer,
|
DerefOfRawPointer,
|
||||||
AssignToDroppingUnionField,
|
|
||||||
AccessToUnionField,
|
AccessToUnionField,
|
||||||
MutationOfLayoutConstrainedField,
|
MutationOfLayoutConstrainedField,
|
||||||
BorrowOfLayoutConstrainedField,
|
BorrowOfLayoutConstrainedField,
|
||||||
|
@ -555,7 +547,6 @@ impl UnsafeOpKind {
|
||||||
UseOfMutableStatic => "use of mutable static",
|
UseOfMutableStatic => "use of mutable static",
|
||||||
UseOfExternStatic => "use of extern static",
|
UseOfExternStatic => "use of extern static",
|
||||||
DerefOfRawPointer => "dereference of raw pointer",
|
DerefOfRawPointer => "dereference of raw pointer",
|
||||||
AssignToDroppingUnionField => "assignment to union field that might need dropping",
|
|
||||||
AccessToUnionField => "access to union field",
|
AccessToUnionField => "access to union field",
|
||||||
MutationOfLayoutConstrainedField => "mutation of layout constrained field",
|
MutationOfLayoutConstrainedField => "mutation of layout constrained field",
|
||||||
BorrowOfLayoutConstrainedField => {
|
BorrowOfLayoutConstrainedField => {
|
||||||
|
@ -600,11 +591,6 @@ impl UnsafeOpKind {
|
||||||
"raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
|
"raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
|
||||||
and cause data races: all of these are undefined behavior",
|
and cause data races: all of these are undefined behavior",
|
||||||
),
|
),
|
||||||
AssignToDroppingUnionField => (
|
|
||||||
Cow::Borrowed(self.simple_description()),
|
|
||||||
"the previous content of the field will be dropped, which causes undefined \
|
|
||||||
behavior if the field was not properly initialized",
|
|
||||||
),
|
|
||||||
AccessToUnionField => (
|
AccessToUnionField => (
|
||||||
Cow::Borrowed(self.simple_description()),
|
Cow::Borrowed(self.simple_description()),
|
||||||
"the field may not be properly initialized: using uninitialized data will cause \
|
"the field may not be properly initialized: using uninitialized data will cause \
|
||||||
|
|
|
@ -219,22 +219,15 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
|
||||||
// We have to check the actual type of the assignment, as that determines if the
|
// We have to check the actual type of the assignment, as that determines if the
|
||||||
// old value is being dropped.
|
// old value is being dropped.
|
||||||
let assigned_ty = place.ty(&self.body.local_decls, self.tcx).ty;
|
let assigned_ty = place.ty(&self.body.local_decls, self.tcx).ty;
|
||||||
// To avoid semver hazard, we only consider `Copy` and `ManuallyDrop` non-dropping.
|
if assigned_ty.needs_drop(
|
||||||
let manually_drop = assigned_ty
|
self.tcx,
|
||||||
.ty_adt_def()
|
self.tcx.param_env(base_ty.ty_adt_def().unwrap().did()),
|
||||||
.map_or(false, |adt_def| adt_def.is_manually_drop());
|
) {
|
||||||
let nodrop = manually_drop
|
// This would be unsafe, but should be outright impossible since we reject such unions.
|
||||||
|| assigned_ty.is_copy_modulo_regions(
|
self.tcx.sess.delay_span_bug(
|
||||||
self.tcx.at(self.source_info.span),
|
self.source_info.span,
|
||||||
self.param_env,
|
"union fields that need dropping should be impossible",
|
||||||
);
|
);
|
||||||
if !nodrop {
|
|
||||||
self.require_unsafe(
|
|
||||||
UnsafetyViolationKind::General,
|
|
||||||
UnsafetyViolationDetails::AssignToDroppingUnionField,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// write to non-drop union field, safe
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.require_unsafe(
|
self.require_unsafe(
|
||||||
|
|
|
@ -6,14 +6,6 @@ LL | *(u.p) = 13;
|
||||||
|
|
|
|
||||||
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
|
||||||
|
|
||||||
error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
|
|
||||||
--> $DIR/union-unsafe.rs:38:5
|
|
||||||
|
|
|
||||||
LL | u.a = (ManuallyDrop::new(RefCell::new(0)), 1);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
|
|
||||||
|
|
|
||||||
= note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
|
|
||||||
|
|
||||||
error[E0133]: access to union field is unsafe and requires unsafe function or block
|
error[E0133]: access to union field is unsafe and requires unsafe function or block
|
||||||
--> $DIR/union-unsafe.rs:46:6
|
--> $DIR/union-unsafe.rs:46:6
|
||||||
|
|
|
|
||||||
|
@ -78,6 +70,6 @@ LL | *u3.a = String::from("new");
|
||||||
|
|
|
|
||||||
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0133`.
|
For more information about this error, try `rustc --explain E0133`.
|
||||||
|
|
|
@ -35,7 +35,7 @@ fn deref_union_field(mut u: URef) {
|
||||||
|
|
||||||
fn assign_noncopy_union_field(mut u: URefCell) {
|
fn assign_noncopy_union_field(mut u: URefCell) {
|
||||||
// FIXME(thir-unsafeck)
|
// FIXME(thir-unsafeck)
|
||||||
u.a = (ManuallyDrop::new(RefCell::new(0)), 1); //~ ERROR assignment to union field
|
u.a = (ManuallyDrop::new(RefCell::new(0)), 1); // OK (assignment does not drop)
|
||||||
u.a.0 = ManuallyDrop::new(RefCell::new(0)); // OK (assignment does not drop)
|
u.a.0 = ManuallyDrop::new(RefCell::new(0)); // OK (assignment does not drop)
|
||||||
u.a.1 = 1; // OK
|
u.a.1 = 1; // OK
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,6 @@ LL | *(u.p) = 13;
|
||||||
|
|
|
|
||||||
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
|
||||||
|
|
||||||
error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
|
|
||||||
--> $DIR/union-unsafe.rs:38:5
|
|
||||||
|
|
|
||||||
LL | u.a = (ManuallyDrop::new(RefCell::new(0)), 1);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
|
|
||||||
|
|
|
||||||
= note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
|
|
||||||
|
|
||||||
error[E0133]: access to union field is unsafe and requires unsafe function or block
|
error[E0133]: access to union field is unsafe and requires unsafe function or block
|
||||||
--> $DIR/union-unsafe.rs:46:6
|
--> $DIR/union-unsafe.rs:46:6
|
||||||
|
|
|
|
||||||
|
@ -78,6 +70,6 @@ LL | *u3.a = String::from("new");
|
||||||
|
|
|
|
||||||
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0133`.
|
For more information about this error, try `rustc --explain E0133`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue