Unnamed repository; edit this file 'description' to name the repository.
Fix various IDE features
As a side benefit, we got `let` guard support for `move_guard` for free.
Chayim Refael Friedman 2022-02-21
parent fe1e324 · commit 13ac5c3
-rw-r--r--crates/hir_expand/src/lib.rs8
-rw-r--r--crates/hir_ty/src/tests/patterns.rs10
-rw-r--r--crates/hir_ty/src/tests/simple.rs1
-rw-r--r--crates/ide/src/hover/render.rs4
-rw-r--r--crates/ide/src/inlay_hints.rs15
-rw-r--r--crates/ide_assists/src/handlers/convert_bool_then.rs3
-rw-r--r--crates/ide_assists/src/handlers/convert_to_guarded_return.rs34
-rw-r--r--crates/ide_assists/src/handlers/convert_while_to_loop.rs23
-rw-r--r--crates/ide_assists/src/handlers/extract_function.rs20
-rw-r--r--crates/ide_assists/src/handlers/invert_if.rs4
-rw-r--r--crates/ide_assists/src/handlers/move_guard.rs28
-rw-r--r--crates/ide_assists/src/handlers/replace_if_let_with_match.rs23
-rw-r--r--crates/ide_assists/src/handlers/replace_let_with_if_let.rs2
-rw-r--r--crates/ide_completion/src/context.rs12
-rw-r--r--crates/ide_db/src/helpers.rs1
15 files changed, 95 insertions, 93 deletions
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 56cf7aed8e..e33c2565c3 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -811,10 +811,10 @@ impl ExpandTo {
MACRO_TYPE => ExpandTo::Type,
ARG_LIST | TRY_EXPR | TUPLE_EXPR | PAREN_EXPR | ARRAY_EXPR | FOR_EXPR | PATH_EXPR
- | CLOSURE_EXPR | CONDITION | BREAK_EXPR | RETURN_EXPR | MATCH_EXPR | MATCH_ARM
- | MATCH_GUARD | RECORD_EXPR_FIELD | CALL_EXPR | INDEX_EXPR | METHOD_CALL_EXPR
- | FIELD_EXPR | AWAIT_EXPR | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR
- | BIN_EXPR => ExpandTo::Expr,
+ | CLOSURE_EXPR | BREAK_EXPR | RETURN_EXPR | MATCH_EXPR | MATCH_ARM | MATCH_GUARD
+ | RECORD_EXPR_FIELD | CALL_EXPR | INDEX_EXPR | METHOD_CALL_EXPR | FIELD_EXPR
+ | AWAIT_EXPR | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR
+ | LET_EXPR => ExpandTo::Expr,
LET_STMT => {
// FIXME: Handle LHS Pattern
ExpandTo::Expr
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs
index 5b08d65c46..acdd8f50ef 100644
--- a/crates/hir_ty/src/tests/patterns.rs
+++ b/crates/hir_ty/src/tests/patterns.rs
@@ -55,6 +55,7 @@ fn infer_pattern() {
139..140 'g': {unknown}
143..144 'e': {unknown}
157..204 'if let... }': ()
+ 160..175 'let [val] = opt': bool
164..169 '[val]': [{unknown}]
165..168 'val': {unknown}
172..175 'opt': [{unknown}]
@@ -62,6 +63,7 @@ fn infer_pattern() {
190..191 'h': {unknown}
194..197 'val': {unknown}
210..236 'if let...rue {}': ()
+ 213..233 'let x ... &true': bool
217..225 'x @ true': &bool
221..225 'true': bool
221..225 'true': bool
@@ -111,36 +113,42 @@ fn infer_literal_pattern() {
37..38 'x': &i32
46..208 '{ ...) {} }': ()
52..75 'if let...y() {}': ()
+ 55..72 'let "f... any()': bool
59..64 '"foo"': &str
59..64 '"foo"': &str
67..70 'any': fn any<&str>() -> &str
67..72 'any()': &str
73..75 '{}': ()
80..99 'if let...y() {}': ()
+ 83..96 'let 1 = any()': bool
87..88 '1': i32
87..88 '1': i32
91..94 'any': fn any<i32>() -> i32
91..96 'any()': i32
97..99 '{}': ()
104..126 'if let...y() {}': ()
+ 107..123 'let 1u... any()': bool
111..115 '1u32': u32
111..115 '1u32': u32
118..121 'any': fn any<u32>() -> u32
118..123 'any()': u32
124..126 '{}': ()
131..153 'if let...y() {}': ()
+ 134..150 'let 1f... any()': bool
138..142 '1f32': f32
138..142 '1f32': f32
145..148 'any': fn any<f32>() -> f32
145..150 'any()': f32
151..153 '{}': ()
158..179 'if let...y() {}': ()
+ 161..176 'let 1.0 = any()': bool
165..168 '1.0': f64
165..168 '1.0': f64
171..174 'any': fn any<f64>() -> f64
171..176 'any()': f64
177..179 '{}': ()
184..206 'if let...y() {}': ()
+ 187..203 'let tr... any()': bool
191..195 'true': bool
191..195 'true': bool
198..201 'any': fn any<bool>() -> bool
@@ -163,10 +171,12 @@ fn infer_range_pattern() {
8..9 'x': &i32
17..75 '{ ...2 {} }': ()
23..45 'if let...u32 {}': ()
+ 26..42 'let 1....= 2u32': bool
30..35 '1..76': u32
38..42 '2u32': u32
43..45 '{}': ()
50..73 'if let...u32 {}': ()
+ 53..70 'let 1....= 2u32': bool
57..63 '1..=76': u32
66..70 '2u32': u32
71..73 '{}': ()
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index f4d082ea8c..c11a70fa66 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -2248,6 +2248,7 @@ fn generic_default_in_struct_literal() {
176..193 'Thing ...1i32 }': Thing<i32>
187..191 '1i32': i32
199..240 'if let... }': ()
+ 202..221 'let Th... } = z': bool
206..217 'Thing { t }': Thing<i32>
214..215 't': i32
220..221 'z': Thing<i32>
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index f94348ec58..ce9055c090 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -18,7 +18,7 @@ use syntax::{
algo, ast,
display::{fn_as_proc_macro_label, macro_label},
match_ast, AstNode, Direction,
- SyntaxKind::{CONDITION, LET_STMT},
+ SyntaxKind::{LET_EXPR, LET_STMT},
SyntaxToken, T,
};
@@ -484,7 +484,7 @@ fn local(db: &RootDatabase, it: hir::Local) -> Option<Markup> {
let let_kw = if ident
.syntax()
.parent()
- .map_or(false, |p| p.kind() == LET_STMT || p.kind() == CONDITION)
+ .map_or(false, |p| p.kind() == LET_STMT || p.kind() == LET_EXPR)
{
"let "
} else {
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index cc304cb10a..2ca756cbe0 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -243,7 +243,7 @@ fn is_named_constructor(
let expr = match_ast! {
match let_node {
ast::LetStmt(it) => it.initializer(),
- ast::Condition(it) => it.expr(),
+ ast::LetExpr(it) => it.expr(),
_ => None,
}
}?;
@@ -372,15 +372,10 @@ fn should_not_display_type_hint(
match node {
ast::LetStmt(it) => return it.ty().is_some(),
ast::Param(it) => return it.ty().is_some(),
- ast::MatchArm(_it) => return pat_is_enum_variant(db, bind_pat, pat_ty),
- ast::IfExpr(it) => {
- return it.condition().and_then(|condition| condition.pat()).is_some()
- && pat_is_enum_variant(db, bind_pat, pat_ty);
- },
- ast::WhileExpr(it) => {
- return it.condition().and_then(|condition| condition.pat()).is_some()
- && pat_is_enum_variant(db, bind_pat, pat_ty);
- },
+ ast::MatchArm(_) => return pat_is_enum_variant(db, bind_pat, pat_ty),
+ ast::LetExpr(_) => return pat_is_enum_variant(db, bind_pat, pat_ty),
+ ast::IfExpr(_) => return false,
+ ast::WhileExpr(_) => return false,
ast::ForExpr(it) => {
// We *should* display hint only if user provided "in {expr}" and we know the type of expr (and it's not unit).
// Type of expr should be iterable.
diff --git a/crates/ide_assists/src/handlers/convert_bool_then.rs b/crates/ide_assists/src/handlers/convert_bool_then.rs
index b8c55eb852..0bf2abe493 100644
--- a/crates/ide_assists/src/handlers/convert_bool_then.rs
+++ b/crates/ide_assists/src/handlers/convert_bool_then.rs
@@ -46,7 +46,6 @@ pub(crate) fn convert_if_to_bool_then(acc: &mut Assists, ctx: &AssistContext) ->
}
let cond = expr.condition().filter(|cond| !cond.is_pattern_cond())?;
- let cond = cond.expr()?;
let then = expr.then_branch()?;
let else_ = match expr.else_branch()? {
ast::ElseBranch::Block(b) => b,
@@ -209,7 +208,7 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext) ->
_ => receiver,
};
let if_expr = make::expr_if(
- make::condition(cond, None),
+ cond,
closure_body.reset_indent(),
Some(ast::ElseBranch::Block(make::block_expr(None, Some(none_path)))),
)
diff --git a/crates/ide_assists/src/handlers/convert_to_guarded_return.rs b/crates/ide_assists/src/handlers/convert_to_guarded_return.rs
index 884905a918..9a80db6a83 100644
--- a/crates/ide_assists/src/handlers/convert_to_guarded_return.rs
+++ b/crates/ide_assists/src/handlers/convert_to_guarded_return.rs
@@ -48,25 +48,28 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
let cond = if_expr.condition()?;
// Check if there is an IfLet that we can handle.
- let if_let_pat = match cond.pat() {
- None => None, // No IfLet, supported.
- Some(ast::Pat::TupleStructPat(pat)) if pat.fields().count() == 1 => {
- let path = pat.path()?;
- if path.qualifier().is_some() {
- return None;
- }
+ let (if_let_pat, cond_expr) = if cond.is_pattern_cond() {
+ let let_ = cond.single_let()?;
+ match let_.pat() {
+ Some(ast::Pat::TupleStructPat(pat)) if pat.fields().count() == 1 => {
+ let path = pat.path()?;
+ if path.qualifier().is_some() {
+ return None;
+ }
- let bound_ident = pat.fields().next().unwrap();
- if !ast::IdentPat::can_cast(bound_ident.syntax().kind()) {
- return None;
- }
+ let bound_ident = pat.fields().next().unwrap();
+ if !ast::IdentPat::can_cast(bound_ident.syntax().kind()) {
+ return None;
+ }
- Some((path, bound_ident))
+ (Some((path, bound_ident)), let_.expr()?)
+ }
+ _ => return None, // Unsupported IfLet.
}
- Some(_) => return None, // Unsupported IfLet.
+ } else {
+ (None, cond)
};
- let cond_expr = cond.expr()?;
let then_block = if_expr.then_branch()?;
let then_block = then_block.stmt_list()?;
@@ -119,8 +122,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
let then_branch =
make::block_expr(once(make::expr_stmt(early_expression).into()), None);
let cond = invert_boolean_expression(cond_expr);
- make::expr_if(make::condition(cond, None), then_branch, None)
- .indent(if_indent_level)
+ make::expr_if(cond, then_branch, None).indent(if_indent_level)
};
new_expr.syntax().clone_for_update()
}
diff --git a/crates/ide_assists/src/handlers/convert_while_to_loop.rs b/crates/ide_assists/src/handlers/convert_while_to_loop.rs
index 2bc64e77a3..30b4daec9d 100644
--- a/crates/ide_assists/src/handlers/convert_while_to_loop.rs
+++ b/crates/ide_assists/src/handlers/convert_while_to_loop.rs
@@ -42,7 +42,6 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext) -> O
let while_expr = while_kw.parent().and_then(ast::WhileExpr::cast)?;
let while_body = while_expr.loop_body()?;
let while_cond = while_expr.condition()?;
- let while_cond_expr = while_cond.expr()?;
let target = while_expr.syntax().text_range();
acc.add(
@@ -55,19 +54,15 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext) -> O
let break_block =
make::block_expr(once(make::expr_stmt(make::expr_break(None)).into()), None)
.indent(while_indent_level);
- let block_expr = match while_cond.pat() {
- Some(_) => {
- let if_expr = make::expr_if(while_cond, while_body, Some(break_block.into()));
- let stmts = once(make::expr_stmt(if_expr).into());
- make::block_expr(stmts, None)
- }
- None => {
- let if_cond = make::condition(invert_boolean_expression(while_cond_expr), None);
- let if_expr = make::expr_if(if_cond, break_block, None);
- let stmts =
- once(make::expr_stmt(if_expr).into()).chain(while_body.statements());
- make::block_expr(stmts, while_body.tail_expr())
- }
+ let block_expr = if while_cond.is_pattern_cond() {
+ let if_expr = make::expr_if(while_cond, while_body, Some(break_block.into()));
+ let stmts = once(make::expr_stmt(if_expr).into());
+ make::block_expr(stmts, None)
+ } else {
+ let if_cond = invert_boolean_expression(while_cond);
+ let if_expr = make::expr_if(if_cond, break_block, None);
+ let stmts = once(make::expr_stmt(if_expr).into()).chain(while_body.statements());
+ make::block_expr(stmts, while_body.tail_expr())
};
let replacement = make::expr_loop(block_expr.indent(while_indent_level));
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs
index 877c5b0cef..21cfc76ac9 100644
--- a/crates/ide_assists/src/handlers/extract_function.rs
+++ b/crates/ide_assists/src/handlers/extract_function.rs
@@ -1219,28 +1219,26 @@ impl FlowHandler {
let stmt = make::expr_stmt(action);
let block = make::block_expr(iter::once(stmt.into()), None);
let controlflow_break_path = make::path_from_text("ControlFlow::Break");
- let condition = make::condition(
+ let condition = make::expr_let(
+ make::tuple_struct_pat(
+ controlflow_break_path,
+ iter::once(make::wildcard_pat().into()),
+ )
+ .into(),
call_expr,
- Some(
- make::tuple_struct_pat(
- controlflow_break_path,
- iter::once(make::wildcard_pat().into()),
- )
- .into(),
- ),
);
- make::expr_if(condition, block, None)
+ make::expr_if(condition.into(), block, None)
}
FlowHandler::IfOption { action } => {
let path = make::ext::ident_path("Some");
let value_pat = make::ext::simple_ident_pat(make::name("value"));
let pattern = make::tuple_struct_pat(path, iter::once(value_pat.into()));
- let cond = make::condition(call_expr, Some(pattern.into()));
+ let cond = make::expr_let(pattern.into(), call_expr);
let value = make::expr_path(make::ext::ident_path("value"));
let action_expr = action.make_result_handler(Some(value));
let action_stmt = make::expr_stmt(action_expr);
let then = make::block_expr(iter::once(action_stmt.into()), None);
- make::expr_if(cond, then, None)
+ make::expr_if(cond.into(), then, None)
}
FlowHandler::MatchOption { none } => {
let some_name = "value";
diff --git a/crates/ide_assists/src/handlers/invert_if.rs b/crates/ide_assists/src/handlers/invert_if.rs
index 20f6b0c54c..8f99c4db67 100644
--- a/crates/ide_assists/src/handlers/invert_if.rs
+++ b/crates/ide_assists/src/handlers/invert_if.rs
@@ -34,12 +34,12 @@ pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
return None;
}
+ let cond = expr.condition()?;
// This assist should not apply for if-let.
- if expr.condition()?.is_pattern_cond() {
+ if cond.is_pattern_cond() {
return None;
}
- let cond = expr.condition()?.expr()?;
let then_node = expr.then_branch()?.syntax().clone();
let else_block = match expr.else_branch()? {
ast::ElseBranch::Block(it) => it,
diff --git a/crates/ide_assists/src/handlers/move_guard.rs b/crates/ide_assists/src/handlers/move_guard.rs
index 366f308f6e..6554940859 100644
--- a/crates/ide_assists/src/handlers/move_guard.rs
+++ b/crates/ide_assists/src/handlers/move_guard.rs
@@ -1,8 +1,5 @@
use syntax::{
- ast::{
- edit::AstNodeEdit, make, AstNode, BlockExpr, Condition, ElseBranch, Expr, IfExpr, MatchArm,
- Pat,
- },
+ ast::{edit::AstNodeEdit, make, AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat},
SyntaxKind::WHITESPACE,
};
@@ -44,18 +41,11 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext) ->
}
let space_before_guard = guard.syntax().prev_sibling_or_token();
- // FIXME: support `if let` guards too
- if guard.let_token().is_some() {
- return None;
- }
- let guard_condition = guard.expr()?;
+ let guard_condition = guard.condition()?;
let arm_expr = match_arm.expr()?;
- let if_expr = make::expr_if(
- make::condition(guard_condition, None),
- make::block_expr(None, Some(arm_expr.clone())),
- None,
- )
- .indent(arm_expr.indent_level());
+ let if_expr =
+ make::expr_if(guard_condition, make::block_expr(None, Some(arm_expr.clone())), None)
+ .indent(arm_expr.indent_level());
let target = guard.syntax().text_range();
acc.add(
@@ -193,17 +183,13 @@ pub(crate) fn move_arm_cond_to_match_guard(acc: &mut Assists, ctx: &AssistContex
)
}
-// Parses an if-else-if chain to get the conditons and the then branches until we encounter an else
+// Parses an if-else-if chain to get the conditions and the then branches until we encounter an else
// branch or the end.
-fn parse_if_chain(if_expr: IfExpr) -> Option<(Vec<(Condition, BlockExpr)>, Option<BlockExpr>)> {
+fn parse_if_chain(if_expr: IfExpr) -> Option<(Vec<(Expr, BlockExpr)>, Option<BlockExpr>)> {
let mut conds_blocks = Vec::new();
let mut curr_if = if_expr;
let tail = loop {
let cond = curr_if.condition()?;
- // Not support moving if let to arm guard
- if cond.is_pattern_cond() {
- return None;
- }
conds_blocks.push((cond, curr_if.then_branch()?));
match curr_if.else_branch() {
Some(ElseBranch::IfExpr(e)) => {
diff --git a/crates/ide_assists/src/handlers/replace_if_let_with_match.rs b/crates/ide_assists/src/handlers/replace_if_let_with_match.rs
index 7790934792..3be14d7d95 100644
--- a/crates/ide_assists/src/handlers/replace_if_let_with_match.rs
+++ b/crates/ide_assists/src/handlers/replace_if_let_with_match.rs
@@ -60,15 +60,22 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
None
}
});
- let scrutinee_to_be_expr = if_expr.condition()?.expr()?;
+ let scrutinee_to_be_expr = if_expr.condition()?;
+ let scrutinee_to_be_expr = match scrutinee_to_be_expr.single_let() {
+ Some(cond) => cond.expr()?,
+ None => scrutinee_to_be_expr,
+ };
let mut pat_seen = false;
let mut cond_bodies = Vec::new();
for if_expr in if_exprs {
let cond = if_expr.condition()?;
- let expr = cond.expr()?;
- let cond = match cond.pat() {
- Some(pat) => {
+ let cond = match cond.single_let() {
+ Some(let_) => {
+ let pat = let_.pat()?;
+ let expr = let_.expr()?;
+ // FIXME: If one `let` is wrapped in parentheses and the second is not,
+ // we'll exit here.
if scrutinee_to_be_expr.syntax().text() != expr.syntax().text() {
// Only if all condition expressions are equal we can merge them into a match
return None;
@@ -76,7 +83,9 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
pat_seen = true;
Either::Left(pat)
}
- None => Either::Right(expr),
+ // Multiple `let`, unsupported.
+ None if cond.is_pattern_cond() => return None,
+ None => Either::Right(cond),
};
let body = if_expr.then_branch()?;
cond_bodies.push((cond, body));
@@ -217,11 +226,11 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext)
}
}
- let condition = make::condition(scrutinee, Some(if_let_pat));
+ let condition = make::expr_let(if_let_pat, scrutinee);
let then_block = make_block_expr(then_expr.reset_indent());
let else_expr = if is_empty_expr(&else_expr) { None } else { Some(else_expr) };
let if_let_expr = make::expr_if(
- condition,
+ condition.into(),
then_block,
else_expr.map(make_block_expr).map(ast::ElseBranch::Block),
)
diff --git a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
index 1062cc3953..a5fa8a110d 100644
--- a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
+++ b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
@@ -62,7 +62,7 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) ->
let block =
make::ext::empty_block_expr().indent(IndentLevel::from_node(let_stmt.syntax()));
- let if_ = make::expr_if(make::condition(init, Some(pat)), block, None);
+ let if_ = make::expr_if(make::expr_let(pat, init).into(), block, None);
let stmt = make::expr_stmt(if_);
edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt));
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index d711215491..e986c28b14 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -575,6 +575,14 @@ impl<'a> CompletionContext<'a> {
(ty, name)
},
+ ast::LetExpr(it) => {
+ cov_mark::hit!(expected_type_if_let_without_leading_char);
+ let ty = it.pat()
+ .and_then(|pat| self.sema.type_of_pat(&pat))
+ .or_else(|| it.expr().and_then(|it| self.sema.type_of_expr(&it)))
+ .map(TypeInfo::original);
+ (ty, None)
+ },
ast::ArgList(_) => {
cov_mark::hit!(expected_type_fn_param);
ActiveParameter::at_token(
@@ -641,9 +649,7 @@ impl<'a> CompletionContext<'a> {
(ty, None)
},
ast::IfExpr(it) => {
- cov_mark::hit!(expected_type_if_let_without_leading_char);
let ty = it.condition()
- .and_then(|cond| cond.expr())
.and_then(|e| self.sema.type_of_expr(&e))
.map(TypeInfo::original);
(ty, None)
@@ -939,7 +945,7 @@ fn pattern_context_for(original_file: &SyntaxNode, pat: ast::Pat) -> PatternCont
return (PatternRefutability::Irrefutable, has_type_ascription)
},
ast::MatchArm(_) => PatternRefutability::Refutable,
- ast::Condition(_) => PatternRefutability::Refutable,
+ ast::LetExpr(_) => PatternRefutability::Refutable,
ast::ForExpr(_) => PatternRefutability::Irrefutable,
_ => PatternRefutability::Irrefutable,
}
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs
index 2d3d640933..9c6d3775c7 100644
--- a/crates/ide_db/src/helpers.rs
+++ b/crates/ide_db/src/helpers.rs
@@ -226,6 +226,7 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
| ast::Expr::TryExpr(_)
| ast::Expr::TupleExpr(_)
| ast::Expr::WhileExpr(_)
+ | ast::Expr::LetExpr(_)
| ast::Expr::YieldExpr(_) => cb(expr),
}
}