Skip to content

Fix incremental perf regression unsafety checking #96425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 19 additions & 49 deletions compiler/rustc_middle/src/mir/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use rustc_index::vec::IndexVec;
use rustc_span::Span;
use rustc_target::abi::VariantIdx;
use smallvec::SmallVec;
use std::borrow::Cow;
use std::cell::Cell;
use std::fmt::{self, Debug};

Expand All @@ -29,7 +28,7 @@ pub enum UnsafetyViolationKind {

#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
pub enum UnsafetyViolationDetails {
CallToUnsafeFunction(Option<DefId>),
CallToUnsafeFunction,
UseOfInlineAssembly,
InitializingTypeWith,
CastOfPointerToInt,
Expand All @@ -40,95 +39,66 @@ pub enum UnsafetyViolationDetails {
AccessToUnionField,
MutationOfLayoutConstrainedField,
BorrowOfLayoutConstrainedField,
CallToFunctionWith(DefId),
CallToFunctionWith,
}

impl UnsafetyViolationDetails {
pub fn simple_description(&self) -> &'static str {
use UnsafetyViolationDetails::*;

match self {
CallToUnsafeFunction(..) => "call to unsafe function",
UseOfInlineAssembly => "use of inline assembly",
InitializingTypeWith => "initializing type with `rustc_layout_scalar_valid_range` attr",
CastOfPointerToInt => "cast of pointer to int",
UseOfMutableStatic => "use of mutable static",
UseOfExternStatic => "use of extern static",
DerefOfRawPointer => "dereference of raw pointer",
AssignToDroppingUnionField => "assignment to union field that might need dropping",
AccessToUnionField => "access to union field",
MutationOfLayoutConstrainedField => "mutation of layout constrained field",
BorrowOfLayoutConstrainedField => {
"borrow of layout constrained field with interior mutability"
}
CallToFunctionWith(..) => "call to function with `#[target_feature]`",
}
}

pub fn description_and_note(&self, tcx: TyCtxt<'_>) -> (Cow<'static, str>, &'static str) {
pub fn description_and_note(&self) -> (&'static str, &'static str) {
use UnsafetyViolationDetails::*;
match self {
CallToUnsafeFunction(did) => (
if let Some(did) = did {
Cow::from(format!("call to unsafe function `{}`", tcx.def_path_str(*did)))
} else {
Cow::Borrowed(self.simple_description())
},
CallToUnsafeFunction => (
"call to unsafe function",
"consult the function's documentation for information on how to avoid undefined \
behavior",
),
UseOfInlineAssembly => (
Cow::Borrowed(self.simple_description()),
"use of inline assembly",
"inline assembly is entirely unchecked and can cause undefined behavior",
),
InitializingTypeWith => (
Cow::Borrowed(self.simple_description()),
"initializing type with `rustc_layout_scalar_valid_range` attr",
"initializing a layout restricted type's field with a value outside the valid \
range is undefined behavior",
),
CastOfPointerToInt => (
Cow::Borrowed(self.simple_description()),
"casting pointers to integers in constants",
),
CastOfPointerToInt => {
("cast of pointer to int", "casting pointers to integers in constants")
}
UseOfMutableStatic => (
Cow::Borrowed(self.simple_description()),
"use of mutable static",
"mutable statics can be mutated by multiple threads: aliasing violations or data \
races will cause undefined behavior",
),
UseOfExternStatic => (
Cow::Borrowed(self.simple_description()),
"use of extern static",
"extern statics are not controlled by the Rust type system: invalid data, \
aliasing violations or data races will cause undefined behavior",
),
DerefOfRawPointer => (
Cow::Borrowed(self.simple_description()),
"dereference of raw pointer",
"raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
and cause data races: all of these are undefined behavior",
),
AssignToDroppingUnionField => (
Cow::Borrowed(self.simple_description()),
"assignment to union field that might need dropping",
"the previous content of the field will be dropped, which causes undefined \
behavior if the field was not properly initialized",
),
AccessToUnionField => (
Cow::Borrowed(self.simple_description()),
"access to union field",
"the field may not be properly initialized: using uninitialized data will cause \
undefined behavior",
),
MutationOfLayoutConstrainedField => (
Cow::Borrowed(self.simple_description()),
"mutation of layout constrained field",
"mutating layout constrained fields cannot statically be checked for valid values",
),
BorrowOfLayoutConstrainedField => (
Cow::Borrowed(self.simple_description()),
"borrow of layout constrained field with interior mutability",
"references to fields of layout constrained fields lose the constraints. Coupled \
with interior mutability, the field can be changed to invalid values",
),
CallToFunctionWith(did) => (
Cow::from(format!(
"call to function `{}` with `#[target_feature]`",
tcx.def_path_str(*did)
)),
CallToFunctionWith => (
"call to function with `#[target_feature]`",
"can only be called if the required target features are available",
),
}
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_mir_transform/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
if let hir::Unsafety::Unsafe = sig.unsafety() {
self.require_unsafe(
UnsafetyViolationKind::General,
UnsafetyViolationDetails::CallToUnsafeFunction(func_id.copied()),
UnsafetyViolationDetails::CallToUnsafeFunction,
)
}

Expand Down Expand Up @@ -381,7 +381,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
if !callee_features.iter().all(|feature| self_features.contains(feature)) {
self.require_unsafe(
UnsafetyViolationKind::General,
UnsafetyViolationDetails::CallToFunctionWith(func_did),
UnsafetyViolationDetails::CallToFunctionWith,
)
}
}
Expand Down Expand Up @@ -580,8 +580,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let UnsafetyCheckResult { violations, unused_unsafes, .. } = tcx.unsafety_check_result(def_id);

for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() {
let (description, note) =
ty::print::with_no_trimmed_paths!(details.description_and_note(tcx));
let (description, note) = details.description_and_note();

// Report an error.
let unsafe_fn_msg =
Expand All @@ -598,7 +597,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
description,
unsafe_fn_msg,
)
.span_label(source_info.span, details.simple_description())
.span_label(source_info.span, description)
.note(note)
.emit();
}
Expand Down
14 changes: 7 additions & 7 deletions src/test/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
error[E0133]: call to unsafe function `S::f` is unsafe and requires unsafe function or block
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/async-unsafe-fn-call-in-safe.rs:14:5
|
LL | S::f();
| ^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior

error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block
--> $DIR/async-unsafe-fn-call-in-safe.rs:15:5
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/async-unsafe-fn-call-in-safe.rs:17:5
|
LL | f();
| ^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior

error[E0133]: call to unsafe function `S::f` is unsafe and requires unsafe function or block
--> $DIR/async-unsafe-fn-call-in-safe.rs:19:5
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/async-unsafe-fn-call-in-safe.rs:23:5
|
LL | S::f();
| ^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior

error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block
--> $DIR/async-unsafe-fn-call-in-safe.rs:20:5
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/async-unsafe-fn-call-in-safe.rs:24:5
|
LL | f();
| ^^^ call to unsafe function
Expand Down
12 changes: 8 additions & 4 deletions src/test/ui/async-await/async-unsafe-fn-call-in-safe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@ impl S {
async unsafe fn f() {}

async fn g() {
S::f(); //~ ERROR call to unsafe function `S::f` is unsafe
f(); //~ ERROR call to unsafe function `f` is unsafe
S::f();
//[mir]~^ ERROR call to unsafe function is unsafe
//[thir]~^^ ERROR call to unsafe function `S::f` is unsafe
f();
//[mir]~^ ERROR call to unsafe function is unsafe
//[thir]~^^ ERROR call to unsafe function `f` is unsafe
}

fn main() {
S::f(); //[mir]~ ERROR call to unsafe function `S::f` is unsafe
f(); //[mir]~ ERROR call to unsafe function `f` is unsafe
S::f(); //[mir]~ ERROR call to unsafe function is unsafe
f(); //[mir]~ ERROR call to unsafe function is unsafe
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ LL | S::f();
= note: consult the function's documentation for information on how to avoid undefined behavior

error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block
--> $DIR/async-unsafe-fn-call-in-safe.rs:15:5
--> $DIR/async-unsafe-fn-call-in-safe.rs:17:5
|
LL | f();
| ^^^ call to unsafe function
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0133]: call to unsafe function `std::pin::Pin::<P>::new_unchecked` is unsafe and requires unsafe function or block
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/coerce-unsafe-closure-to-unsafe-fn-ptr.rs:5:31
|
LL | let _: unsafe fn() = || { ::std::pin::Pin::new_unchecked(&0_u8); };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/const-extern-fn-requires-unsafe.rs:9:17
|
LL | let a: [u8; foo()];
| ^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior

error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block
--> $DIR/const-extern-fn-requires-unsafe.rs:11:5
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/const-extern-fn-requires-unsafe.rs:12:5
|
LL | foo();
| ^^^^^ call to unsafe function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const unsafe extern "C" fn foo() -> usize { 5 }

fn main() {
let a: [u8; foo()];
//~^ ERROR call to unsafe function `foo` is unsafe and requires unsafe function or block
//[mir]~^ call to unsafe function is unsafe and requires unsafe function or block
//[thir]~^^ call to unsafe function `foo` is unsafe and requires unsafe function or block
foo();
//[mir]~^ ERROR call to unsafe function `foo` is unsafe and requires unsafe function or block
//[mir]~^ ERROR call to unsafe function is unsafe and requires unsafe function or block
}
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0133.mir.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/E0133.rs:7:5
|
LL | f();
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/foreign-unsafe-fn-called.mir.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0133]: call to unsafe function `test::free` is unsafe and requires unsafe function or block
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/foreign-unsafe-fn-called.rs:11:5
|
LL | test::free();
Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/foreign-unsafe-fn-called.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ mod test {

fn main() {
test::free();
//~^ ERROR call to unsafe function `test::free` is unsafe
//[mir]~^ ERROR call to unsafe function is unsafe
//[thir]~^^ ERROR call to unsafe function `test::free` is unsafe
}
6 changes: 3 additions & 3 deletions src/test/ui/intrinsics/unchecked_math_unsafe.mir.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
error[E0133]: call to unsafe function `std::intrinsics::unchecked_add` is unsafe and requires unsafe function or block
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/unchecked_math_unsafe.rs:8:15
|
LL | let add = std::intrinsics::unchecked_add(x, y);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior

error[E0133]: call to unsafe function `std::intrinsics::unchecked_sub` is unsafe and requires unsafe function or block
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/unchecked_math_unsafe.rs:9:15
|
LL | let sub = std::intrinsics::unchecked_sub(x, y);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior

error[E0133]: call to unsafe function `std::intrinsics::unchecked_mul` is unsafe and requires unsafe function or block
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/unchecked_math_unsafe.rs:10:15
|
LL | let mul = std::intrinsics::unchecked_mul(x, y);
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-28776.mir.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0133]: call to unsafe function `std::ptr::write` is unsafe and requires unsafe function or block
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/issue-28776.rs:7:5
|
LL | (&ptr::write)(1 as *mut _, 42);
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-3080.mir.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0133]: call to unsafe function `X::with` is unsafe and requires unsafe function or block
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/issue-3080.rs:10:5
|
LL | X(()).with();
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-5844.mir.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0133]: call to unsafe function `issue_5844_aux::rand` is unsafe and requires unsafe function or block
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/issue-5844.rs:8:5
|
LL | issue_5844_aux::rand();
Expand Down
Loading