},
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;
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) => {
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!(