]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir_def/src/body/lower.rs
Merge #11481
[rust.git] / crates / hir_def / src / body / lower.rs
index 372cf9aba8acb8eef03524c78634be1d3681bcde..06ad7ce4cd0887ebf7ba1570ee69b9614c90423b 100644 (file)
@@ -28,7 +28,7 @@
     db::DefDatabase,
     expr::{
         dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, Label, LabelId, Literal, MatchArm,
-        MatchGuard, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
+        Pat, PatId, RecordFieldPat, RecordLitField, Statement,
     },
     intern::Interned,
     item_scope::BuiltinShadowMode,
@@ -130,11 +130,7 @@ fn collect(
                 self.body.params.push(param_pat);
             }
 
-            for param in param_list.params() {
-                let pat = match param.pat() {
-                    None => continue,
-                    Some(pat) => pat,
-                };
+            for pat in param_list.params().filter_map(|param| param.pat()) {
                 let param_pat = self.collect_pat(pat);
                 self.body.params.push(param_pat);
             }
@@ -159,9 +155,6 @@ fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
     fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
         self.make_expr(expr, Err(SyntheticSyntax))
     }
-    fn unit(&mut self) -> ExprId {
-        self.alloc_expr_desugared(Expr::Tuple { exprs: Vec::new() })
-    }
     fn missing_expr(&mut self) -> ExprId {
         self.alloc_expr_desugared(Expr::Missing)
     }
@@ -219,32 +212,15 @@ fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
                     }
                 });
 
-                let condition = match e.condition() {
-                    None => self.missing_expr(),
-                    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.missing_pat();
-                            let arms = vec![
-                                MatchArm { pat, expr: then_branch, guard: None },
-                                MatchArm {
-                                    pat: placeholder_pat,
-                                    expr: else_branch.unwrap_or_else(|| self.unit()),
-                                    guard: None,
-                                },
-                            ];
-                            return Some(
-                                self.alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr),
-                            );
-                        }
-                    },
-                };
+                let condition = self.collect_expr_opt(e.condition());
 
                 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
             }
+            ast::Expr::LetExpr(e) => {
+                let pat = self.collect_pat_opt(e.pat());
+                let expr = self.collect_expr_opt(e.expr());
+                self.alloc_expr(Expr::Let { pat, expr }, syntax_ptr)
+            }
             ast::Expr::BlockExpr(e) => match e.modifier() {
                 Some(ast::BlockModifier::Try(_)) => {
                     let body = self.collect_block(e);
@@ -285,30 +261,7 @@ fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
                 let label = e.label().map(|label| self.collect_label(label));
                 let body = self.collect_block_opt(e.loop_body());
 
-                let condition = match e.condition() {
-                    None => self.missing_expr(),
-                    Some(condition) => match condition.pat() {
-                        None => self.collect_expr_opt(condition.expr()),
-                        // if let -- desugar to match
-                        Some(pat) => {
-                            cov_mark::hit!(infer_resolve_while_let);
-                            let pat = self.collect_pat(pat);
-                            let match_expr = self.collect_expr_opt(condition.expr());
-                            let placeholder_pat = self.missing_pat();
-                            let break_ =
-                                self.alloc_expr_desugared(Expr::Break { expr: None, label: None });
-                            let arms = vec![
-                                MatchArm { pat, expr: body, guard: None },
-                                MatchArm { pat: placeholder_pat, expr: break_, guard: None },
-                            ];
-                            let match_expr =
-                                self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
-                            return Some(
-                                self.alloc_expr(Expr::Loop { body: match_expr, label }, syntax_ptr),
-                            );
-                        }
-                    },
-                };
+                let condition = self.collect_expr_opt(e.condition());
 
                 self.alloc_expr(Expr::While { condition, body, label }, syntax_ptr)
             }
@@ -324,7 +277,7 @@ fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
                 let args = if let Some(arg_list) = e.arg_list() {
                     arg_list.args().filter_map(|e| self.maybe_collect_expr(e)).collect()
                 } else {
-                    Vec::new()
+                    Box::default()
                 };
                 self.alloc_expr(Expr::Call { callee, args }, syntax_ptr)
             }
@@ -333,7 +286,7 @@ fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
                 let args = if let Some(arg_list) = e.arg_list() {
                     arg_list.args().filter_map(|e| self.maybe_collect_expr(e)).collect()
                 } else {
-                    Vec::new()
+                    Box::default()
                 };
                 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
                 let generic_args = e
@@ -354,20 +307,14 @@ fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
                             self.check_cfg(&arm).map(|()| MatchArm {
                                 pat: self.collect_pat_opt(arm.pat()),
                                 expr: self.collect_expr_opt(arm.expr()),
-                                guard: arm.guard().map(|guard| match guard.pat() {
-                                    Some(pat) => MatchGuard::IfLet {
-                                        pat: self.collect_pat(pat),
-                                        expr: self.collect_expr_opt(guard.expr()),
-                                    },
-                                    None => {
-                                        MatchGuard::If { expr: self.collect_expr_opt(guard.expr()) }
-                                    }
-                                }),
+                                guard: arm
+                                    .guard()
+                                    .map(|guard| self.collect_expr_opt(guard.condition())),
                             })
                         })
                         .collect()
                 } else {
-                    Vec::new()
+                    Box::default()
                 };
                 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
             }
@@ -429,7 +376,7 @@ fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
                     let spread = nfl.spread().map(|s| self.collect_expr(s));
                     Expr::RecordLit { path, fields, spread }
                 } else {
-                    Expr::RecordLit { path, fields: Vec::new(), spread: None }
+                    Expr::RecordLit { path, fields: Box::default(), spread: None }
                 };
 
                 self.alloc_expr(record_lit, syntax_ptr)
@@ -496,7 +443,10 @@ fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
                     .and_then(|r| r.ty())
                     .map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
                 let body = self.collect_expr_opt(e.body());
-                self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
+                self.alloc_expr(
+                    Expr::Lambda { args: args.into(), arg_types: arg_types.into(), ret_type, body },
+                    syntax_ptr,
+                )
             }
             ast::Expr::BinExpr(e) => {
                 let lhs = self.collect_expr_opt(e.lhs());
@@ -551,7 +501,7 @@ fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
             ast::Expr::MacroCall(e) => {
                 let macro_ptr = AstPtr::new(&e);
                 let mut ids = vec![];
-                self.collect_macro_call(e, macro_ptr, |this, expansion| {
+                self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
                     ids.push(match expansion {
                         Some(it) => this.collect_expr(it),
                         None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
@@ -575,6 +525,7 @@ fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
         &mut self,
         e: ast::MacroCall,
         syntax_ptr: AstPtr<ast::MacroCall>,
+        record_diagnostics: bool,
         mut collector: F,
     ) {
         // File containing the macro call. Expansion errors will be attached here.
@@ -586,28 +537,32 @@ fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
         let res = match res {
             Ok(res) => res,
             Err(UnresolvedMacro { path }) => {
-                self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedMacroCall {
-                    node: InFile::new(outer_file, syntax_ptr),
-                    path,
-                });
+                if record_diagnostics {
+                    self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedMacroCall {
+                        node: InFile::new(outer_file, syntax_ptr),
+                        path,
+                    });
+                }
                 collector(self, None);
                 return;
             }
         };
 
-        match &res.err {
-            Some(ExpandError::UnresolvedProcMacro) => {
-                self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro {
-                    node: InFile::new(outer_file, syntax_ptr),
-                });
-            }
-            Some(err) => {
-                self.source_map.diagnostics.push(BodyDiagnostic::MacroError {
-                    node: InFile::new(outer_file, syntax_ptr),
-                    message: err.to_string(),
-                });
+        if record_diagnostics {
+            match &res.err {
+                Some(ExpandError::UnresolvedProcMacro) => {
+                    self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro {
+                        node: InFile::new(outer_file, syntax_ptr),
+                    });
+                }
+                Some(err) => {
+                    self.source_map.diagnostics.push(BodyDiagnostic::MacroError {
+                        node: InFile::new(outer_file, syntax_ptr),
+                        message: err.to_string(),
+                    });
+                }
+                None => {}
             }
-            None => {}
         }
 
         match res.value {
@@ -639,7 +594,16 @@ fn collect_stmt(&mut self, s: ast::Stmt) {
                 let type_ref =
                     stmt.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
                 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
-                self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer });
+                let else_branch = stmt
+                    .let_else()
+                    .and_then(|let_else| let_else.block_expr())
+                    .map(|block| self.collect_block(block));
+                self.statements_in_scope.push(Statement::Let {
+                    pat,
+                    type_ref,
+                    initializer,
+                    else_branch,
+                });
             }
             ast::Stmt::ExprStmt(stmt) => {
                 if let Some(expr) = stmt.expr() {
@@ -653,29 +617,33 @@ fn collect_stmt(&mut self, s: ast::Stmt) {
                     let macro_ptr = AstPtr::new(&m);
                     let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
 
-                    self.collect_macro_call(m, macro_ptr, |this, expansion| match expansion {
-                        Some(expansion) => {
-                            let statements: ast::MacroStmts = expansion;
-
-                            statements.statements().for_each(|stmt| this.collect_stmt(stmt));
-                            if let Some(expr) = statements.expr() {
-                                let expr = this.collect_expr(expr);
+                    self.collect_macro_call(
+                        m,
+                        macro_ptr,
+                        false,
+                        |this, expansion| match expansion {
+                            Some(expansion) => {
+                                let statements: ast::MacroStmts = expansion;
+
+                                statements.statements().for_each(|stmt| this.collect_stmt(stmt));
+                                if let Some(expr) = statements.expr() {
+                                    let expr = this.collect_expr(expr);
+                                    this.statements_in_scope
+                                        .push(Statement::Expr { expr, has_semi });
+                                }
+                            }
+                            None => {
+                                let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone());
                                 this.statements_in_scope.push(Statement::Expr { expr, has_semi });
                             }
-                        }
-                        None => {
-                            let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone());
-                            this.statements_in_scope.push(Statement::Expr { expr, has_semi });
-                        }
-                    });
+                        },
+                    );
                 } else {
                     let expr = self.collect_expr_opt(stmt.expr());
                     self.statements_in_scope.push(Statement::Expr { expr, has_semi });
                 }
             }
-            ast::Stmt::Item(item) => {
-                self.check_cfg(&item);
-            }
+            ast::Stmt::Item(_item) => {}
         }
     }
 
@@ -709,7 +677,7 @@ fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
             self.statements_in_scope.pop();
         }
         let tail = tail;
-        let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements);
+        let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements).into();
         let syntax_node_ptr = AstPtr::new(&block.into());
         let expr_id = self.alloc_expr(
             Expr::Block { id: block_id, statements, tail, label: None },
@@ -803,7 +771,7 @@ fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
             ast::Pat::RecordPat(p) => {
                 let path =
                     p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
-                let args: Vec<_> = p
+                let args = p
                     .record_pat_field_list()
                     .expect("every struct should have a field list")
                     .fields()
@@ -868,7 +836,7 @@ fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
                 Some(call) => {
                     let macro_ptr = AstPtr::new(&call);
                     let mut pat = None;
-                    self.collect_macro_call(call, macro_ptr, |this, expanded_pat| {
+                    self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
                         pat = Some(this.collect_pat_opt(expanded_pat));
                     });
 
@@ -893,7 +861,7 @@ fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId {
         }
     }
 
-    fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) {
+    fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Box<[PatId]>, Option<usize>) {
         // Find the location of the `..`, if there is one. Note that we do not
         // consider the possibility of there being multiple `..` here.
         let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_)));
@@ -952,7 +920,7 @@ fn from(ast_lit_kind: ast::LiteralKind) -> Self {
                 Literal::Float(Default::default(), ty)
             }
             LiteralKind::ByteString(bs) => {
-                let text = bs.value().map(Vec::from).unwrap_or_else(Default::default);
+                let text = bs.value().map(Box::from).unwrap_or_else(Default::default);
                 Literal::ByteString(text)
             }
             LiteralKind::String(_) => Literal::String(Default::default()),