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:
Matthias Krüger 2023-07-15 19:42:52 +02:00 committed by GitHub
commit 9b8be2f0e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 176 additions and 26 deletions

View File

@ -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

View File

@ -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),
});
}

View File

@ -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)]

View File

@ -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

View File

@ -1,3 +1,5 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(unused, dead_code)]
static mut FOO: u64 = 0;

View 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`.