@@ -229,23 +229,30 @@ fn exprs_with_muldiv_binop_peeled<'e>(expr: &'e Expr<'_>) -> Vec<&'e Expr<'e>> {
229229 // For binary operators which both contribute to the sign of the result,
230230 // collect all their operands, recursively. This ignores overflow.
231231 ControlFlow :: Continue ( Descend :: Yes )
232- } else if matches ! ( op. node, BinOpKind :: Rem ) {
232+ } else if matches ! ( op. node, BinOpKind :: Rem | BinOpKind :: Shr ) {
233233 // For binary operators where the left hand side determines the sign of the result,
234234 // only collect that side, recursively. Overflow panics, so this always holds.
235235 //
236+ // Large left shifts turn negatives into zeroes, so we can't use it here.
237+ //
236238 // > Given remainder = dividend % divisor, the remainder will have the same sign as the dividend
239+ // > ...
240+ // > Arithmetic right shift on signed integer types
237241 // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators
242+
243+ // We want to descend into the lhs, but skip the rhs.
244+ // That's tricky to do using for_each_expr(), so we just keep the lhs intact.
238245 res. push ( lhs) ;
239- ControlFlow :: Break ( ( ) )
246+ ControlFlow :: Continue ( Descend :: No )
240247 } else {
241248 // The sign of the result of other binary operators depends on the values of the operands,
242249 // so try to evaluate the expression.
243- res. push ( expr ) ;
250+ res. push ( sub_expr ) ;
244251 ControlFlow :: Continue ( Descend :: No )
245252 }
246253 } else {
247254 // For other expressions, including unary operators and constants, try to evaluate the expression.
248- res. push ( expr ) ;
255+ res. push ( sub_expr ) ;
249256 ControlFlow :: Continue ( Descend :: No )
250257 }
251258 } ) ;
0 commit comments