Skip to content

Commit 631120b

Browse files
committed
fix: unwrap_used and expect_used FN when using fully qualified syntax
1 parent dc8b277 commit 631120b

File tree

4 files changed

+139
-1
lines changed

4 files changed

+139
-1
lines changed

clippy_lints/src/methods/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4965,6 +4965,16 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
49654965
io_other_error::check(cx, expr, func, args, self.msrv);
49664966
swap_with_temporary::check(cx, expr, func, args);
49674967
ip_constant::check(cx, expr, func, args);
4968+
unwrap_expect_used::check_call(
4969+
cx,
4970+
expr,
4971+
func,
4972+
args,
4973+
self.allow_unwrap_in_tests,
4974+
self.allow_expect_in_tests,
4975+
self.allow_unwrap_in_consts,
4976+
self.allow_expect_in_consts,
4977+
);
49684978
},
49694979
ExprKind::MethodCall(..) => {
49704980
self.check_methods(cx, expr);

clippy_lints/src/methods/unwrap_expect_used.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use clippy_utils::res::MaybeDef;
33
use clippy_utils::ty::is_never_like;
44
use clippy_utils::{is_in_test, is_inside_always_const_context, is_lint_allowed};
55
use rustc_hir::Expr;
6+
use rustc_hir::def::DefKind;
67
use rustc_lint::{LateContext, Lint};
78
use rustc_middle::ty;
89
use rustc_span::sym;
@@ -87,3 +88,70 @@ pub(super) fn check(
8788
},
8889
);
8990
}
91+
92+
#[expect(clippy::too_many_arguments, clippy::fn_params_excessive_bools)]
93+
pub(super) fn check_call(
94+
cx: &LateContext<'_>,
95+
expr: &Expr<'_>,
96+
func: &Expr<'_>,
97+
args: &[Expr<'_>],
98+
allow_unwrap_in_consts: bool,
99+
allow_unwrap_in_tests: bool,
100+
allow_expect_in_consts: bool,
101+
allow_expect_in_tests: bool,
102+
) {
103+
let Some(recv) = args.first() else {
104+
return;
105+
};
106+
let Some((DefKind::AssocFn, def_id)) = cx.typeck_results().type_dependent_def(func.hir_id) else {
107+
return;
108+
};
109+
110+
match cx.tcx.item_name(def_id) {
111+
sym::unwrap => {
112+
check(
113+
cx,
114+
expr,
115+
recv,
116+
false,
117+
allow_unwrap_in_consts,
118+
allow_unwrap_in_tests,
119+
Variant::Unwrap,
120+
);
121+
},
122+
sym::expect => {
123+
check(
124+
cx,
125+
expr,
126+
recv,
127+
false,
128+
allow_expect_in_consts,
129+
allow_expect_in_tests,
130+
Variant::Expect,
131+
);
132+
},
133+
clippy_utils::sym::unwrap_err => {
134+
check(
135+
cx,
136+
expr,
137+
recv,
138+
true,
139+
allow_unwrap_in_consts,
140+
allow_unwrap_in_tests,
141+
Variant::Unwrap,
142+
);
143+
},
144+
clippy_utils::sym::expect_err => {
145+
check(
146+
cx,
147+
expr,
148+
recv,
149+
true,
150+
allow_expect_in_consts,
151+
allow_expect_in_tests,
152+
Variant::Expect,
153+
);
154+
},
155+
_ => (),
156+
}
157+
}

tests/ui/unwrap_expect_used.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,15 @@ mod with_expansion {
8383
let _ = open!(file).expect_err("can open"); //~ expect_used
8484
}
8585
}
86+
87+
fn issue16484() {
88+
let opt = Some(());
89+
Option::unwrap(opt); //~ unwrap_used
90+
Option::expect(opt, "error message"); //~ expect_used
91+
92+
let res: Result<(), i32> = Ok(());
93+
Result::unwrap(res); //~ unwrap_used
94+
Result::expect(res, "error message"); //~ expect_used
95+
Result::unwrap_err(res); //~ unwrap_used
96+
Result::expect_err(res, "error message"); //~ expect_used
97+
}

tests/ui/unwrap_expect_used.stderr

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,53 @@ LL | let _ = open!(file).expect_err("can open");
8282
|
8383
= note: if this value is an `Ok`, it will panic
8484

85-
error: aborting due to 10 previous errors
85+
error: used `unwrap()` on an `Option` value
86+
--> tests/ui/unwrap_expect_used.rs:89:5
87+
|
88+
LL | Option::unwrap(opt);
89+
| ^^^^^^^^^^^^^^^^^^^
90+
|
91+
= note: if this value is `None`, it will panic
92+
93+
error: used `expect()` on an `Option` value
94+
--> tests/ui/unwrap_expect_used.rs:90:5
95+
|
96+
LL | Option::expect(opt, "error message");
97+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
98+
|
99+
= note: if this value is `None`, it will panic
100+
101+
error: used `unwrap()` on a `Result` value
102+
--> tests/ui/unwrap_expect_used.rs:93:5
103+
|
104+
LL | Result::unwrap(res);
105+
| ^^^^^^^^^^^^^^^^^^^
106+
|
107+
= note: if this value is an `Err`, it will panic
108+
109+
error: used `expect()` on a `Result` value
110+
--> tests/ui/unwrap_expect_used.rs:94:5
111+
|
112+
LL | Result::expect(res, "error message");
113+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
114+
|
115+
= note: if this value is an `Err`, it will panic
116+
117+
error: used `unwrap_err()` on a `Result` value
118+
--> tests/ui/unwrap_expect_used.rs:95:5
119+
|
120+
LL | Result::unwrap_err(res);
121+
| ^^^^^^^^^^^^^^^^^^^^^^^
122+
|
123+
= note: if this value is an `Ok`, it will panic
124+
125+
error: used `expect_err()` on a `Result` value
126+
--> tests/ui/unwrap_expect_used.rs:96:5
127+
|
128+
LL | Result::expect_err(res, "error message");
129+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
130+
|
131+
= note: if this value is an `Ok`, it will panic
132+
133+
error: aborting due to 16 previous errors
86134

0 commit comments

Comments
 (0)