Rollup merge of #113663 - syvb:non_inherited_unsafe_thir, r=cjgillot
Implement "items do not inherit unsafety" note for THIR unsafeck Implements the "items do not inherit unsafety from separate enclosing items" note from the MIR unsafety checker in the THIR unsafety checker (`-Z thir-unsafeck`) to maintain parity between the two unsafety checkers. The logic to find the separate enclosing item is nearly the same as in the MIR unsafety checker.
This commit is contained in:
commit
9b8be2f0e1
@ -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
|
||||
|
@ -91,7 +91,12 @@ fn requires_unsafe(&mut self, span: Span, kind: UnsafeOpKind) {
|
||||
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 @@ pub fn emit_requires_unsafe_err(
|
||||
&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),
|
||||
});
|
||||
}
|
||||
|
@ -119,6 +119,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafe<'a> {
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub function: &'a str,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -128,6 +130,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNameless {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[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<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -150,6 +156,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -159,6 +167,8 @@ pub struct UseOfInlineAssemblyRequiresUnsafe {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -168,6 +178,8 @@ pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -177,6 +189,8 @@ pub struct InitializingTypeWithRequiresUnsafe {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -189,6 +203,8 @@ pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -198,6 +214,8 @@ pub struct UseOfMutableStaticRequiresUnsafe {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -207,6 +225,8 @@ pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -216,6 +236,8 @@ pub struct UseOfExternStaticRequiresUnsafe {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -225,6 +247,8 @@ pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -234,6 +258,8 @@ pub struct DerefOfRawPointerRequiresUnsafe {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -243,6 +269,8 @@ pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -252,6 +280,8 @@ pub struct AccessToUnionFieldRequiresUnsafe {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -261,6 +291,8 @@ pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -270,6 +302,8 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -282,6 +316,8 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllow
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -291,6 +327,8 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -303,6 +341,8 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[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<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[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<UnsafeNotInheritedNote>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[label(mir_build_unsafe_not_inherited)]
|
||||
pub struct UnsafeNotInheritedNote {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
@ -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
|
@ -1,3 +1,5 @@
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
#![allow(unused, dead_code)]
|
||||
|
||||
static mut FOO: u64 = 0;
|
||||
|
24
tests/ui/unsafe/unsafe-not-inherited.thirunsafeck.stderr
Normal file
24
tests/ui/unsafe/unsafe-not-inherited.thirunsafeck.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user