Skip to content

Commit ec036c7

Browse files
borsflip1995
authored andcommitted
Auto merge of rust-lang#12508 - y21:issue12506, r=llogiq
Fix infinite loop in `cast_sign_loss` when peeling unwrap method calls Fixes rust-lang#12506 The lint wants to peel method calls but didn't actually reassign the expression, leading to an infinite loop. ---- changelog: Fix infinite loop in [`cast_sign_loss`] when having two chained `.unwrap()` calls
1 parent 564f93e commit ec036c7

File tree

3 files changed

+118
-89
lines changed

3 files changed

+118
-89
lines changed

src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ enum Sign {
118118
Uncertain,
119119
}
120120

121-
fn expr_sign<'cx>(cx: &LateContext<'cx>, expr: &Expr<'_>, ty: impl Into<Option<Ty<'cx>>>) -> Sign {
121+
fn expr_sign<'cx, 'tcx>(cx: &LateContext<'cx>, mut expr: &'tcx Expr<'tcx>, ty: impl Into<Option<Ty<'cx>>>) -> Sign {
122122
// Try evaluate this expr first to see if it's positive
123123
if let Some(val) = get_const_signed_int_eval(cx, expr, ty) {
124124
return if val >= 0 { Sign::ZeroOrPositive } else { Sign::Negative };
@@ -134,11 +134,12 @@ fn expr_sign<'cx>(cx: &LateContext<'cx>, expr: &Expr<'_>, ty: impl Into<Option<T
134134
// Peel unwrap(), expect(), etc.
135135
while let Some(&found_name) = METHODS_UNWRAP.iter().find(|&name| &method_name == name)
136136
&& let Some(arglist) = method_chain_args(expr, &[found_name])
137-
&& let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind
137+
&& let ExprKind::MethodCall(inner_path, recv, ..) = &arglist[0].0.kind
138138
{
139139
// The original type has changed, but we can't use `ty` here anyway, because it has been
140140
// moved.
141141
method_name = inner_path.ident.name.as_str();
142+
expr = recv;
142143
}
143144

144145
if METHODS_POW.iter().any(|&name| method_name == name)

src/tools/clippy/tests/ui/cast.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
clippy::cast_sign_loss,
1010
clippy::cast_possible_wrap
1111
)]
12-
#![allow(clippy::cast_abs_to_unsigned, clippy::no_effect, clippy::unnecessary_operation)]
12+
#![allow(
13+
clippy::cast_abs_to_unsigned,
14+
clippy::no_effect,
15+
clippy::unnecessary_operation,
16+
clippy::unnecessary_literal_unwrap
17+
)]
1318

1419
fn main() {
1520
// Test clippy::cast_precision_loss
@@ -457,3 +462,8 @@ fn issue11642() {
457462
//~^ ERROR: casting `i32` to `u32` may lose the sign of the value
458463
}
459464
}
465+
466+
fn issue12506() -> usize {
467+
let bar: Result<Option<i64>, u32> = Ok(Some(10));
468+
bar.unwrap().unwrap() as usize
469+
}

0 commit comments

Comments
 (0)