diff options
| author | Jason Newcomb <jsnewcomb@pm.me> | 2023-02-26 02:55:52 -0500 |
|---|---|---|
| committer | Jason Newcomb <jsnewcomb@pm.me> | 2023-02-26 02:55:52 -0500 |
| commit | 002e9341891c95886b3eb29dfa9be1d50d8096d4 (patch) | |
| tree | 79a3f645051d6ab41cc1f6371f41625163293484 | |
| parent | 3d193fa17a7df3256d58b841a2df92af1cbdbea4 (diff) | |
| download | rust-002e9341891c95886b3eb29dfa9be1d50d8096d4.tar.gz rust-002e9341891c95886b3eb29dfa9be1d50d8096d4.zip | |
Don't assume paths work with `fn_sig` in `multiple_unsafe_ops_pre_block`.
| -rw-r--r-- | clippy_lints/src/multiple_unsafe_ops_per_block.rs | 37 | ||||
| -rw-r--r-- | tests/ui/multiple_unsafe_ops_per_block.rs | 28 | ||||
| -rw-r--r-- | tests/ui/multiple_unsafe_ops_per_block.stderr | 62 |
3 files changed, 99 insertions, 28 deletions
diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 63c575fca30..5418616ded0 100644 --- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -11,6 +11,7 @@ use rustc_ast::Mutability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; @@ -120,33 +121,15 @@ fn collect_unsafe_exprs<'tcx>( unsafe_ops.push(("raw pointer dereference occurs here", expr.span)); }, - ExprKind::Call(path_expr, _) => match path_expr.kind { - ExprKind::Path(QPath::Resolved( - _, - hir::Path { - res: Res::Def(kind, def_id), - .. - }, - )) if kind.is_fn_like() => { - let sig = cx.tcx.fn_sig(*def_id); - if sig.0.unsafety() == Unsafety::Unsafe { - unsafe_ops.push(("unsafe function call occurs here", expr.span)); - } - }, - - ExprKind::Path(QPath::TypeRelative(..)) => { - if let Some(sig) = cx - .typeck_results() - .type_dependent_def_id(path_expr.hir_id) - .map(|def_id| cx.tcx.fn_sig(def_id)) - { - if sig.0.unsafety() == Unsafety::Unsafe { - unsafe_ops.push(("unsafe function call occurs here", expr.span)); - } - } - }, - - _ => {}, + ExprKind::Call(path_expr, _) => { + let sig = match *cx.typeck_results().expr_ty(path_expr).kind() { + ty::FnDef(id, _) => cx.tcx.fn_sig(id).skip_binder(), + ty::FnPtr(sig) => sig, + _ => return Continue(Descend::Yes), + }; + if sig.unsafety() == Unsafety::Unsafe { + unsafe_ops.push(("unsafe function call occurs here", expr.span)); + } }, ExprKind::MethodCall(..) => { diff --git a/tests/ui/multiple_unsafe_ops_per_block.rs b/tests/ui/multiple_unsafe_ops_per_block.rs index 4511bc99c3c..5073685c9f0 100644 --- a/tests/ui/multiple_unsafe_ops_per_block.rs +++ b/tests/ui/multiple_unsafe_ops_per_block.rs @@ -116,4 +116,32 @@ fn issue10259() { unsafe_macro!(); } +fn _fn_ptr(x: unsafe fn()) { + unsafe { + x(); + x(); + } +} + +fn _assoc_const() { + trait X { + const X: unsafe fn(); + } + fn _f<T: X>() { + unsafe { + T::X(); + T::X(); + } + } +} + +fn _field_fn_ptr(x: unsafe fn()) { + struct X(unsafe fn()); + let x = X(x); + unsafe { + x.0(); + x.0(); + } +} + fn main() {} diff --git a/tests/ui/multiple_unsafe_ops_per_block.stderr b/tests/ui/multiple_unsafe_ops_per_block.stderr index 303aeb7aee0..e0c1d3801f7 100644 --- a/tests/ui/multiple_unsafe_ops_per_block.stderr +++ b/tests/ui/multiple_unsafe_ops_per_block.stderr @@ -125,5 +125,65 @@ note: raw pointer dereference occurs here LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) } | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: this `unsafe` block contains 2 unsafe operations, expected only one + --> $DIR/multiple_unsafe_ops_per_block.rs:120:5 + | +LL | / unsafe { +LL | | x(); +LL | | x(); +LL | | } + | |_____^ + | +note: unsafe function call occurs here + --> $DIR/multiple_unsafe_ops_per_block.rs:121:9 + | +LL | x(); + | ^^^ +note: unsafe function call occurs here + --> $DIR/multiple_unsafe_ops_per_block.rs:122:9 + | +LL | x(); + | ^^^ + +error: this `unsafe` block contains 2 unsafe operations, expected only one + --> $DIR/multiple_unsafe_ops_per_block.rs:131:9 + | +LL | / unsafe { +LL | | T::X(); +LL | | T::X(); +LL | | } + | |_________^ + | +note: unsafe function call occurs here + --> $DIR/multiple_unsafe_ops_per_block.rs:132:13 + | +LL | T::X(); + | ^^^^^^ +note: unsafe function call occurs here + --> $DIR/multiple_unsafe_ops_per_block.rs:133:13 + | +LL | T::X(); + | ^^^^^^ + +error: this `unsafe` block contains 2 unsafe operations, expected only one + --> $DIR/multiple_unsafe_ops_per_block.rs:141:5 + | +LL | / unsafe { +LL | | x.0(); +LL | | x.0(); +LL | | } + | |_____^ + | +note: unsafe function call occurs here + --> $DIR/multiple_unsafe_ops_per_block.rs:142:9 + | +LL | x.0(); + | ^^^^^ +note: unsafe function call occurs here + --> $DIR/multiple_unsafe_ops_per_block.rs:143:9 + | +LL | x.0(); + | ^^^^^ + +error: aborting due to 8 previous errors |
