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
This commit is contained in:
parent
d8e59edbfa
commit
8b8f6653cf
42 changed files with 228 additions and 200 deletions
|
@ -12,6 +12,7 @@ use rustc_span::def_id::{DefId, LocalDefId};
|
|||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::ops::Bound;
|
||||
|
||||
struct UnsafetyVisitor<'a, 'tcx> {
|
||||
|
@ -70,7 +71,6 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
|
|||
}
|
||||
|
||||
fn requires_unsafe(&mut self, span: Span, kind: UnsafeOpKind) {
|
||||
let (description, note) = kind.description_and_note();
|
||||
let unsafe_op_in_unsafe_fn_allowed = self.unsafe_op_in_unsafe_fn_allowed();
|
||||
match self.safety_context {
|
||||
SafetyContext::BuiltinUnsafeBlock => {}
|
||||
|
@ -82,6 +82,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
|
|||
}
|
||||
SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
|
||||
SafetyContext::UnsafeFn => {
|
||||
let (description, note) = kind.description_and_note(self.tcx);
|
||||
// unsafe_op_in_unsafe_fn is disallowed
|
||||
self.tcx.struct_span_lint_hir(
|
||||
UNSAFE_OP_IN_UNSAFE_FN,
|
||||
|
@ -99,6 +100,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
|
|||
)
|
||||
}
|
||||
SafetyContext::Safe => {
|
||||
let (description, note) = kind.description_and_note(self.tcx);
|
||||
let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" };
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
|
@ -350,7 +352,12 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||
}
|
||||
ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
|
||||
if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
|
||||
self.requires_unsafe(expr.span, CallToUnsafeFunction);
|
||||
let func_id = if let ty::FnDef(func_id, _) = self.thir[fun].ty.kind() {
|
||||
Some(*func_id)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.requires_unsafe(expr.span, CallToUnsafeFunction(func_id));
|
||||
} else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() {
|
||||
// If the called function has target features the calling function hasn't,
|
||||
// the call requires `unsafe`. Don't check this on wasm
|
||||
|
@ -364,7 +371,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||
.iter()
|
||||
.all(|feature| self.body_target_features.contains(feature))
|
||||
{
|
||||
self.requires_unsafe(expr.span, CallToFunctionWith);
|
||||
self.requires_unsafe(expr.span, CallToFunctionWith(func_did));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -523,7 +530,7 @@ impl BodyUnsafety {
|
|||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum UnsafeOpKind {
|
||||
CallToUnsafeFunction,
|
||||
CallToUnsafeFunction(Option<DefId>),
|
||||
UseOfInlineAssembly,
|
||||
InitializingTypeWith,
|
||||
UseOfMutableStatic,
|
||||
|
@ -533,64 +540,71 @@ enum UnsafeOpKind {
|
|||
AccessToUnionField,
|
||||
MutationOfLayoutConstrainedField,
|
||||
BorrowOfLayoutConstrainedField,
|
||||
CallToFunctionWith,
|
||||
CallToFunctionWith(DefId),
|
||||
}
|
||||
|
||||
use UnsafeOpKind::*;
|
||||
|
||||
impl UnsafeOpKind {
|
||||
pub fn description_and_note(&self) -> (&'static str, &'static str) {
|
||||
pub fn description_and_note(&self, tcx: TyCtxt<'_>) -> (Cow<'static, str>, &'static str) {
|
||||
match self {
|
||||
CallToUnsafeFunction => (
|
||||
"call to unsafe function",
|
||||
CallToUnsafeFunction(did) => (
|
||||
if let Some(did) = did {
|
||||
Cow::from(format!("call to unsafe function `{}`", tcx.def_path_str(*did)))
|
||||
} else {
|
||||
Cow::Borrowed("call to unsafe function")
|
||||
},
|
||||
"consult the function's documentation for information on how to avoid undefined \
|
||||
behavior",
|
||||
),
|
||||
UseOfInlineAssembly => (
|
||||
"use of inline assembly",
|
||||
Cow::Borrowed("use of inline assembly"),
|
||||
"inline assembly is entirely unchecked and can cause undefined behavior",
|
||||
),
|
||||
InitializingTypeWith => (
|
||||
"initializing type with `rustc_layout_scalar_valid_range` attr",
|
||||
Cow::Borrowed("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",
|
||||
),
|
||||
UseOfMutableStatic => (
|
||||
"use of mutable static",
|
||||
Cow::Borrowed("use of mutable static"),
|
||||
"mutable statics can be mutated by multiple threads: aliasing violations or data \
|
||||
races will cause undefined behavior",
|
||||
),
|
||||
UseOfExternStatic => (
|
||||
"use of extern static",
|
||||
Cow::Borrowed("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 => (
|
||||
"dereference of raw pointer",
|
||||
Cow::Borrowed("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 => (
|
||||
"assignment to union field that might need dropping",
|
||||
Cow::Borrowed("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 => (
|
||||
"access to union field",
|
||||
Cow::Borrowed("access to union field"),
|
||||
"the field may not be properly initialized: using uninitialized data will cause \
|
||||
undefined behavior",
|
||||
),
|
||||
MutationOfLayoutConstrainedField => (
|
||||
"mutation of layout constrained field",
|
||||
Cow::Borrowed("mutation of layout constrained field"),
|
||||
"mutating layout constrained fields cannot statically be checked for valid values",
|
||||
),
|
||||
BorrowOfLayoutConstrainedField => (
|
||||
"borrow of layout constrained field with interior mutability",
|
||||
Cow::Borrowed("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 => (
|
||||
"call to function with `#[target_feature]`",
|
||||
CallToFunctionWith(did) => (
|
||||
Cow::from(format!(
|
||||
"call to function `{}` with `#[target_feature]`",
|
||||
tcx.def_path_str(*did)
|
||||
)),
|
||||
"can only be called if the required target features are available",
|
||||
),
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue