Skip to content

Commit 979eaf4

Browse files
authored
Rollup merge of rust-lang#104417 - mejrs:mir_build, r=davidtwco
Migrate rustc_mir_build diagnostics Rebases rust-lang#100854 ~~The remaining issue is how to better resolve rust-lang@72bea68af4ee2a41c44998916f6a789163f12e7d~~ ~~The diagnostic macros seems to generate a broken diagnostic, and I couldn't figure out how to manually format the fluent message, so I hardcoded the format string for now. I'd like pointers to a better fix for this.~~ Also, I'm not 100% sure I didn't mess up a rebase somewhere 🙂 r? `@davidtwco`
2 parents 0f0b4f6 + 1d324dd commit 979eaf4

File tree

10 files changed

+1188
-291
lines changed

10 files changed

+1188
-291
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4070,6 +4070,7 @@ dependencies = [
40704070
"rustc_hir",
40714071
"rustc_index",
40724072
"rustc_infer",
4073+
"rustc_macros",
40734074
"rustc_middle",
40744075
"rustc_serialize",
40754076
"rustc_session",

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

+301
Large diffs are not rendered by default.

compiler/rustc_error_messages/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ fluent_messages! {
5757
lint => "../locales/en-US/lint.ftl",
5858
metadata => "../locales/en-US/metadata.ftl",
5959
middle => "../locales/en-US/middle.ftl",
60+
mir_build => "../locales/en-US/mir_build.ftl",
6061
mir_dataflow => "../locales/en-US/mir_dataflow.ftl",
6162
monomorphize => "../locales/en-US/monomorphize.ftl",
6263
parse => "../locales/en-US/parse.ftl",

compiler/rustc_mir_build/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ rustc_index = { path = "../rustc_index" }
1717
rustc_errors = { path = "../rustc_errors" }
1818
rustc_hir = { path = "../rustc_hir" }
1919
rustc_infer = { path = "../rustc_infer" }
20+
rustc_macros = { path = "../rustc_macros" }
2021
rustc_serialize = { path = "../rustc_serialize" }
2122
rustc_session = { path = "../rustc_session" }
2223
rustc_span = { path = "../rustc_span" }

compiler/rustc_mir_build/src/check_unsafety.rs

+185-95
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::build::ExprCategory;
2+
use crate::errors::*;
23
use rustc_middle::thir::visit::{self, Visitor};
34

4-
use rustc_errors::struct_span_err;
55
use rustc_hir as hir;
66
use rustc_middle::mir::BorrowKind;
77
use rustc_middle::thir::*;
@@ -12,7 +12,6 @@ use rustc_span::def_id::{DefId, LocalDefId};
1212
use rustc_span::symbol::Symbol;
1313
use rustc_span::Span;
1414

15-
use std::borrow::Cow;
1615
use std::ops::Bound;
1716

1817
struct UnsafetyVisitor<'a, 'tcx> {
@@ -46,7 +45,9 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
4645
self.warn_unused_unsafe(
4746
hir_id,
4847
block_span,
49-
Some((self.tcx.sess.source_map().guess_head_span(enclosing_span), "block")),
48+
Some(UnusedUnsafeEnclosing::Block {
49+
span: self.tcx.sess.source_map().guess_head_span(enclosing_span),
50+
}),
5051
);
5152
f(self);
5253
} else {
@@ -60,7 +61,9 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
6061
hir_id,
6162
span,
6263
if self.unsafe_op_in_unsafe_fn_allowed() {
63-
self.body_unsafety.unsafe_fn_sig_span().map(|span| (span, "fn"))
64+
self.body_unsafety
65+
.unsafe_fn_sig_span()
66+
.map(|span| UnusedUnsafeEnclosing::Function { span })
6467
} else {
6568
None
6669
},
@@ -83,30 +86,11 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
8386
}
8487
SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
8588
SafetyContext::UnsafeFn => {
86-
let (description, note) = kind.description_and_note(self.tcx);
8789
// 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-
format!("{} is unsafe and requires unsafe block (error E0133)", description,),
93-
|lint| lint.span_label(span, kind.simple_description()).note(note),
94-
)
90+
kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span);
9591
}
9692
SafetyContext::Safe => {
97-
let (description, note) = kind.description_and_note(self.tcx);
98-
let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" };
99-
struct_span_err!(
100-
self.tcx.sess,
101-
span,
102-
E0133,
103-
"{} is unsafe and requires unsafe{} block",
104-
description,
105-
fn_sugg,
106-
)
107-
.span_label(span, kind.simple_description())
108-
.note(note)
109-
.emit();
93+
kind.emit_requires_unsafe_err(self.tcx, span, unsafe_op_in_unsafe_fn_allowed);
11094
}
11195
}
11296
}
@@ -115,17 +99,15 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
11599
&self,
116100
hir_id: hir::HirId,
117101
block_span: Span,
118-
enclosing_unsafe: Option<(Span, &'static str)>,
102+
enclosing_unsafe: Option<UnusedUnsafeEnclosing>,
119103
) {
120104
let block_span = self.tcx.sess.source_map().guess_head_span(block_span);
121-
let msg = "unnecessary `unsafe` block";
122-
self.tcx.struct_span_lint_hir(UNUSED_UNSAFE, hir_id, block_span, msg, |lint| {
123-
lint.span_label(block_span, msg);
124-
if let Some((span, kind)) = enclosing_unsafe {
125-
lint.span_label(span, format!("because it's nested under this `unsafe` {}", kind));
126-
}
127-
lint
128-
});
105+
self.tcx.emit_spanned_lint(
106+
UNUSED_UNSAFE,
107+
hir_id,
108+
block_span,
109+
UnusedUnsafe { span: block_span, enclosing: enclosing_unsafe },
110+
);
129111
}
130112

131113
/// Whether the `unsafe_op_in_unsafe_fn` lint is `allow`ed at the current HIR node.
@@ -529,81 +511,189 @@ enum UnsafeOpKind {
529511
use UnsafeOpKind::*;
530512

531513
impl UnsafeOpKind {
532-
pub fn simple_description(&self) -> &'static str {
533-
match self {
534-
CallToUnsafeFunction(..) => "call to unsafe function",
535-
UseOfInlineAssembly => "use of inline assembly",
536-
InitializingTypeWith => "initializing type with `rustc_layout_scalar_valid_range` attr",
537-
UseOfMutableStatic => "use of mutable static",
538-
UseOfExternStatic => "use of extern static",
539-
DerefOfRawPointer => "dereference of raw pointer",
540-
AccessToUnionField => "access to union field",
541-
MutationOfLayoutConstrainedField => "mutation of layout constrained field",
542-
BorrowOfLayoutConstrainedField => {
543-
"borrow of layout constrained field with interior mutability"
544-
}
545-
CallToFunctionWith(..) => "call to function with `#[target_feature]`",
546-
}
547-
}
548-
549-
pub fn description_and_note(&self, tcx: TyCtxt<'_>) -> (Cow<'static, str>, &'static str) {
514+
pub fn emit_unsafe_op_in_unsafe_fn_lint(
515+
&self,
516+
tcx: TyCtxt<'_>,
517+
hir_id: hir::HirId,
518+
span: Span,
519+
) {
550520
match self {
551-
CallToUnsafeFunction(did) => (
552-
if let Some(did) = did {
553-
Cow::from(format!("call to unsafe function `{}`", tcx.def_path_str(*did)))
554-
} else {
555-
Cow::Borrowed(self.simple_description())
521+
CallToUnsafeFunction(did) if did.is_some() => tcx.emit_spanned_lint(
522+
UNSAFE_OP_IN_UNSAFE_FN,
523+
hir_id,
524+
span,
525+
UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
526+
span,
527+
function: &tcx.def_path_str(did.unwrap()),
556528
},
557-
"consult the function's documentation for information on how to avoid undefined \
558-
behavior",
559529
),
560-
UseOfInlineAssembly => (
561-
Cow::Borrowed(self.simple_description()),
562-
"inline assembly is entirely unchecked and can cause undefined behavior",
530+
CallToUnsafeFunction(..) => tcx.emit_spanned_lint(
531+
UNSAFE_OP_IN_UNSAFE_FN,
532+
hir_id,
533+
span,
534+
UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span },
535+
),
536+
UseOfInlineAssembly => tcx.emit_spanned_lint(
537+
UNSAFE_OP_IN_UNSAFE_FN,
538+
hir_id,
539+
span,
540+
UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span },
563541
),
564-
InitializingTypeWith => (
565-
Cow::Borrowed(self.simple_description()),
566-
"initializing a layout restricted type's field with a value outside the valid \
567-
range is undefined behavior",
542+
InitializingTypeWith => tcx.emit_spanned_lint(
543+
UNSAFE_OP_IN_UNSAFE_FN,
544+
hir_id,
545+
span,
546+
UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span },
568547
),
569-
UseOfMutableStatic => (
570-
Cow::Borrowed(self.simple_description()),
571-
"mutable statics can be mutated by multiple threads: aliasing violations or data \
572-
races will cause undefined behavior",
548+
UseOfMutableStatic => tcx.emit_spanned_lint(
549+
UNSAFE_OP_IN_UNSAFE_FN,
550+
hir_id,
551+
span,
552+
UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span },
573553
),
574-
UseOfExternStatic => (
575-
Cow::Borrowed(self.simple_description()),
576-
"extern statics are not controlled by the Rust type system: invalid data, \
577-
aliasing violations or data races will cause undefined behavior",
554+
UseOfExternStatic => tcx.emit_spanned_lint(
555+
UNSAFE_OP_IN_UNSAFE_FN,
556+
hir_id,
557+
span,
558+
UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span },
578559
),
579-
DerefOfRawPointer => (
580-
Cow::Borrowed(self.simple_description()),
581-
"raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
582-
and cause data races: all of these are undefined behavior",
560+
DerefOfRawPointer => tcx.emit_spanned_lint(
561+
UNSAFE_OP_IN_UNSAFE_FN,
562+
hir_id,
563+
span,
564+
UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span },
583565
),
584-
AccessToUnionField => (
585-
Cow::Borrowed(self.simple_description()),
586-
"the field may not be properly initialized: using uninitialized data will cause \
587-
undefined behavior",
566+
AccessToUnionField => tcx.emit_spanned_lint(
567+
UNSAFE_OP_IN_UNSAFE_FN,
568+
hir_id,
569+
span,
570+
UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span },
588571
),
589-
MutationOfLayoutConstrainedField => (
590-
Cow::Borrowed(self.simple_description()),
591-
"mutating layout constrained fields cannot statically be checked for valid values",
572+
MutationOfLayoutConstrainedField => tcx.emit_spanned_lint(
573+
UNSAFE_OP_IN_UNSAFE_FN,
574+
hir_id,
575+
span,
576+
UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span },
592577
),
593-
BorrowOfLayoutConstrainedField => (
594-
Cow::Borrowed(self.simple_description()),
595-
"references to fields of layout constrained fields lose the constraints. Coupled \
596-
with interior mutability, the field can be changed to invalid values",
578+
BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint(
579+
UNSAFE_OP_IN_UNSAFE_FN,
580+
hir_id,
581+
span,
582+
UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span },
597583
),
598-
CallToFunctionWith(did) => (
599-
Cow::from(format!(
600-
"call to function `{}` with `#[target_feature]`",
601-
tcx.def_path_str(*did)
602-
)),
603-
"can only be called if the required target features are available",
584+
CallToFunctionWith(did) => tcx.emit_spanned_lint(
585+
UNSAFE_OP_IN_UNSAFE_FN,
586+
hir_id,
587+
span,
588+
UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
589+
span,
590+
function: &tcx.def_path_str(*did),
591+
},
604592
),
605593
}
606594
}
595+
596+
pub fn emit_requires_unsafe_err(
597+
&self,
598+
tcx: TyCtxt<'_>,
599+
span: Span,
600+
unsafe_op_in_unsafe_fn_allowed: bool,
601+
) {
602+
match self {
603+
CallToUnsafeFunction(did) if did.is_some() && unsafe_op_in_unsafe_fn_allowed => {
604+
tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
605+
span,
606+
function: &tcx.def_path_str(did.unwrap()),
607+
});
608+
}
609+
CallToUnsafeFunction(did) if did.is_some() => {
610+
tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafe {
611+
span,
612+
function: &tcx.def_path_str(did.unwrap()),
613+
});
614+
}
615+
CallToUnsafeFunction(..) if unsafe_op_in_unsafe_fn_allowed => {
616+
tcx.sess.emit_err(
617+
CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { span },
618+
);
619+
}
620+
CallToUnsafeFunction(..) => {
621+
tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeNameless { span });
622+
}
623+
UseOfInlineAssembly if unsafe_op_in_unsafe_fn_allowed => {
624+
tcx.sess
625+
.emit_err(UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
626+
}
627+
UseOfInlineAssembly => {
628+
tcx.sess.emit_err(UseOfInlineAssemblyRequiresUnsafe { span });
629+
}
630+
InitializingTypeWith if unsafe_op_in_unsafe_fn_allowed => {
631+
tcx.sess
632+
.emit_err(InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
633+
}
634+
InitializingTypeWith => {
635+
tcx.sess.emit_err(InitializingTypeWithRequiresUnsafe { span });
636+
}
637+
UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => {
638+
tcx.sess
639+
.emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
640+
}
641+
UseOfMutableStatic => {
642+
tcx.sess.emit_err(UseOfMutableStaticRequiresUnsafe { span });
643+
}
644+
UseOfExternStatic if unsafe_op_in_unsafe_fn_allowed => {
645+
tcx.sess
646+
.emit_err(UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
647+
}
648+
UseOfExternStatic => {
649+
tcx.sess.emit_err(UseOfExternStaticRequiresUnsafe { span });
650+
}
651+
DerefOfRawPointer if unsafe_op_in_unsafe_fn_allowed => {
652+
tcx.sess
653+
.emit_err(DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
654+
}
655+
DerefOfRawPointer => {
656+
tcx.sess.emit_err(DerefOfRawPointerRequiresUnsafe { span });
657+
}
658+
AccessToUnionField if unsafe_op_in_unsafe_fn_allowed => {
659+
tcx.sess
660+
.emit_err(AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
661+
}
662+
AccessToUnionField => {
663+
tcx.sess.emit_err(AccessToUnionFieldRequiresUnsafe { span });
664+
}
665+
MutationOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => {
666+
tcx.sess.emit_err(
667+
MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
668+
span,
669+
},
670+
);
671+
}
672+
MutationOfLayoutConstrainedField => {
673+
tcx.sess.emit_err(MutationOfLayoutConstrainedFieldRequiresUnsafe { span });
674+
}
675+
BorrowOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => {
676+
tcx.sess.emit_err(
677+
BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span },
678+
);
679+
}
680+
BorrowOfLayoutConstrainedField => {
681+
tcx.sess.emit_err(BorrowOfLayoutConstrainedFieldRequiresUnsafe { span });
682+
}
683+
CallToFunctionWith(did) if unsafe_op_in_unsafe_fn_allowed => {
684+
tcx.sess.emit_err(CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
685+
span,
686+
function: &tcx.def_path_str(*did),
687+
});
688+
}
689+
CallToFunctionWith(did) => {
690+
tcx.sess.emit_err(CallToFunctionWithRequiresUnsafe {
691+
span,
692+
function: &tcx.def_path_str(*did),
693+
});
694+
}
695+
}
696+
}
607697
}
608698

609699
pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) {

0 commit comments

Comments
 (0)