diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 98156840dd8..938f3edd31b 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -312,6 +312,8 @@ mir_build_unreachable_pattern = unreachable pattern .label = unreachable pattern .catchall_label = matches any value +mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items + mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe = borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133) .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 8b4ff9bb868..192bd4a83e3 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -91,7 +91,12 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span); } SafetyContext::Safe => { - kind.emit_requires_unsafe_err(self.tcx, span, unsafe_op_in_unsafe_fn_allowed); + kind.emit_requires_unsafe_err( + self.tcx, + span, + self.hir_context, + unsafe_op_in_unsafe_fn_allowed, + ); } } } @@ -602,98 +607,164 @@ impl UnsafeOpKind { &self, tcx: TyCtxt<'_>, span: Span, + hir_context: hir::HirId, unsafe_op_in_unsafe_fn_allowed: bool, ) { + let note_non_inherited = tcx.hir().parent_iter(hir_context).find(|(id, node)| { + if let hir::Node::Expr(block) = node + && let hir::ExprKind::Block(block, _) = block.kind + && let hir::BlockCheckMode::UnsafeBlock(_) = block.rules + { + true + } + else if let Some(sig) = tcx.hir().fn_sig_by_hir_id(*id) + && sig.header.is_unsafe() + { + true + } else { + false + } + }); + let unsafe_not_inherited_note = if let Some((id, _)) = note_non_inherited { + let span = tcx.hir().span(id); + let span = tcx.sess.source_map().guess_head_span(span); + Some(UnsafeNotInheritedNote { span }) + } else { + None + }; + match self { CallToUnsafeFunction(Some(did)) if unsafe_op_in_unsafe_fn_allowed => { tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, + unsafe_not_inherited_note, function: &tcx.def_path_str(*did), }); } CallToUnsafeFunction(Some(did)) => { tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafe { span, + unsafe_not_inherited_note, function: &tcx.def_path_str(*did), }); } CallToUnsafeFunction(None) if unsafe_op_in_unsafe_fn_allowed => { tcx.sess.emit_err( - CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { span }, + CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }, ); } CallToUnsafeFunction(None) => { - tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeNameless { span }); + tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeNameless { + span, + unsafe_not_inherited_note, + }); } UseOfInlineAssembly if unsafe_op_in_unsafe_fn_allowed => { - tcx.sess - .emit_err(UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + tcx.sess.emit_err(UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }); } UseOfInlineAssembly => { - tcx.sess.emit_err(UseOfInlineAssemblyRequiresUnsafe { span }); + tcx.sess.emit_err(UseOfInlineAssemblyRequiresUnsafe { + span, + unsafe_not_inherited_note, + }); } InitializingTypeWith if unsafe_op_in_unsafe_fn_allowed => { - tcx.sess - .emit_err(InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + tcx.sess.emit_err(InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }); } InitializingTypeWith => { - tcx.sess.emit_err(InitializingTypeWithRequiresUnsafe { span }); + tcx.sess.emit_err(InitializingTypeWithRequiresUnsafe { + span, + unsafe_not_inherited_note, + }); } UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => { - tcx.sess - .emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + tcx.sess.emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }); } UseOfMutableStatic => { - tcx.sess.emit_err(UseOfMutableStaticRequiresUnsafe { span }); + tcx.sess + .emit_err(UseOfMutableStaticRequiresUnsafe { span, unsafe_not_inherited_note }); } UseOfExternStatic if unsafe_op_in_unsafe_fn_allowed => { - tcx.sess - .emit_err(UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + tcx.sess.emit_err(UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }); } UseOfExternStatic => { - tcx.sess.emit_err(UseOfExternStaticRequiresUnsafe { span }); + tcx.sess + .emit_err(UseOfExternStaticRequiresUnsafe { span, unsafe_not_inherited_note }); } DerefOfRawPointer if unsafe_op_in_unsafe_fn_allowed => { - tcx.sess - .emit_err(DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + tcx.sess.emit_err(DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }); } DerefOfRawPointer => { - tcx.sess.emit_err(DerefOfRawPointerRequiresUnsafe { span }); + tcx.sess + .emit_err(DerefOfRawPointerRequiresUnsafe { span, unsafe_not_inherited_note }); } AccessToUnionField if unsafe_op_in_unsafe_fn_allowed => { - tcx.sess - .emit_err(AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + tcx.sess.emit_err(AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }); } AccessToUnionField => { - tcx.sess.emit_err(AccessToUnionFieldRequiresUnsafe { span }); + tcx.sess + .emit_err(AccessToUnionFieldRequiresUnsafe { span, unsafe_not_inherited_note }); } MutationOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => { tcx.sess.emit_err( MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, + unsafe_not_inherited_note, }, ); } MutationOfLayoutConstrainedField => { - tcx.sess.emit_err(MutationOfLayoutConstrainedFieldRequiresUnsafe { span }); + tcx.sess.emit_err(MutationOfLayoutConstrainedFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }); } BorrowOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => { tcx.sess.emit_err( - BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }, + BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }, ); } BorrowOfLayoutConstrainedField => { - tcx.sess.emit_err(BorrowOfLayoutConstrainedFieldRequiresUnsafe { span }); + tcx.sess.emit_err(BorrowOfLayoutConstrainedFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }); } CallToFunctionWith(did) if unsafe_op_in_unsafe_fn_allowed => { tcx.sess.emit_err(CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, + unsafe_not_inherited_note, function: &tcx.def_path_str(*did), }); } CallToFunctionWith(did) => { tcx.sess.emit_err(CallToFunctionWithRequiresUnsafe { span, + unsafe_not_inherited_note, function: &tcx.def_path_str(*did), }); } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index df00cc75cc7..820ab93851e 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -119,6 +119,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -128,6 +130,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNameless { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -138,6 +142,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -150,6 +156,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -159,6 +167,8 @@ pub struct UseOfInlineAssemblyRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -168,6 +178,8 @@ pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -177,6 +189,8 @@ pub struct InitializingTypeWithRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -189,6 +203,8 @@ pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -198,6 +214,8 @@ pub struct UseOfMutableStaticRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -207,6 +225,8 @@ pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -216,6 +236,8 @@ pub struct UseOfExternStaticRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -225,6 +247,8 @@ pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -234,6 +258,8 @@ pub struct DerefOfRawPointerRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -243,6 +269,8 @@ pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -252,6 +280,8 @@ pub struct AccessToUnionFieldRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -261,6 +291,8 @@ pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -270,6 +302,8 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -282,6 +316,8 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllow #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -291,6 +327,8 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -303,6 +341,8 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -313,6 +353,8 @@ pub struct CallToFunctionWithRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -323,6 +365,15 @@ pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, +} + +#[derive(Subdiagnostic)] +#[label(mir_build_unsafe_not_inherited)] +pub struct UnsafeNotInheritedNote { + #[primary_span] + pub span: Span, } #[derive(LintDiagnostic)] diff --git a/tests/ui/unsafe/unsafe-not-inherited.stderr b/tests/ui/unsafe/unsafe-not-inherited.mirunsafeck.stderr similarity index 91% rename from tests/ui/unsafe/unsafe-not-inherited.stderr rename to tests/ui/unsafe/unsafe-not-inherited.mirunsafeck.stderr index 3bc5ca5c9d1..5536efbc6f4 100644 --- a/tests/ui/unsafe/unsafe-not-inherited.stderr +++ b/tests/ui/unsafe/unsafe-not-inherited.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0133]: use of mutable static is unsafe and requires unsafe function or block - --> $DIR/unsafe-not-inherited.rs:6:31 + --> $DIR/unsafe-not-inherited.rs:8:31 | LL | unsafe {static BAR: u64 = FOO;} | ------ ^^^ use of mutable static @@ -9,7 +9,7 @@ LL | unsafe {static BAR: u64 = FOO;} = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/unsafe-not-inherited.rs:18:13 + --> $DIR/unsafe-not-inherited.rs:20:13 | LL | unsafe { | ------ items do not inherit unsafety from separate enclosing items diff --git a/tests/ui/unsafe/unsafe-not-inherited.rs b/tests/ui/unsafe/unsafe-not-inherited.rs index 6d797caa0f9..f9d9a595714 100644 --- a/tests/ui/unsafe/unsafe-not-inherited.rs +++ b/tests/ui/unsafe/unsafe-not-inherited.rs @@ -1,3 +1,5 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck #![allow(unused, dead_code)] static mut FOO: u64 = 0; diff --git a/tests/ui/unsafe/unsafe-not-inherited.thirunsafeck.stderr b/tests/ui/unsafe/unsafe-not-inherited.thirunsafeck.stderr new file mode 100644 index 00000000000..88ea2e6d1fe --- /dev/null +++ b/tests/ui/unsafe/unsafe-not-inherited.thirunsafeck.stderr @@ -0,0 +1,24 @@ +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/unsafe-not-inherited.rs:8:31 + | +LL | unsafe {static BAR: u64 = FOO;} + | ------ ^^^ use of mutable static + | | + | items do not inherit unsafety from separate enclosing items + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: call to unsafe function `unsafe_call` is unsafe and requires unsafe function or block + --> $DIR/unsafe-not-inherited.rs:20:13 + | +LL | unsafe { + | ------ items do not inherit unsafety from separate enclosing items +... +LL | unsafe_call(); + | ^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`.