Skip to content

Commit 1a11ad7

Browse files
committed
Auto merge of #10405 - Jarcho:issue_10367, r=flip1995
Fix ICE in `multiple_unsafe_ops_per_block` fixes #10367 changelog: [`multiple_unsafe_ops_per_block`]: Fix ICE when calling a function-like object in an unsafe block
2 parents acf70ea + 002e934 commit 1a11ad7

File tree

3 files changed

+99
-28
lines changed

3 files changed

+99
-28
lines changed

clippy_lints/src/multiple_unsafe_ops_per_block.rs

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_ast::Mutability;
1111
use rustc_hir as hir;
1212
use rustc_lint::{LateContext, LateLintPass};
1313
use rustc_middle::lint::in_external_macro;
14+
use rustc_middle::ty;
1415
use rustc_session::{declare_lint_pass, declare_tool_lint};
1516
use rustc_span::Span;
1617

@@ -120,33 +121,15 @@ fn collect_unsafe_exprs<'tcx>(
120121
unsafe_ops.push(("raw pointer dereference occurs here", expr.span));
121122
},
122123

123-
ExprKind::Call(path_expr, _) => match path_expr.kind {
124-
ExprKind::Path(QPath::Resolved(
125-
_,
126-
hir::Path {
127-
res: Res::Def(kind, def_id),
128-
..
129-
},
130-
)) if kind.is_fn_like() => {
131-
let sig = cx.tcx.fn_sig(*def_id);
132-
if sig.0.unsafety() == Unsafety::Unsafe {
133-
unsafe_ops.push(("unsafe function call occurs here", expr.span));
134-
}
135-
},
136-
137-
ExprKind::Path(QPath::TypeRelative(..)) => {
138-
if let Some(sig) = cx
139-
.typeck_results()
140-
.type_dependent_def_id(path_expr.hir_id)
141-
.map(|def_id| cx.tcx.fn_sig(def_id))
142-
{
143-
if sig.0.unsafety() == Unsafety::Unsafe {
144-
unsafe_ops.push(("unsafe function call occurs here", expr.span));
145-
}
146-
}
147-
},
148-
149-
_ => {},
124+
ExprKind::Call(path_expr, _) => {
125+
let sig = match *cx.typeck_results().expr_ty(path_expr).kind() {
126+
ty::FnDef(id, _) => cx.tcx.fn_sig(id).skip_binder(),
127+
ty::FnPtr(sig) => sig,
128+
_ => return Continue(Descend::Yes),
129+
};
130+
if sig.unsafety() == Unsafety::Unsafe {
131+
unsafe_ops.push(("unsafe function call occurs here", expr.span));
132+
}
150133
},
151134

152135
ExprKind::MethodCall(..) => {

tests/ui/multiple_unsafe_ops_per_block.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,32 @@ fn issue10259() {
116116
unsafe_macro!();
117117
}
118118

119+
fn _fn_ptr(x: unsafe fn()) {
120+
unsafe {
121+
x();
122+
x();
123+
}
124+
}
125+
126+
fn _assoc_const() {
127+
trait X {
128+
const X: unsafe fn();
129+
}
130+
fn _f<T: X>() {
131+
unsafe {
132+
T::X();
133+
T::X();
134+
}
135+
}
136+
}
137+
138+
fn _field_fn_ptr(x: unsafe fn()) {
139+
struct X(unsafe fn());
140+
let x = X(x);
141+
unsafe {
142+
x.0();
143+
x.0();
144+
}
145+
}
146+
119147
fn main() {}

tests/ui/multiple_unsafe_ops_per_block.stderr

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,5 +125,65 @@ note: raw pointer dereference occurs here
125125
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
126126
| ^^^^^^^^^^^^^^^^^^
127127

128-
error: aborting due to 5 previous errors
128+
error: this `unsafe` block contains 2 unsafe operations, expected only one
129+
--> $DIR/multiple_unsafe_ops_per_block.rs:120:5
130+
|
131+
LL | / unsafe {
132+
LL | | x();
133+
LL | | x();
134+
LL | | }
135+
| |_____^
136+
|
137+
note: unsafe function call occurs here
138+
--> $DIR/multiple_unsafe_ops_per_block.rs:121:9
139+
|
140+
LL | x();
141+
| ^^^
142+
note: unsafe function call occurs here
143+
--> $DIR/multiple_unsafe_ops_per_block.rs:122:9
144+
|
145+
LL | x();
146+
| ^^^
147+
148+
error: this `unsafe` block contains 2 unsafe operations, expected only one
149+
--> $DIR/multiple_unsafe_ops_per_block.rs:131:9
150+
|
151+
LL | / unsafe {
152+
LL | | T::X();
153+
LL | | T::X();
154+
LL | | }
155+
| |_________^
156+
|
157+
note: unsafe function call occurs here
158+
--> $DIR/multiple_unsafe_ops_per_block.rs:132:13
159+
|
160+
LL | T::X();
161+
| ^^^^^^
162+
note: unsafe function call occurs here
163+
--> $DIR/multiple_unsafe_ops_per_block.rs:133:13
164+
|
165+
LL | T::X();
166+
| ^^^^^^
167+
168+
error: this `unsafe` block contains 2 unsafe operations, expected only one
169+
--> $DIR/multiple_unsafe_ops_per_block.rs:141:5
170+
|
171+
LL | / unsafe {
172+
LL | | x.0();
173+
LL | | x.0();
174+
LL | | }
175+
| |_____^
176+
|
177+
note: unsafe function call occurs here
178+
--> $DIR/multiple_unsafe_ops_per_block.rs:142:9
179+
|
180+
LL | x.0();
181+
| ^^^^^
182+
note: unsafe function call occurs here
183+
--> $DIR/multiple_unsafe_ops_per_block.rs:143:9
184+
|
185+
LL | x.0();
186+
| ^^^^^
187+
188+
error: aborting due to 8 previous errors
129189

0 commit comments

Comments
 (0)