mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge #1660
1660: implement while let desugaring r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
c5b44975b8
@ -11,17 +11,16 @@ use ra_syntax::{
|
|||||||
},
|
},
|
||||||
AstNode, AstPtr, SyntaxNodePtr,
|
AstNode, AstPtr, SyntaxNodePtr,
|
||||||
};
|
};
|
||||||
|
use test_utils::tested_by;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
name::{AsName, SELF_PARAM},
|
name::{AsName, SELF_PARAM},
|
||||||
|
path::GenericArgs,
|
||||||
|
ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy},
|
||||||
type_ref::{Mutability, TypeRef},
|
type_ref::{Mutability, TypeRef},
|
||||||
DefWithBody, Either, HasSource, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind, Name,
|
DefWithBody, Either, HasSource, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind, Name,
|
||||||
Path, Resolver,
|
Path, Resolver,
|
||||||
};
|
};
|
||||||
use crate::{
|
|
||||||
path::GenericArgs,
|
|
||||||
ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub use self::scope::ExprScopes;
|
pub use self::scope::ExprScopes;
|
||||||
|
|
||||||
@ -558,37 +557,40 @@ where
|
|||||||
let syntax_ptr = SyntaxNodePtr::new(expr.syntax());
|
let syntax_ptr = SyntaxNodePtr::new(expr.syntax());
|
||||||
match expr.kind() {
|
match expr.kind() {
|
||||||
ast::ExprKind::IfExpr(e) => {
|
ast::ExprKind::IfExpr(e) => {
|
||||||
if let Some(pat) = e.condition().and_then(|c| c.pat()) {
|
let then_branch = self.collect_block_opt(e.then_branch());
|
||||||
// if let -- desugar to match
|
|
||||||
let pat = self.collect_pat(pat);
|
let else_branch = e.else_branch().map(|b| match b {
|
||||||
let match_expr =
|
ast::ElseBranch::Block(it) => self.collect_block(it),
|
||||||
self.collect_expr_opt(e.condition().expect("checked above").expr());
|
ast::ElseBranch::IfExpr(elif) => {
|
||||||
let then_branch = self.collect_block_opt(e.then_branch());
|
let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap();
|
||||||
let else_branch = e
|
self.collect_expr(expr)
|
||||||
.else_branch()
|
}
|
||||||
.map(|b| match b {
|
});
|
||||||
ast::ElseBranch::Block(it) => self.collect_block(it),
|
|
||||||
ast::ElseBranch::IfExpr(elif) => self.collect_expr(elif.into()),
|
let condition = match e.condition() {
|
||||||
})
|
None => self.exprs.alloc(Expr::Missing),
|
||||||
.unwrap_or_else(|| self.empty_block());
|
Some(condition) => match condition.pat() {
|
||||||
let placeholder_pat = self.pats.alloc(Pat::Missing);
|
None => self.collect_expr_opt(condition.expr()),
|
||||||
let arms = vec![
|
// if let -- desugar to match
|
||||||
MatchArm { pats: vec![pat], expr: then_branch, guard: None },
|
Some(pat) => {
|
||||||
MatchArm { pats: vec![placeholder_pat], expr: else_branch, guard: None },
|
let pat = self.collect_pat(pat);
|
||||||
];
|
let match_expr = self.collect_expr_opt(condition.expr());
|
||||||
self.alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr)
|
let placeholder_pat = self.pats.alloc(Pat::Missing);
|
||||||
} else {
|
let arms = vec![
|
||||||
let condition = self.collect_expr_opt(e.condition().and_then(|c| c.expr()));
|
MatchArm { pats: vec![pat], expr: then_branch, guard: None },
|
||||||
let then_branch = self.collect_block_opt(e.then_branch());
|
MatchArm {
|
||||||
let else_branch = e.else_branch().map(|b| match b {
|
pats: vec![placeholder_pat],
|
||||||
ast::ElseBranch::Block(it) => self.collect_block(it),
|
expr: else_branch.unwrap_or_else(|| self.empty_block()),
|
||||||
ast::ElseBranch::IfExpr(elif) => {
|
guard: None,
|
||||||
let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap();
|
},
|
||||||
self.collect_expr(expr)
|
];
|
||||||
|
return self
|
||||||
|
.alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr);
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
|
};
|
||||||
}
|
|
||||||
|
self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
|
||||||
}
|
}
|
||||||
ast::ExprKind::TryBlockExpr(e) => {
|
ast::ExprKind::TryBlockExpr(e) => {
|
||||||
let body = self.collect_block_opt(e.try_body());
|
let body = self.collect_block_opt(e.try_body());
|
||||||
@ -600,17 +602,30 @@ where
|
|||||||
self.alloc_expr(Expr::Loop { body }, syntax_ptr)
|
self.alloc_expr(Expr::Loop { body }, syntax_ptr)
|
||||||
}
|
}
|
||||||
ast::ExprKind::WhileExpr(e) => {
|
ast::ExprKind::WhileExpr(e) => {
|
||||||
let condition = if let Some(condition) = e.condition() {
|
|
||||||
if condition.pat().is_none() {
|
|
||||||
self.collect_expr_opt(condition.expr())
|
|
||||||
} else {
|
|
||||||
// FIXME handle while let
|
|
||||||
return self.alloc_expr(Expr::Missing, syntax_ptr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.exprs.alloc(Expr::Missing)
|
|
||||||
};
|
|
||||||
let body = self.collect_block_opt(e.loop_body());
|
let body = self.collect_block_opt(e.loop_body());
|
||||||
|
|
||||||
|
let condition = match e.condition() {
|
||||||
|
None => self.exprs.alloc(Expr::Missing),
|
||||||
|
Some(condition) => match condition.pat() {
|
||||||
|
None => self.collect_expr_opt(condition.expr()),
|
||||||
|
// if let -- desugar to match
|
||||||
|
Some(pat) => {
|
||||||
|
tested_by!(infer_while_let);
|
||||||
|
let pat = self.collect_pat(pat);
|
||||||
|
let match_expr = self.collect_expr_opt(condition.expr());
|
||||||
|
let placeholder_pat = self.pats.alloc(Pat::Missing);
|
||||||
|
let break_ = self.exprs.alloc(Expr::Break { expr: None });
|
||||||
|
let arms = vec![
|
||||||
|
MatchArm { pats: vec![pat], expr: body, guard: None },
|
||||||
|
MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None },
|
||||||
|
];
|
||||||
|
let match_expr =
|
||||||
|
self.exprs.alloc(Expr::Match { expr: match_expr, arms });
|
||||||
|
return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
self.alloc_expr(Expr::While { condition, body }, syntax_ptr)
|
self.alloc_expr(Expr::While { condition, body }, syntax_ptr)
|
||||||
}
|
}
|
||||||
ast::ExprKind::ForExpr(e) => {
|
ast::ExprKind::ForExpr(e) => {
|
||||||
|
@ -10,4 +10,5 @@ test_utils::marks!(
|
|||||||
std_prelude
|
std_prelude
|
||||||
match_ergonomics_ref
|
match_ergonomics_ref
|
||||||
trait_resolution_on_fn_type
|
trait_resolution_on_fn_type
|
||||||
|
infer_while_let
|
||||||
);
|
);
|
||||||
|
@ -144,6 +144,26 @@ mod collections {
|
|||||||
assert_eq!("&str", type_at_pos(&db, pos));
|
assert_eq!("&str", type_at_pos(&db, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_while_let() {
|
||||||
|
covers!(infer_while_let);
|
||||||
|
let (db, pos) = MockDatabase::with_position(
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
enum Option<T> { Some(T), None }
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
let foo: Option<f32> = None;
|
||||||
|
while let Option::Some(x) = foo {
|
||||||
|
<|>x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
assert_eq!("f32", type_at_pos(&db, pos));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn infer_basics() {
|
fn infer_basics() {
|
||||||
assert_snapshot_matches!(
|
assert_snapshot_matches!(
|
||||||
|
@ -414,13 +414,35 @@ fn main() {
|
|||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[
|
assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r###"
|
||||||
InlayHint {
|
⋮[
|
||||||
range: [166; 170),
|
⋮ InlayHint {
|
||||||
kind: TypeHint,
|
⋮ range: [166; 170),
|
||||||
label: "CustomOption<Test>",
|
⋮ kind: TypeHint,
|
||||||
},
|
⋮ label: "CustomOption<Test>",
|
||||||
]"#
|
⋮ },
|
||||||
|
⋮ InlayHint {
|
||||||
|
⋮ range: [343; 347),
|
||||||
|
⋮ kind: TypeHint,
|
||||||
|
⋮ label: "&Test",
|
||||||
|
⋮ },
|
||||||
|
⋮ InlayHint {
|
||||||
|
⋮ range: [401; 402),
|
||||||
|
⋮ kind: TypeHint,
|
||||||
|
⋮ label: "&CustomOption<u32>",
|
||||||
|
⋮ },
|
||||||
|
⋮ InlayHint {
|
||||||
|
⋮ range: [404; 405),
|
||||||
|
⋮ kind: TypeHint,
|
||||||
|
⋮ label: "&u8",
|
||||||
|
⋮ },
|
||||||
|
⋮ InlayHint {
|
||||||
|
⋮ range: [549; 550),
|
||||||
|
⋮ kind: TypeHint,
|
||||||
|
⋮ label: "&u32",
|
||||||
|
⋮ },
|
||||||
|
⋮]
|
||||||
|
"###
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user