Skip to content

Commit adbff8b

Browse files
authored
Merge pull request #21465 from A4-Tacks/prec-cast-before-angle
Fix false positive precedence in `(2 as i32) < 3`
2 parents 2d65c93 + 8a0462a commit adbff8b

2 files changed

Lines changed: 26 additions & 4 deletions

File tree

crates/ide-assists/src/handlers/remove_parentheses.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,12 @@ mod tests {
321321
);
322322
}
323323

324+
#[test]
325+
fn remove_parens_conflict_cast_before_l_angle() {
326+
check_assist_not_applicable(remove_parentheses, r#"fn f() { _ = $0(1 as u32) << 10; }"#);
327+
check_assist_not_applicable(remove_parentheses, r#"fn f() { _ = $0(1 as u32) < 10; }"#);
328+
}
329+
324330
#[test]
325331
fn remove_parens_double_paren_stmt() {
326332
check_assist(

crates/syntax/src/ast/prec.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,11 @@ fn check_ancestry(ancestor: &SyntaxNode, descendent: &SyntaxNode) -> bool {
154154
bail()
155155
}
156156

157+
fn next_token_of(node: &SyntaxNode) -> Option<ast::SyntaxToken> {
158+
let last = node.last_token()?;
159+
skip_trivia_token(last.next_token()?, Direction::Next)
160+
}
161+
157162
impl Expr {
158163
pub fn precedence(&self) -> ExprPrecedence {
159164
precedence(self)
@@ -197,6 +202,8 @@ impl Expr {
197202
if is_parent_call_expr && is_field_expr {
198203
return true;
199204
}
205+
let place_of_parent =
206+
|| place_of.ancestors().find(|it| it.parent().is_none_or(|p| &p == parent.syntax()));
200207

201208
// Special-case block weirdness
202209
if parent.child_is_followed_by_a_block() {
@@ -226,15 +233,24 @@ impl Expr {
226233
// For `&&`, we avoid introducing `<ret-like> && <expr>` into a binary chain.
227234

228235
if self.precedence() == ExprPrecedence::Jump
229-
&& let Some(node) =
230-
place_of.ancestors().find(|it| it.parent().is_none_or(|p| &p == parent.syntax()))
231-
&& let Some(next) =
232-
node.last_token().and_then(|t| skip_trivia_token(t.next_token()?, Direction::Next))
236+
&& let Some(node) = place_of_parent()
237+
&& let Some(next) = next_token_of(&node)
233238
&& matches!(next.kind(), T![||] | T![&&])
234239
{
235240
return true;
236241
}
237242

243+
// Special-case `2 as x < 3`
244+
if let ast::Expr::CastExpr(it) = self
245+
&& let Some(ty) = it.ty()
246+
&& ty.syntax().last_token().and_then(|it| ast::NameLike::cast(it.parent()?)).is_some()
247+
&& let Some(node) = place_of_parent()
248+
&& let Some(next) = next_token_of(&node)
249+
&& matches!(next.kind(), T![<] | T![<<])
250+
{
251+
return true;
252+
}
253+
238254
if self.is_paren_like()
239255
|| parent.is_paren_like()
240256
|| self.is_prefix()

0 commit comments

Comments
 (0)