diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 40 | ||||
-rw-r--r-- | crates/ra_hir/src/marks.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 20 |
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 | }; |
14 | use test_utils::tested_by; | ||
14 | 15 | ||
15 | use crate::{ | 16 | use 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 | }; |
21 | use crate::{ | ||
22 | path::GenericArgs, | ||
23 | ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy}, | ||
24 | }; | ||
25 | 24 | ||
26 | pub use self::scope::ExprScopes; | 25 | pub 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] |
148 | fn infer_while_let() { | ||
149 | covers!(infer_while_let); | ||
150 | let (db, pos) = MockDatabase::with_position( | ||
151 | r#" | ||
152 | //- /main.rs | ||
153 | enum Option<T> { Some(T), None } | ||
154 | |||
155 | fn 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] | ||
148 | fn infer_basics() { | 168 | fn infer_basics() { |
149 | assert_snapshot_matches!( | 169 | assert_snapshot_matches!( |
150 | infer(r#" | 170 | infer(r#" |