Do not require that unsafe fields lack drop glue
Instead, we adopt the position that introducing an `unsafe` field
itself carries a safety invariant: that if you assign an invariant
to that field weaker than what the field's destructor requires,
you must ensure that field is in a droppable state in your
destructor.
See:
- https://github.com/rust-lang/rfcs/pull/3458#discussion_r1971676100
- 502113897
This commit is contained in:
parent
2f581937e1
commit
91034adf30
6 changed files with 5 additions and 80 deletions
|
@ -278,13 +278,6 @@ hir_analysis_invalid_union_field =
|
||||||
hir_analysis_invalid_union_field_sugg =
|
hir_analysis_invalid_union_field_sugg =
|
||||||
wrap the field type in `ManuallyDrop<...>`
|
wrap the field type in `ManuallyDrop<...>`
|
||||||
|
|
||||||
hir_analysis_invalid_unsafe_field =
|
|
||||||
field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be unsafe
|
|
||||||
.note = unsafe fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
|
|
||||||
|
|
||||||
hir_analysis_invalid_unsafe_field_sugg =
|
|
||||||
wrap the field type in `ManuallyDrop<...>`
|
|
||||||
|
|
||||||
hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl
|
hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl
|
||||||
.label = const parameter declared here
|
.label = const parameter declared here
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,6 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
|
|
||||||
check_transparent(tcx, def);
|
check_transparent(tcx, def);
|
||||||
check_packed(tcx, span, def);
|
check_packed(tcx, span, def);
|
||||||
check_unsafe_fields(tcx, def_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
|
@ -144,36 +143,6 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that the unsafe fields do not need dropping.
|
|
||||||
fn check_unsafe_fields(tcx: TyCtxt<'_>, item_def_id: LocalDefId) {
|
|
||||||
let span = tcx.def_span(item_def_id);
|
|
||||||
let def = tcx.adt_def(item_def_id);
|
|
||||||
|
|
||||||
let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
|
|
||||||
let args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
|
|
||||||
|
|
||||||
for field in def.all_fields() {
|
|
||||||
if !field.safety.is_unsafe() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) {
|
|
||||||
let hir::Node::Field(field) = tcx.hir_node_by_def_id(field.did.expect_local()) else {
|
|
||||||
unreachable!("field has to correspond to hir field")
|
|
||||||
};
|
|
||||||
let ty_span = field.ty.span;
|
|
||||||
tcx.dcx().emit_err(errors::InvalidUnsafeField {
|
|
||||||
field_span: field.span,
|
|
||||||
sugg: errors::InvalidUnsafeFieldSuggestion {
|
|
||||||
lo: ty_span.shrink_to_lo(),
|
|
||||||
hi: ty_span.shrink_to_hi(),
|
|
||||||
},
|
|
||||||
note: (),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check that a `static` is inhabited.
|
/// Check that a `static` is inhabited.
|
||||||
fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
// Make sure statics are inhabited.
|
// Make sure statics are inhabited.
|
||||||
|
@ -1517,7 +1486,6 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
|
|
||||||
detect_discriminant_duplicate(tcx, def);
|
detect_discriminant_duplicate(tcx, def);
|
||||||
check_transparent(tcx, def);
|
check_transparent(tcx, def);
|
||||||
check_unsafe_fields(tcx, def_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Part of enum check. Given the discriminants of an enum, errors if two or more discriminants are equal
|
/// Part of enum check. Given the discriminants of an enum, errors if two or more discriminants are equal
|
||||||
|
|
|
@ -710,17 +710,6 @@ pub(crate) struct InvalidUnionField {
|
||||||
pub note: (),
|
pub note: (),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(hir_analysis_invalid_unsafe_field, code = E0740)]
|
|
||||||
pub(crate) struct InvalidUnsafeField {
|
|
||||||
#[primary_span]
|
|
||||||
pub field_span: Span,
|
|
||||||
#[subdiagnostic]
|
|
||||||
pub sugg: InvalidUnsafeFieldSuggestion,
|
|
||||||
#[note]
|
|
||||||
pub note: (),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(hir_analysis_return_type_notation_on_non_rpitit)]
|
#[diag(hir_analysis_return_type_notation_on_non_rpitit)]
|
||||||
pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> {
|
pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> {
|
||||||
|
@ -742,18 +731,6 @@ pub(crate) struct InvalidUnionFieldSuggestion {
|
||||||
pub hi: Span,
|
pub hi: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
|
||||||
#[multipart_suggestion(
|
|
||||||
hir_analysis_invalid_unsafe_field_sugg,
|
|
||||||
applicability = "machine-applicable"
|
|
||||||
)]
|
|
||||||
pub(crate) struct InvalidUnsafeFieldSuggestion {
|
|
||||||
#[suggestion_part(code = "std::mem::ManuallyDrop<")]
|
|
||||||
pub lo: Span,
|
|
||||||
#[suggestion_part(code = ">")]
|
|
||||||
pub hi: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(hir_analysis_return_type_notation_equality_bound)]
|
#[diag(hir_analysis_return_type_notation_equality_bound)]
|
||||||
pub(crate) struct ReturnTypeNotationEqualityBound {
|
pub(crate) struct ReturnTypeNotationEqualityBound {
|
||||||
|
|
|
@ -453,8 +453,8 @@ impl Copy for ! {}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> Copy for &T {}
|
impl<T: ?Sized> Copy for &T {}
|
||||||
|
|
||||||
/// Marker trait for the types that are allowed in union fields, unsafe fields,
|
/// Marker trait for the types that are allowed in union fields and unsafe
|
||||||
/// and unsafe binder types.
|
/// binder types.
|
||||||
///
|
///
|
||||||
/// Implemented for:
|
/// Implemented for:
|
||||||
/// * `&T`, `&mut T` for all `T`,
|
/// * `&T`, `&mut T` for all `T`,
|
||||||
|
|
|
@ -17,7 +17,7 @@ fn f(a: A) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WithInvalidUnsafeField {
|
struct WithInvalidUnsafeField {
|
||||||
unsafe unsafe_noncopy_field: Vec<u32>, //~ ERROR
|
unsafe unsafe_noncopy_field: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WithManuallyDropUnsafeField {
|
struct WithManuallyDropUnsafeField {
|
||||||
|
|
|
@ -1,15 +1,3 @@
|
||||||
error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be unsafe
|
|
||||||
--> $DIR/unsafe-fields.rs:20:5
|
|
||||||
|
|
|
||||||
LL | unsafe unsafe_noncopy_field: Vec<u32>,
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: unsafe fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
|
|
||||||
help: wrap the field type in `ManuallyDrop<...>`
|
|
||||||
|
|
|
||||||
LL | unsafe unsafe_noncopy_field: std::mem::ManuallyDrop<Vec<u32>>,
|
|
||||||
| +++++++++++++++++++++++ +
|
|
||||||
|
|
||||||
error[E0133]: use of unsafe field is unsafe and requires unsafe block
|
error[E0133]: use of unsafe field is unsafe and requires unsafe block
|
||||||
--> $DIR/unsafe-fields.rs:15:30
|
--> $DIR/unsafe-fields.rs:15:30
|
||||||
|
|
|
|
||||||
|
@ -69,7 +57,6 @@ LL | &raw const self.unsafe_field
|
||||||
|
|
|
|
||||||
= note: unsafe fields may carry library invariants
|
= note: unsafe fields may carry library invariants
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0133, E0740.
|
For more information about this error, try `rustc --explain E0133`.
|
||||||
For more information about an error, try `rustc --explain E0133`.
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue