Skip to content

Commit 35a99ee

Browse files
committed
Auto merge of #104417 - mejrs:mir_build, r=davidtwco
Migrate rustc_mir_build diagnostics Rebases #100854 ~~The remaining issue is how to better resolve 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 48b3c46 + f7e894c commit 35a99ee

File tree

12 files changed

+1203
-302
lines changed

12 files changed

+1203
-302
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4069,6 +4069,7 @@ dependencies = [
40694069
"rustc_hir",
40704070
"rustc_index",
40714071
"rustc_infer",
4072+
"rustc_macros",
40724073
"rustc_middle",
40734074
"rustc_serialize",
40744075
"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.
@@ -536,81 +518,189 @@ enum UnsafeOpKind {
536518
use UnsafeOpKind::*;
537519

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

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

0 commit comments

Comments
 (0)