aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-08-07 14:14:22 +0100
committerAleksey Kladov <[email protected]>2019-08-07 14:14:22 +0100
commit6efc79b89d50b1b2ad9127afb2073bebe4b35290 (patch)
treec7209226fc680c545a02b0deb6da25c61a64500f /crates/ra_hir
parent39967a85e1f04676062d46b04e7ac8399c57df66 (diff)
implement while let desugaring
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/expr.rs40
-rw-r--r--crates/ra_hir/src/marks.rs1
-rw-r--r--crates/ra_hir/src/ty/tests.rs20
3 files changed, 47 insertions, 14 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::{
11 }, 11 },
12 AstNode, AstPtr, SyntaxNodePtr, 12 AstNode, AstPtr, SyntaxNodePtr,
13}; 13};
14use test_utils::tested_by;
14 15
15use crate::{ 16use crate::{
16 name::{AsName, SELF_PARAM}, 17 name::{AsName, SELF_PARAM},
18 path::GenericArgs,
19 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy},
17 type_ref::{Mutability, TypeRef}, 20 type_ref::{Mutability, TypeRef},
18 DefWithBody, Either, HasSource, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind, Name, 21 DefWithBody, Either, HasSource, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind, Name,
19 Path, Resolver, 22 Path, Resolver,
20}; 23};
21use crate::{
22 path::GenericArgs,
23 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy},
24};
25 24
26pub use self::scope::ExprScopes; 25pub use self::scope::ExprScopes;
27 26
@@ -603,17 +602,30 @@ where
603 self.alloc_expr(Expr::Loop { body }, syntax_ptr) 602 self.alloc_expr(Expr::Loop { body }, syntax_ptr)
604 } 603 }
605 ast::ExprKind::WhileExpr(e) => { 604 ast::ExprKind::WhileExpr(e) => {
606 let condition = if let Some(condition) = e.condition() {
607 if condition.pat().is_none() {
608 self.collect_expr_opt(condition.expr())
609 } else {
610 // FIXME handle while let
611 return self.alloc_expr(Expr::Missing, syntax_ptr);
612 }
613 } else {
614 self.exprs.alloc(Expr::Missing)
615 };
616 let body = self.collect_block_opt(e.loop_body()); 605 let body = self.collect_block_opt(e.loop_body());
606
607 let condition = match e.condition() {
608 None => self.exprs.alloc(Expr::Missing),
609 Some(condition) => match condition.pat() {
610 None => self.collect_expr_opt(condition.expr()),
611 // if let -- desugar to match
612 Some(pat) => {
613 tested_by!(infer_while_let);
614 let pat = self.collect_pat(pat);
615 let match_expr = self.collect_expr_opt(condition.expr());
616 let placeholder_pat = self.pats.alloc(Pat::Missing);
617 let break_ = self.exprs.alloc(Expr::Break { expr: None });
618 let arms = vec![
619 MatchArm { pats: vec![pat], expr: body, guard: None },
620 MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None },
621 ];
622 let match_expr =
623 self.exprs.alloc(Expr::Match { expr: match_expr, arms });
624 return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr);
625 }
626 },
627 };
628
617 self.alloc_expr(Expr::While { condition, body }, syntax_ptr) 629 self.alloc_expr(Expr::While { condition, body }, syntax_ptr)
618 } 630 }
619 ast::ExprKind::ForExpr(e) => { 631 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!(
10 std_prelude 10 std_prelude
11 match_ergonomics_ref 11 match_ergonomics_ref
12 trait_resolution_on_fn_type 12 trait_resolution_on_fn_type
13 infer_while_let
13); 14);
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
@@ -145,6 +145,26 @@ mod collections {
145} 145}
146 146
147#[test] 147#[test]
148fn infer_while_let() {
149 covers!(infer_while_let);
150 let (db, pos) = MockDatabase::with_position(
151 r#"
152//- /main.rs
153enum Option<T> { Some(T), None }
154
155fn test() {
156 let foo: Option<f32> = None;
157 while let Option::Some(x) = foo {
158 <|>x
159 }
160}
161
162"#,
163 );
164 assert_eq!("f32", type_at_pos(&db, pos));
165}
166
167#[test]
148fn infer_basics() { 168fn infer_basics() {
149 assert_snapshot_matches!( 169 assert_snapshot_matches!(
150 infer(r#" 170 infer(r#"