diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 581f177ad14f6..5087258737806 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -64,7 +64,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; -use smallvec::{smallvec, SmallVec}; +use smallvec::SmallVec; use std::collections::BTreeMap; use std::mem; use tracing::{debug, trace}; @@ -1787,7 +1787,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) } - fn lower_local(&mut self, l: &Local) -> hir::Local<'hir> { + fn lower_local(&mut self, l: &Local) -> &'hir hir::Local<'hir> { let ty = l .ty .as_ref() @@ -1795,14 +1795,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let init = l.init.as_ref().map(|e| self.lower_expr(e)); let hir_id = self.lower_node_id(l.id); self.lower_attrs(hir_id, &l.attrs); - hir::Local { + self.arena.alloc(hir::Local { hir_id, ty, pat: self.lower_pat(&l.pat), init, span: l.span, source: hir::LocalSource::Normal, - } + }) } fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] { @@ -2388,15 +2388,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_block_noalloc(&mut self, b: &Block, targeted_by_break: bool) -> hir::Block<'hir> { - let (stmts, expr) = match &*b.stmts { - [stmts @ .., Stmt { kind: StmtKind::Expr(e), .. }] => (stmts, Some(&*e)), - stmts => (stmts, None), - }; - let stmts = self.arena.alloc_from_iter(stmts.iter().flat_map(|stmt| self.lower_stmt(stmt))); - let expr = expr.map(|e| self.lower_expr(e)); + let (stmts, expr) = self.lower_stmts(&b.stmts); let rules = self.lower_block_check_mode(&b.rules); let hir_id = self.lower_node_id(b.id); - hir::Block { hir_id, stmts, expr, rules, span: b.span, targeted_by_break } } @@ -2414,50 +2408,56 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) } - fn lower_stmt(&mut self, s: &Stmt) -> SmallVec<[hir::Stmt<'hir>; 1]> { - let (hir_id, kind) = match s.kind { - StmtKind::Local(ref l) => { - let l = self.lower_local(l); - let hir_id = self.lower_node_id(s.id); - self.alias_attrs(hir_id, l.hir_id); - return smallvec![hir::Stmt { - hir_id, - kind: hir::StmtKind::Local(self.arena.alloc(l)), - span: s.span, - }]; - } - StmtKind::Item(ref it) => { - // Can only use the ID once. - let mut id = Some(s.id); - return self - .lower_item_id(it) - .into_iter() - .map(|item_id| { - let hir_id = id - .take() - .map(|id| self.lower_node_id(id)) - .unwrap_or_else(|| self.next_id()); - - hir::Stmt { hir_id, kind: hir::StmtKind::Item(item_id), span: s.span } - }) - .collect(); - } - StmtKind::Expr(ref e) => { - let e = self.lower_expr(e); - let hir_id = self.lower_node_id(s.id); - self.alias_attrs(hir_id, e.hir_id); - (hir_id, hir::StmtKind::Expr(e)) - } - StmtKind::Semi(ref e) => { - let e = self.lower_expr(e); - let hir_id = self.lower_node_id(s.id); - self.alias_attrs(hir_id, e.hir_id); - (hir_id, hir::StmtKind::Semi(e)) + fn lower_stmts( + &mut self, + ast_stmts: &[Stmt], + ) -> (&'hir [hir::Stmt<'hir>], Option<&'hir hir::Expr<'hir>>) { + let mut stmts = SmallVec::<[hir::Stmt<'hir>; 8]>::new(); + let mut expr = None; + for (i, s) in ast_stmts.iter().enumerate() { + match s.kind { + StmtKind::Local(ref l) => { + let l = self.lower_local(l); + let hir_id = self.lower_node_id(s.id); + self.alias_attrs(hir_id, l.hir_id); + let kind = hir::StmtKind::Local(l); + stmts.push(hir::Stmt { hir_id, kind, span: s.span }); + } + StmtKind::Item(ref it) => { + stmts.extend(self.lower_item_id(it).into_iter().enumerate().map( + |(i, item_id)| { + let hir_id = match i { + 0 => self.lower_node_id(s.id), + _ => self.next_id(), + }; + + hir::Stmt { hir_id, kind: hir::StmtKind::Item(item_id), span: s.span } + }, + )); + } + StmtKind::Expr(ref e) => { + let e = self.lower_expr(e); + if i == ast_stmts.len() - 1 { + expr = Some(e); + } else { + let hir_id = self.lower_node_id(s.id); + self.alias_attrs(hir_id, e.hir_id); + let kind = hir::StmtKind::Expr(e); + stmts.push(hir::Stmt { hir_id, kind, span: s.span }); + } + } + StmtKind::Semi(ref e) => { + let e = self.lower_expr(e); + let hir_id = self.lower_node_id(s.id); + self.alias_attrs(hir_id, e.hir_id); + let kind = hir::StmtKind::Semi(e); + stmts.push(hir::Stmt { hir_id, kind, span: s.span }); + } + StmtKind::Empty => {} + StmtKind::MacCall(..) => panic!("shouldn't exist here"), } - StmtKind::Empty => return smallvec![], - StmtKind::MacCall(..) => panic!("shouldn't exist here"), - }; - smallvec![hir::Stmt { hir_id, kind, span: s.span }] + } + (self.arena.alloc_from_iter(stmts), expr) } fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {