]> git.lizzy.rs Git - rust.git/commitdiff
implement while let desugaring
authorAleksey Kladov <aleksey.kladov@gmail.com>
Wed, 7 Aug 2019 13:14:22 +0000 (15:14 +0200)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Wed, 7 Aug 2019 13:14:22 +0000 (15:14 +0200)
crates/ra_hir/src/expr.rs
crates/ra_hir/src/marks.rs
crates/ra_hir/src/ty/tests.rs
crates/ra_ide_api/src/inlay_hints.rs

index b59787a83c8094ee1fd5d11b45edc4cf8d4cfbee..f33676655b2359da89d4d635b6f1a21b12f80e42 100644 (file)
     },
     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 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
                 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) => {
index 2d831f0d859b08a428f18697ed0049cd89621e2b..5b15eee901a9bde788ff3be6c76b9e800fde1a2a 100644 (file)
@@ -10,4 +10,5 @@
     std_prelude
     match_ergonomics_ref
     trait_resolution_on_fn_type
+    infer_while_let
 );
index 36dea17a30b3f7af808ed57f9cd4a76f47132229..d5f7a4d2503b71fdc68905a786b3213a2e9ef907 100644 (file)
@@ -144,6 +144,26 @@ impl<T> crate::iter::IntoIterator for Vec<T> {
     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]
 fn infer_basics() {
     assert_snapshot_matches!(
index 7b919031411086e228d2cfed765cb046a0d2496f..0b3c96d26aa63a179040d72d19975b149b6721b4 100644 (file)
@@ -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<Test>",
-    },
-]"#
+        assert_debug_snapshot_matches!(analysis.inlay_hints(file_id).unwrap(), @r###"
+       ⋮[
+       ⋮    InlayHint {
+       ⋮        range: [166; 170),
+       ⋮        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",
+       ⋮    },
+       ⋮]
+        "###
         );
     }