1
Fork 0

Implement the unsafe-fields RFC.

Co-Authored-By: Jacob Pratt <jacob@jhpratt.dev>
This commit is contained in:
Luca Versari 2024-10-27 01:35:33 +02:00
parent 75703c1a78
commit 9022bb2d6f
38 changed files with 793 additions and 85 deletions

View file

@ -4,7 +4,7 @@ use std::ops::Bound;
use rustc_errors::DiagArgValue;
use rustc_hir::def::DefKind;
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, Safety};
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
use rustc_middle::mir::BorrowKind;
use rustc_middle::span_bug;
@ -339,8 +339,13 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
};
match &pat.kind {
PatKind::Leaf { .. } => {
PatKind::Leaf { subpatterns, .. } => {
if let ty::Adt(adt_def, ..) = pat.ty.kind() {
for pat in subpatterns {
if adt_def.non_enum_variant().fields[pat.field].safety == Safety::Unsafe {
self.requires_unsafe(pat.pattern.span, UseOfUnsafeField);
}
}
if adt_def.is_union() {
let old_in_union_destructure =
std::mem::replace(&mut self.in_union_destructure, true);
@ -359,6 +364,15 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
visit::walk_pat(self, pat);
}
}
PatKind::Variant { adt_def, args: _, variant_index, subpatterns } => {
for pat in subpatterns {
let field = &pat.field;
if adt_def.variant(*variant_index).fields[*field].safety == Safety::Unsafe {
self.requires_unsafe(pat.pattern.span, UseOfUnsafeField);
}
}
visit::walk_pat(self, pat);
}
PatKind::Binding { mode: BindingMode(ByRef::Yes(rm), _), ty, .. } => {
if self.inside_adt {
let ty::Ref(_, ty, _) = ty.kind() else {
@ -579,15 +593,20 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
}
ExprKind::Adt(box AdtExpr {
adt_def,
variant_index: _,
variant_index,
args: _,
user_ty: _,
fields: _,
base: _,
}) => match self.tcx.layout_scalar_valid_range(adt_def.did()) {
(Bound::Unbounded, Bound::Unbounded) => {}
_ => self.requires_unsafe(expr.span, InitializingTypeWith),
},
}) => {
if adt_def.variant(variant_index).has_unsafe_fields() {
self.requires_unsafe(expr.span, InitializingTypeWithUnsafeField)
}
match self.tcx.layout_scalar_valid_range(adt_def.did()) {
(Bound::Unbounded, Bound::Unbounded) => {}
_ => self.requires_unsafe(expr.span, InitializingTypeWith),
}
}
ExprKind::Closure(box ClosureExpr {
closure_id,
args: _,
@ -601,23 +620,24 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
let def_id = did.expect_local();
self.visit_inner_body(def_id);
}
ExprKind::Field { lhs, .. } => {
ExprKind::Field { lhs, variant_index, name } => {
let lhs = &self.thir[lhs];
if let ty::Adt(adt_def, _) = lhs.ty.kind()
&& adt_def.is_union()
{
if let Some(assigned_ty) = self.assignment_info {
if assigned_ty.needs_drop(self.tcx, self.typing_env) {
// This would be unsafe, but should be outright impossible since we
// reject such unions.
assert!(
self.tcx.dcx().has_errors().is_some(),
"union fields that need dropping should be impossible: \
{assigned_ty}"
);
if let ty::Adt(adt_def, _) = lhs.ty.kind() {
if adt_def.variant(variant_index).fields[name].safety == Safety::Unsafe {
self.requires_unsafe(expr.span, UseOfUnsafeField);
} else if adt_def.is_union() {
if let Some(assigned_ty) = self.assignment_info {
if assigned_ty.needs_drop(self.tcx, self.typing_env) {
// This would be unsafe, but should be outright impossible since we
// reject such unions.
assert!(
self.tcx.dcx().has_errors().is_some(),
"union fields that need dropping should be impossible: {assigned_ty}"
);
}
} else {
self.requires_unsafe(expr.span, AccessToUnionField);
}
} else {
self.requires_unsafe(expr.span, AccessToUnionField);
}
}
}
@ -689,8 +709,10 @@ enum UnsafeOpKind {
CallToUnsafeFunction(Option<DefId>),
UseOfInlineAssembly,
InitializingTypeWith,
InitializingTypeWithUnsafeField,
UseOfMutableStatic,
UseOfExternStatic,
UseOfUnsafeField,
DerefOfRawPointer,
AccessToUnionField,
MutationOfLayoutConstrainedField,
@ -770,6 +792,15 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
},
),
InitializingTypeWithUnsafeField => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
UnsafeOpInUnsafeFnInitializingTypeWithUnsafeFieldRequiresUnsafe {
span,
unsafe_not_inherited_note,
},
),
UseOfMutableStatic => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
@ -788,6 +819,15 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
},
),
UseOfUnsafeField => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
UnsafeOpInUnsafeFnUseOfUnsafeFieldRequiresUnsafe {
span,
unsafe_not_inherited_note,
},
),
DerefOfRawPointer => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
@ -927,6 +967,20 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
});
}
InitializingTypeWithUnsafeField if unsafe_op_in_unsafe_fn_allowed => {
dcx.emit_err(
InitializingTypeWithUnsafeFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
span,
unsafe_not_inherited_note,
},
);
}
InitializingTypeWithUnsafeField => {
dcx.emit_err(InitializingTypeWithUnsafeFieldRequiresUnsafe {
span,
unsafe_not_inherited_note,
});
}
UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => {
dcx.emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
span,
@ -945,6 +999,15 @@ impl UnsafeOpKind {
UseOfExternStatic => {
dcx.emit_err(UseOfExternStaticRequiresUnsafe { span, unsafe_not_inherited_note });
}
UseOfUnsafeField if unsafe_op_in_unsafe_fn_allowed => {
dcx.emit_err(UseOfUnsafeFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
span,
unsafe_not_inherited_note,
});
}
UseOfUnsafeField => {
dcx.emit_err(UseOfUnsafeFieldRequiresUnsafe { span, unsafe_not_inherited_note });
}
DerefOfRawPointer if unsafe_op_in_unsafe_fn_allowed => {
dcx.emit_err(DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
span,

View file

@ -86,6 +86,16 @@ pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
}
#[derive(LintDiagnostic)]
#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_unsafe_field_requires_unsafe, code = E0133)]
#[note]
pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithUnsafeFieldRequiresUnsafe {
#[label]
pub(crate) span: Span,
#[subdiagnostic]
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
}
#[derive(LintDiagnostic)]
#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)]
#[note]
@ -106,6 +116,16 @@ pub(crate) struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
}
#[derive(LintDiagnostic)]
#[diag(mir_build_unsafe_op_in_unsafe_fn_unsafe_field_requires_unsafe, code = E0133)]
#[note]
pub(crate) struct UnsafeOpInUnsafeFnUseOfUnsafeFieldRequiresUnsafe {
#[label]
pub(crate) span: Span,
#[subdiagnostic]
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
}
#[derive(LintDiagnostic)]
#[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe, code = E0133)]
#[note]
@ -250,6 +270,17 @@ pub(crate) struct InitializingTypeWithRequiresUnsafe {
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
}
#[derive(Diagnostic)]
#[diag(mir_build_initializing_type_with_unsafe_field_requires_unsafe, code = E0133)]
#[note]
pub(crate) struct InitializingTypeWithUnsafeFieldRequiresUnsafe {
#[primary_span]
#[label]
pub(crate) span: Span,
#[subdiagnostic]
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
}
#[derive(Diagnostic)]
#[diag(
mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
@ -264,6 +295,20 @@ pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
}
#[derive(Diagnostic)]
#[diag(
mir_build_initializing_type_with_unsafe_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
code = E0133
)]
#[note]
pub(crate) struct InitializingTypeWithUnsafeFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
#[primary_span]
#[label]
pub(crate) span: Span,
#[subdiagnostic]
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
}
#[derive(Diagnostic)]
#[diag(mir_build_mutable_static_requires_unsafe, code = E0133)]
#[note]
@ -308,6 +353,28 @@ pub(crate) struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
}
#[derive(Diagnostic)]
#[diag(mir_build_unsafe_field_requires_unsafe, code = E0133)]
#[note]
pub(crate) struct UseOfUnsafeFieldRequiresUnsafe {
#[primary_span]
#[label]
pub(crate) span: Span,
#[subdiagnostic]
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
}
#[derive(Diagnostic)]
#[diag(mir_build_unsafe_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
#[note]
pub(crate) struct UseOfUnsafeFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
#[primary_span]
#[label]
pub(crate) span: Span,
#[subdiagnostic]
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
}
#[derive(Diagnostic)]
#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = E0133)]
#[note]