From 4d6475ada0c4176734f7e7f24cb1be8c5c8d1988 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 7 Aug 2019 12:32:32 +0200 Subject: refactor if lowering --- crates/ra_hir/src/expr.rs | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 4dcea19a9..9fea70dda 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -558,35 +558,32 @@ where let syntax_ptr = SyntaxNodePtr::new(expr.syntax()); match expr.kind() { ast::ExprKind::IfExpr(e) => { + let then_branch = self.collect_block_opt(e.then_branch()); + let else_branch = e.else_branch().map(|b| match b { + ast::ElseBranch::Block(it) => self.collect_block(it), + ast::ElseBranch::IfExpr(elif) => { + let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap(); + self.collect_expr(expr) + } + }); + if let Some(pat) = e.condition().and_then(|c| c.pat()) { // if let -- desugar to match let pat = self.collect_pat(pat); let match_expr = self.collect_expr_opt(e.condition().expect("checked above").expr()); - let then_branch = self.collect_block_opt(e.then_branch()); - let else_branch = e - .else_branch() - .map(|b| match b { - ast::ElseBranch::Block(it) => self.collect_block(it), - ast::ElseBranch::IfExpr(elif) => self.collect_expr(elif.into()), - }) - .unwrap_or_else(|| self.empty_block()); let placeholder_pat = self.pats.alloc(Pat::Missing); let arms = vec![ MatchArm { pats: vec![pat], expr: then_branch, guard: None }, - MatchArm { pats: vec![placeholder_pat], expr: else_branch, guard: None }, + MatchArm { + pats: vec![placeholder_pat], + expr: else_branch.unwrap_or_else(|| self.empty_block()), + guard: None, + }, ]; self.alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr) } else { let condition = self.collect_expr_opt(e.condition().and_then(|c| c.expr())); - let then_branch = self.collect_block_opt(e.then_branch()); - let else_branch = e.else_branch().map(|b| match b { - ast::ElseBranch::Block(it) => self.collect_block(it), - ast::ElseBranch::IfExpr(elif) => { - let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap(); - self.collect_expr(expr) - } - }); self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) } } -- cgit v1.2.3 From 39967a85e1f04676062d46b04e7ac8399c57df66 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 7 Aug 2019 13:51:54 +0200 Subject: refactor if-let lowering mainly to get rid of unwraps --- crates/ra_hir/src/expr.rs | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 9fea70dda..b59787a83 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -559,6 +559,7 @@ where match expr.kind() { ast::ExprKind::IfExpr(e) => { let then_branch = self.collect_block_opt(e.then_branch()); + let else_branch = e.else_branch().map(|b| match b { ast::ElseBranch::Block(it) => self.collect_block(it), ast::ElseBranch::IfExpr(elif) => { @@ -567,25 +568,30 @@ where } }); - if let Some(pat) = e.condition().and_then(|c| c.pat()) { - // if let -- desugar to match - let pat = self.collect_pat(pat); - let match_expr = - self.collect_expr_opt(e.condition().expect("checked above").expr()); - let placeholder_pat = self.pats.alloc(Pat::Missing); - let arms = vec![ - MatchArm { pats: vec![pat], expr: then_branch, guard: None }, - MatchArm { - pats: vec![placeholder_pat], - expr: else_branch.unwrap_or_else(|| self.empty_block()), - guard: None, - }, - ]; - self.alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr) - } else { - let condition = self.collect_expr_opt(e.condition().and_then(|c| c.expr())); - self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) - } + 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) => { + let pat = self.collect_pat(pat); + let match_expr = self.collect_expr_opt(condition.expr()); + let placeholder_pat = self.pats.alloc(Pat::Missing); + let arms = vec![ + MatchArm { pats: vec![pat], expr: then_branch, guard: None }, + MatchArm { + pats: vec![placeholder_pat], + expr: else_branch.unwrap_or_else(|| self.empty_block()), + guard: None, + }, + ]; + return self + .alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr); + } + }, + }; + + self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) } ast::ExprKind::TryBlockExpr(e) => { let body = self.collect_block_opt(e.try_body()); -- cgit v1.2.3 From 6efc79b89d50b1b2ad9127afb2073bebe4b35290 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 7 Aug 2019 15:14:22 +0200 Subject: implement while let desugaring --- crates/ra_hir/src/expr.rs | 40 +++++++++++++++++++++++------------- crates/ra_hir/src/marks.rs | 1 + crates/ra_hir/src/ty/tests.rs | 20 ++++++++++++++++++ crates/ra_ide_api/src/inlay_hints.rs | 36 +++++++++++++++++++++++++------- 4 files changed, 76 insertions(+), 21 deletions(-) diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index b59787a83..f33676655 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -11,17 +11,16 @@ use ra_syntax::{ }, AstNode, AstPtr, SyntaxNodePtr, }; +use test_utils::tested_by; use crate::{ name::{AsName, SELF_PARAM}, + path::GenericArgs, + ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy}, type_ref::{Mutability, TypeRef}, DefWithBody, Either, HasSource, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind, Name, Path, Resolver, }; -use crate::{ - path::GenericArgs, - ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy}, -}; pub use self::scope::ExprScopes; @@ -603,17 +602,30 @@ where self.alloc_expr(Expr::Loop { body }, syntax_ptr) } 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 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) } ast::ExprKind::ForExpr(e) => { diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs index 2d831f0d8..5b15eee90 100644 --- a/crates/ra_hir/src/marks.rs +++ b/crates/ra_hir/src/marks.rs @@ -10,4 +10,5 @@ test_utils::marks!( std_prelude match_ergonomics_ref trait_resolution_on_fn_type + infer_while_let ); diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 36dea17a3..d5f7a4d25 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -144,6 +144,26 @@ mod collections { 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 { Some(T), None } + +fn test() { + let foo: Option = None; + while let Option::Some(x) = foo { + <|>x + } +} + +"#, + ); + assert_eq!("f32", type_at_pos(&db, pos)); +} + #[test] fn infer_basics() { assert_snapshot_matches!( diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs index 7b9190314..0b3c96d26 100644 --- a/crates/ra_ide_api/src/inlay_hints.rs +++ b/crates/ra_ide_api/src/inlay_hints.rs @@ -414,13 +414,35 @@ fn main() { }"#, ); - assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r#"[ - InlayHint { - range: [166; 170), - kind: TypeHint, - label: "CustomOption", - }, -]"# + assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r###" + ⋮[ + ⋮ InlayHint { + ⋮ range: [166; 170), + ⋮ kind: TypeHint, + ⋮ label: "CustomOption", + ⋮ }, + ⋮ InlayHint { + ⋮ range: [343; 347), + ⋮ kind: TypeHint, + ⋮ label: "&Test", + ⋮ }, + ⋮ InlayHint { + ⋮ range: [401; 402), + ⋮ kind: TypeHint, + ⋮ label: "&CustomOption", + ⋮ }, + ⋮ InlayHint { + ⋮ range: [404; 405), + ⋮ kind: TypeHint, + ⋮ label: "&u8", + ⋮ }, + ⋮ InlayHint { + ⋮ range: [549; 550), + ⋮ kind: TypeHint, + ⋮ label: "&u32", + ⋮ }, + ⋮] + "### ); } -- cgit v1.2.3