Skip to content

Commit b331f81

Browse files
committed
Migrate "unsafe_op_in_unsafe_fn" lints
1 parent 2629683 commit b331f81

File tree

4 files changed

+236
-21
lines changed

4 files changed

+236
-21
lines changed

compiler/rustc_error_messages/locales/en-US/mir_build.ftl

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,59 @@ mir_build_unconditional_recursion = function cannot return without recursing
33
.help = a `loop` may express intention better if this is on purpose
44
55
mir_build_unconditional_recursion_call_site_label = recursive call site
6+
7+
mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe =
8+
call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133)
9+
.note = consult the function's documentation for information on how to avoid undefined behavior
10+
.label = call to unsafe function
11+
12+
mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless =
13+
call to unsafe function is unsafe and requires unsafe block (error E0133)
14+
.note = consult the function's documentation for information on how to avoid undefined behavior
15+
.label = call to unsafe function
16+
17+
mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
18+
use of inline assembly is unsafe and requires unsafe block (error E0133)
19+
.note = inline assembly is entirely unchecked and can cause undefined behavior
20+
.label = use of inline assembly
21+
22+
mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe =
23+
initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe
24+
block (error E0133)
25+
.note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
26+
.label = initializing type with `rustc_layout_scalar_valid_range` attr
27+
28+
mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe =
29+
use of mutable static is unsafe and requires unsafe block (error E0133)
30+
.note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
31+
.label = use of mutable static
32+
33+
mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe =
34+
use of extern static is unsafe and requires unsafe block (error E0133)
35+
.note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
36+
.label = use of extern static
37+
38+
mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe =
39+
dereference of raw pointer is unsafe and requires unsafe block (error E0133)
40+
.note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
41+
.label = dereference of raw pointer
42+
43+
mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe =
44+
access to union field is unsafe and requires unsafe block (error E0133)
45+
.note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
46+
.label = access to union field
47+
48+
mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe =
49+
mutation of layout constrained field is unsafe and requires unsafe block (error E0133)
50+
.note = mutating layout constrained fields cannot statically be checked for valid values
51+
.label = mutation of layout constrained field
52+
53+
mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe =
54+
borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133)
55+
.note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
56+
.label = borrow of layout constrained field with interior mutability
57+
58+
mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe =
59+
call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
60+
.note = can only be called if the required target features are available
61+
.label = call to function with `#[target_feature]`

compiler/rustc_mir_build/src/check_unsafety.rs

Lines changed: 84 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::build::ExprCategory;
2+
use crate::errors::*;
23
use rustc_middle::thir::visit::{self, Visitor};
34

45
use rustc_errors::struct_span_err;
@@ -83,22 +84,8 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
8384
}
8485
SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
8586
SafetyContext::UnsafeFn => {
86-
let (description, note) = kind.description_and_note(self.tcx);
8787
// unsafe_op_in_unsafe_fn is disallowed
88-
self.tcx.struct_span_lint_hir(
89-
UNSAFE_OP_IN_UNSAFE_FN,
90-
self.hir_context,
91-
span,
92-
|lint| {
93-
lint.build(&format!(
94-
"{} is unsafe and requires unsafe block (error E0133)",
95-
description,
96-
))
97-
.span_label(span, kind.simple_description())
98-
.note(note)
99-
.emit();
100-
},
101-
)
88+
kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span);
10289
}
10390
SafetyContext::Safe => {
10491
let (description, note) = kind.description_and_note(self.tcx);
@@ -539,6 +526,88 @@ enum UnsafeOpKind {
539526
use UnsafeOpKind::*;
540527

541528
impl UnsafeOpKind {
529+
pub fn emit_unsafe_op_in_unsafe_fn_lint(
530+
&self,
531+
tcx: TyCtxt<'_>,
532+
hir_id: hir::HirId,
533+
span: Span,
534+
) {
535+
match self {
536+
CallToUnsafeFunction(did) if did.is_some() => tcx.emit_spanned_lint(
537+
UNSAFE_OP_IN_UNSAFE_FN,
538+
hir_id,
539+
span,
540+
UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
541+
span,
542+
function: &tcx.def_path_str(did.unwrap()),
543+
},
544+
),
545+
CallToUnsafeFunction(..) => tcx.emit_spanned_lint(
546+
UNSAFE_OP_IN_UNSAFE_FN,
547+
hir_id,
548+
span,
549+
UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span },
550+
),
551+
UseOfInlineAssembly => tcx.emit_spanned_lint(
552+
UNSAFE_OP_IN_UNSAFE_FN,
553+
hir_id,
554+
span,
555+
UnsafeOpInUnsafeUseOfInlineAssemblyRequiresUnsafe { span },
556+
),
557+
InitializingTypeWith => tcx.emit_spanned_lint(
558+
UNSAFE_OP_IN_UNSAFE_FN,
559+
hir_id,
560+
span,
561+
UnsafeOpInUnsafeInitializingTypeWithRequiresUnsafe { span },
562+
),
563+
UseOfMutableStatic => tcx.emit_spanned_lint(
564+
UNSAFE_OP_IN_UNSAFE_FN,
565+
hir_id,
566+
span,
567+
UnsafeOpInUnsafeUseOfMutableStaticRequiresUnsafe { span },
568+
),
569+
UseOfExternStatic => tcx.emit_spanned_lint(
570+
UNSAFE_OP_IN_UNSAFE_FN,
571+
hir_id,
572+
span,
573+
UnsafeOpInUnsafeUseOfExternStaticRequiresUnsafe { span },
574+
),
575+
DerefOfRawPointer => tcx.emit_spanned_lint(
576+
UNSAFE_OP_IN_UNSAFE_FN,
577+
hir_id,
578+
span,
579+
UnsafeOpInUnsafeDerefOfRawPointerRequiresUnsafe { span },
580+
),
581+
AccessToUnionField => tcx.emit_spanned_lint(
582+
UNSAFE_OP_IN_UNSAFE_FN,
583+
hir_id,
584+
span,
585+
UnsafeOpInUnsafeAccessToUnionFieldRequiresUnsafe { span },
586+
),
587+
MutationOfLayoutConstrainedField => tcx.emit_spanned_lint(
588+
UNSAFE_OP_IN_UNSAFE_FN,
589+
hir_id,
590+
span,
591+
UnsafeOpInUnsafeMutationOfLayoutConstrainedFieldRequiresUnsafe { span },
592+
),
593+
BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint(
594+
UNSAFE_OP_IN_UNSAFE_FN,
595+
hir_id,
596+
span,
597+
UnsafeOpInUnsafeBorrowOfLayoutConstrainedFieldRequiresUnsafe { span },
598+
),
599+
CallToFunctionWith(did) => tcx.emit_spanned_lint(
600+
UNSAFE_OP_IN_UNSAFE_FN,
601+
hir_id,
602+
span,
603+
UnsafeOpInUnsafeCallToFunctionWithRequiresUnsafe {
604+
span,
605+
function: &tcx.def_path_str(*did),
606+
},
607+
),
608+
}
609+
}
610+
542611
pub fn simple_description(&self) -> &'static str {
543612
match self {
544613
CallToUnsafeFunction(..) => "call to unsafe function",

compiler/rustc_mir_build/src/errors.rs

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,100 @@ use rustc_macros::LintDiagnostic;
22
use rustc_span::Span;
33

44
#[derive(LintDiagnostic)]
5-
#[lint(mir_build::unconditional_recursion)]
5+
#[diag(mir_build::unconditional_recursion)]
66
#[help]
77
pub struct UnconditionalRecursion {
8-
#[primary_span]
98
#[label]
109
pub span: Span,
1110
#[label(mir_build::unconditional_recursion_call_site_label)]
1211
pub call_sites: Vec<Span>,
1312
}
13+
14+
#[derive(LintDiagnostic)]
15+
#[diag(mir_build::unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe)]
16+
#[note]
17+
pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> {
18+
#[label]
19+
pub span: Span,
20+
pub function: &'a str,
21+
}
22+
23+
#[derive(LintDiagnostic)]
24+
#[diag(mir_build::unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless)]
25+
#[note]
26+
pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
27+
#[label]
28+
pub span: Span,
29+
}
30+
31+
#[derive(LintDiagnostic)]
32+
#[diag(mir_build::unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe)]
33+
#[note]
34+
pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
35+
#[label]
36+
pub span: Span,
37+
}
38+
39+
#[derive(LintDiagnostic)]
40+
#[diag(mir_build::unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe)]
41+
#[note]
42+
pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
43+
#[label]
44+
pub span: Span,
45+
}
46+
47+
#[derive(LintDiagnostic)]
48+
#[diag(mir_build::unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe)]
49+
#[note]
50+
pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
51+
#[label]
52+
pub span: Span,
53+
}
54+
55+
#[derive(LintDiagnostic)]
56+
#[diag(mir_build::unsafe_op_in_unsafe_fn_extern_static_requires_unsafe)]
57+
#[note]
58+
pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
59+
#[label]
60+
pub span: Span,
61+
}
62+
63+
#[derive(LintDiagnostic)]
64+
#[diag(mir_build::unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe)]
65+
#[note]
66+
pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
67+
#[label]
68+
pub span: Span,
69+
}
70+
71+
#[derive(LintDiagnostic)]
72+
#[diag(mir_build::unsafe_op_in_unsafe_fn_union_field_requires_unsafe)]
73+
#[note]
74+
pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
75+
#[label]
76+
pub span: Span,
77+
}
78+
79+
#[derive(LintDiagnostic)]
80+
#[diag(mir_build::unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe)]
81+
#[note]
82+
pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
83+
#[label]
84+
pub span: Span,
85+
}
86+
87+
#[derive(LintDiagnostic)]
88+
#[diag(mir_build::unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe)]
89+
pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
90+
#[label]
91+
pub span: Span,
92+
}
93+
94+
#[derive(LintDiagnostic)]
95+
#[diag(mir_build::unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)]
96+
#[note]
97+
pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> {
98+
#[label]
99+
pub span: Span,
100+
pub function: &'a str,
101+
}

compiler/rustc_mir_build/src/lints.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
3737

3838
let sp = tcx.def_span(def_id);
3939
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
40-
tcx.emit_spanned_lint(UNCONDITIONAL_RECURSION, hir_id, sp, UnconditionalRecursion {
41-
span: sp,
42-
call_sites: vis.reachable_recursive_calls,
43-
});
40+
tcx.emit_spanned_lint(
41+
UNCONDITIONAL_RECURSION,
42+
hir_id,
43+
sp,
44+
UnconditionalRecursion { span: sp, call_sites: vis.reachable_recursive_calls },
45+
);
4446
}
4547
}
4648

0 commit comments

Comments
 (0)