Implement "items do not inherit unsafety" for THIR unsafeck

This commit is contained in:
syvb 2023-07-14 22:06:32 -04:00
parent ad963232d9
commit 2cfe8ed37d
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 @@ 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),
});
}

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