Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 8b8f665

Browse files
committed
add DefId to unsafety violations and display function path in E0133
this enables consumers to access the function definition that was reported to be unsafe
1 parent d8e59ed commit 8b8f665

File tree

42 files changed

+228
-200
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+228
-200
lines changed

compiler/rustc_middle/src/mir/query.rs

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_index::vec::IndexVec;
1212
use rustc_span::Span;
1313
use rustc_target::abi::VariantIdx;
1414
use smallvec::SmallVec;
15+
use std::borrow::Cow;
1516
use std::cell::Cell;
1617
use std::fmt::{self, Debug};
1718

@@ -28,7 +29,7 @@ pub enum UnsafetyViolationKind {
2829

2930
#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
3031
pub enum UnsafetyViolationDetails {
31-
CallToUnsafeFunction,
32+
CallToUnsafeFunction(Option<DefId>),
3233
UseOfInlineAssembly,
3334
InitializingTypeWith,
3435
CastOfPointerToInt,
@@ -39,66 +40,74 @@ pub enum UnsafetyViolationDetails {
3940
AccessToUnionField,
4041
MutationOfLayoutConstrainedField,
4142
BorrowOfLayoutConstrainedField,
42-
CallToFunctionWith,
43+
CallToFunctionWith(DefId),
4344
}
4445

4546
impl UnsafetyViolationDetails {
46-
pub fn description_and_note(&self) -> (&'static str, &'static str) {
47+
pub fn description_and_note(&self, tcx: TyCtxt<'_>) -> (Cow<'static, str>, &'static str) {
4748
use UnsafetyViolationDetails::*;
4849
match self {
49-
CallToUnsafeFunction => (
50-
"call to unsafe function",
50+
CallToUnsafeFunction(did) => (
51+
if let Some(did) = did {
52+
Cow::from(format!("call to unsafe function `{}`", tcx.def_path_str(*did)))
53+
} else {
54+
Cow::Borrowed("call to unsafe function")
55+
},
5156
"consult the function's documentation for information on how to avoid undefined \
5257
behavior",
5358
),
5459
UseOfInlineAssembly => (
55-
"use of inline assembly",
60+
Cow::Borrowed("use of inline assembly"),
5661
"inline assembly is entirely unchecked and can cause undefined behavior",
5762
),
5863
InitializingTypeWith => (
59-
"initializing type with `rustc_layout_scalar_valid_range` attr",
64+
Cow::Borrowed("initializing type with `rustc_layout_scalar_valid_range` attr"),
6065
"initializing a layout restricted type's field with a value outside the valid \
6166
range is undefined behavior",
6267
),
63-
CastOfPointerToInt => {
64-
("cast of pointer to int", "casting pointers to integers in constants")
65-
}
68+
CastOfPointerToInt => (
69+
Cow::Borrowed("cast of pointer to int"),
70+
"casting pointers to integers in constants",
71+
),
6672
UseOfMutableStatic => (
67-
"use of mutable static",
73+
Cow::Borrowed("use of mutable static"),
6874
"mutable statics can be mutated by multiple threads: aliasing violations or data \
6975
races will cause undefined behavior",
7076
),
7177
UseOfExternStatic => (
72-
"use of extern static",
78+
Cow::Borrowed("use of extern static"),
7379
"extern statics are not controlled by the Rust type system: invalid data, \
7480
aliasing violations or data races will cause undefined behavior",
7581
),
7682
DerefOfRawPointer => (
77-
"dereference of raw pointer",
83+
Cow::Borrowed("dereference of raw pointer"),
7884
"raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
7985
and cause data races: all of these are undefined behavior",
8086
),
8187
AssignToDroppingUnionField => (
82-
"assignment to union field that might need dropping",
88+
Cow::Borrowed("assignment to union field that might need dropping"),
8389
"the previous content of the field will be dropped, which causes undefined \
8490
behavior if the field was not properly initialized",
8591
),
8692
AccessToUnionField => (
87-
"access to union field",
93+
Cow::Borrowed("access to union field"),
8894
"the field may not be properly initialized: using uninitialized data will cause \
8995
undefined behavior",
9096
),
9197
MutationOfLayoutConstrainedField => (
92-
"mutation of layout constrained field",
98+
Cow::Borrowed("mutation of layout constrained field"),
9399
"mutating layout constrained fields cannot statically be checked for valid values",
94100
),
95101
BorrowOfLayoutConstrainedField => (
96-
"borrow of layout constrained field with interior mutability",
102+
Cow::Borrowed("borrow of layout constrained field with interior mutability"),
97103
"references to fields of layout constrained fields lose the constraints. Coupled \
98104
with interior mutability, the field can be changed to invalid values",
99105
),
100-
CallToFunctionWith => (
101-
"call to function with `#[target_feature]`",
106+
CallToFunctionWith(did) => (
107+
Cow::from(format!(
108+
"call to function `{}` with `#[target_feature]`",
109+
tcx.def_path_str(*did)
110+
)),
102111
"can only be called if the required target features are available",
103112
),
104113
}

compiler/rustc_mir_build/src/check_unsafety.rs

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_span::def_id::{DefId, LocalDefId};
1212
use rustc_span::symbol::Symbol;
1313
use rustc_span::Span;
1414

15+
use std::borrow::Cow;
1516
use std::ops::Bound;
1617

1718
struct UnsafetyVisitor<'a, 'tcx> {
@@ -70,7 +71,6 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
7071
}
7172

7273
fn requires_unsafe(&mut self, span: Span, kind: UnsafeOpKind) {
73-
let (description, note) = kind.description_and_note();
7474
let unsafe_op_in_unsafe_fn_allowed = self.unsafe_op_in_unsafe_fn_allowed();
7575
match self.safety_context {
7676
SafetyContext::BuiltinUnsafeBlock => {}
@@ -82,6 +82,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
8282
}
8383
SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
8484
SafetyContext::UnsafeFn => {
85+
let (description, note) = kind.description_and_note(self.tcx);
8586
// unsafe_op_in_unsafe_fn is disallowed
8687
self.tcx.struct_span_lint_hir(
8788
UNSAFE_OP_IN_UNSAFE_FN,
@@ -99,6 +100,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
99100
)
100101
}
101102
SafetyContext::Safe => {
103+
let (description, note) = kind.description_and_note(self.tcx);
102104
let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" };
103105
struct_span_err!(
104106
self.tcx.sess,
@@ -350,7 +352,12 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
350352
}
351353
ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
352354
if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
353-
self.requires_unsafe(expr.span, CallToUnsafeFunction);
355+
let func_id = if let ty::FnDef(func_id, _) = self.thir[fun].ty.kind() {
356+
Some(*func_id)
357+
} else {
358+
None
359+
};
360+
self.requires_unsafe(expr.span, CallToUnsafeFunction(func_id));
354361
} else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() {
355362
// If the called function has target features the calling function hasn't,
356363
// the call requires `unsafe`. Don't check this on wasm
@@ -364,7 +371,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
364371
.iter()
365372
.all(|feature| self.body_target_features.contains(feature))
366373
{
367-
self.requires_unsafe(expr.span, CallToFunctionWith);
374+
self.requires_unsafe(expr.span, CallToFunctionWith(func_did));
368375
}
369376
}
370377
}
@@ -523,7 +530,7 @@ impl BodyUnsafety {
523530

524531
#[derive(Clone, Copy, PartialEq)]
525532
enum UnsafeOpKind {
526-
CallToUnsafeFunction,
533+
CallToUnsafeFunction(Option<DefId>),
527534
UseOfInlineAssembly,
528535
InitializingTypeWith,
529536
UseOfMutableStatic,
@@ -533,64 +540,71 @@ enum UnsafeOpKind {
533540
AccessToUnionField,
534541
MutationOfLayoutConstrainedField,
535542
BorrowOfLayoutConstrainedField,
536-
CallToFunctionWith,
543+
CallToFunctionWith(DefId),
537544
}
538545

539546
use UnsafeOpKind::*;
540547

541548
impl UnsafeOpKind {
542-
pub fn description_and_note(&self) -> (&'static str, &'static str) {
549+
pub fn description_and_note(&self, tcx: TyCtxt<'_>) -> (Cow<'static, str>, &'static str) {
543550
match self {
544-
CallToUnsafeFunction => (
545-
"call to unsafe function",
551+
CallToUnsafeFunction(did) => (
552+
if let Some(did) = did {
553+
Cow::from(format!("call to unsafe function `{}`", tcx.def_path_str(*did)))
554+
} else {
555+
Cow::Borrowed("call to unsafe function")
556+
},
546557
"consult the function's documentation for information on how to avoid undefined \
547558
behavior",
548559
),
549560
UseOfInlineAssembly => (
550-
"use of inline assembly",
561+
Cow::Borrowed("use of inline assembly"),
551562
"inline assembly is entirely unchecked and can cause undefined behavior",
552563
),
553564
InitializingTypeWith => (
554-
"initializing type with `rustc_layout_scalar_valid_range` attr",
565+
Cow::Borrowed("initializing type with `rustc_layout_scalar_valid_range` attr"),
555566
"initializing a layout restricted type's field with a value outside the valid \
556567
range is undefined behavior",
557568
),
558569
UseOfMutableStatic => (
559-
"use of mutable static",
570+
Cow::Borrowed("use of mutable static"),
560571
"mutable statics can be mutated by multiple threads: aliasing violations or data \
561572
races will cause undefined behavior",
562573
),
563574
UseOfExternStatic => (
564-
"use of extern static",
575+
Cow::Borrowed("use of extern static"),
565576
"extern statics are not controlled by the Rust type system: invalid data, \
566577
aliasing violations or data races will cause undefined behavior",
567578
),
568579
DerefOfRawPointer => (
569-
"dereference of raw pointer",
580+
Cow::Borrowed("dereference of raw pointer"),
570581
"raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
571582
and cause data races: all of these are undefined behavior",
572583
),
573584
AssignToDroppingUnionField => (
574-
"assignment to union field that might need dropping",
585+
Cow::Borrowed("assignment to union field that might need dropping"),
575586
"the previous content of the field will be dropped, which causes undefined \
576587
behavior if the field was not properly initialized",
577588
),
578589
AccessToUnionField => (
579-
"access to union field",
590+
Cow::Borrowed("access to union field"),
580591
"the field may not be properly initialized: using uninitialized data will cause \
581592
undefined behavior",
582593
),
583594
MutationOfLayoutConstrainedField => (
584-
"mutation of layout constrained field",
595+
Cow::Borrowed("mutation of layout constrained field"),
585596
"mutating layout constrained fields cannot statically be checked for valid values",
586597
),
587598
BorrowOfLayoutConstrainedField => (
588-
"borrow of layout constrained field with interior mutability",
599+
Cow::Borrowed("borrow of layout constrained field with interior mutability"),
589600
"references to fields of layout constrained fields lose the constraints. Coupled \
590601
with interior mutability, the field can be changed to invalid values",
591602
),
592-
CallToFunctionWith => (
593-
"call to function with `#[target_feature]`",
603+
CallToFunctionWith(did) => (
604+
Cow::from(format!(
605+
"call to function `{}` with `#[target_feature]`",
606+
tcx.def_path_str(*did)
607+
)),
594608
"can only be called if the required target features are available",
595609
),
596610
}

compiler/rustc_mir_transform/src/check_unsafety.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,17 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
7070

7171
TerminatorKind::Call { ref func, .. } => {
7272
let func_ty = func.ty(self.body, self.tcx);
73+
let func_id =
74+
if let ty::FnDef(func_id, _) = func_ty.kind() { Some(func_id) } else { None };
7375
let sig = func_ty.fn_sig(self.tcx);
7476
if let hir::Unsafety::Unsafe = sig.unsafety() {
7577
self.require_unsafe(
7678
UnsafetyViolationKind::General,
77-
UnsafetyViolationDetails::CallToUnsafeFunction,
79+
UnsafetyViolationDetails::CallToUnsafeFunction(func_id.copied()),
7880
)
7981
}
8082

81-
if let ty::FnDef(func_id, _) = func_ty.kind() {
83+
if let Some(func_id) = func_id {
8284
self.check_target_features(*func_id);
8385
}
8486
}
@@ -379,7 +381,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
379381
if !callee_features.iter().all(|feature| self_features.contains(feature)) {
380382
self.require_unsafe(
381383
UnsafetyViolationKind::General,
382-
UnsafetyViolationDetails::CallToFunctionWith,
384+
UnsafetyViolationDetails::CallToFunctionWith(func_did),
383385
)
384386
}
385387
}
@@ -578,7 +580,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
578580
let UnsafetyCheckResult { violations, unused_unsafes, .. } = tcx.unsafety_check_result(def_id);
579581

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

583586
// Report an error.
584587
let unsafe_fn_msg =

src/test/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
1-
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
1+
error[E0133]: call to unsafe function `S::f` is unsafe and requires unsafe function or block
22
--> $DIR/async-unsafe-fn-call-in-safe.rs:14:5
33
|
44
LL | S::f();
5-
| ^^^^^^ call to unsafe function
5+
| ^^^^^^ call to unsafe function `S::f`
66
|
77
= note: consult the function's documentation for information on how to avoid undefined behavior
88

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

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

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

src/test/ui/async-await/async-unsafe-fn-call-in-safe.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ impl S {
1111
async unsafe fn f() {}
1212

1313
async fn g() {
14-
S::f(); //~ ERROR call to unsafe function is unsafe
15-
f(); //~ ERROR call to unsafe function is unsafe
14+
S::f(); //~ ERROR call to unsafe function `S::f` is unsafe
15+
f(); //~ ERROR call to unsafe function `f` is unsafe
1616
}
1717

1818
fn main() {
19-
S::f(); //[mir]~ ERROR call to unsafe function is unsafe
20-
f(); //[mir]~ ERROR call to unsafe function is unsafe
19+
S::f(); //[mir]~ ERROR call to unsafe function `S::f` is unsafe
20+
f(); //[mir]~ ERROR call to unsafe function `f` is unsafe
2121
}

src/test/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
1+
error[E0133]: call to unsafe function `S::f` is unsafe and requires unsafe function or block
22
--> $DIR/async-unsafe-fn-call-in-safe.rs:14:5
33
|
44
LL | S::f();
5-
| ^^^^^^ call to unsafe function
5+
| ^^^^^^ call to unsafe function `S::f`
66
|
77
= note: consult the function's documentation for information on how to avoid undefined behavior
88

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

src/test/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.mir.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
1+
error[E0133]: call to unsafe function `std::pin::Pin::<P>::new_unchecked` is unsafe and requires unsafe function or block
22
--> $DIR/coerce-unsafe-closure-to-unsafe-fn-ptr.rs:5:31
33
|
44
LL | let _: unsafe fn() = || { ::std::pin::Pin::new_unchecked(&0_u8); };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function `std::pin::Pin::<P>::new_unchecked`
66
|
77
= note: consult the function's documentation for information on how to avoid undefined behavior
88

src/test/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.thir.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
1+
error[E0133]: call to unsafe function `Pin::<P>::new_unchecked` is unsafe and requires unsafe function or block
22
--> $DIR/coerce-unsafe-closure-to-unsafe-fn-ptr.rs:5:31
33
|
44
LL | let _: unsafe fn() = || { ::std::pin::Pin::new_unchecked(&0_u8); };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function `Pin::<P>::new_unchecked`
66
|
77
= note: consult the function's documentation for information on how to avoid undefined behavior
88

0 commit comments

Comments
 (0)