1 use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext}; 2 use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind}; 3 use rustc_hir as hir; 4 5 use smallvec::SmallVec; 6 7 impl<'a, 'hir> LoweringContext<'a, 'hir> { lower_block( &mut self, b: &Block, targeted_by_break: bool, ) -> &'hir hir::Block<'hir>8 pub(super) fn lower_block( 9 &mut self, 10 b: &Block, 11 targeted_by_break: bool, 12 ) -> &'hir hir::Block<'hir> { 13 self.arena.alloc(self.lower_block_noalloc(b, targeted_by_break)) 14 } 15 lower_block_noalloc( &mut self, b: &Block, targeted_by_break: bool, ) -> hir::Block<'hir>16 pub(super) fn lower_block_noalloc( 17 &mut self, 18 b: &Block, 19 targeted_by_break: bool, 20 ) -> hir::Block<'hir> { 21 let (stmts, expr) = self.lower_stmts(&b.stmts); 22 let rules = self.lower_block_check_mode(&b.rules); 23 let hir_id = self.lower_node_id(b.id); 24 hir::Block { hir_id, stmts, expr, rules, span: self.lower_span(b.span), targeted_by_break } 25 } 26 lower_stmts( &mut self, mut ast_stmts: &[Stmt], ) -> (&'hir [hir::Stmt<'hir>], Option<&'hir hir::Expr<'hir>>)27 fn lower_stmts( 28 &mut self, 29 mut ast_stmts: &[Stmt], 30 ) -> (&'hir [hir::Stmt<'hir>], Option<&'hir hir::Expr<'hir>>) { 31 let mut stmts = SmallVec::<[hir::Stmt<'hir>; 8]>::new(); 32 let mut expr = None; 33 while let [s, tail @ ..] = ast_stmts { 34 match &s.kind { 35 StmtKind::Local(local) => { 36 let hir_id = self.lower_node_id(s.id); 37 let local = self.lower_local(local); 38 self.alias_attrs(hir_id, local.hir_id); 39 let kind = hir::StmtKind::Local(local); 40 let span = self.lower_span(s.span); 41 stmts.push(hir::Stmt { hir_id, kind, span }); 42 } 43 StmtKind::Item(it) => { 44 stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map( 45 |(i, item_id)| { 46 let hir_id = match i { 47 0 => self.lower_node_id(s.id), 48 _ => self.next_id(), 49 }; 50 let kind = hir::StmtKind::Item(item_id); 51 let span = self.lower_span(s.span); 52 hir::Stmt { hir_id, kind, span } 53 }, 54 )); 55 } 56 StmtKind::Expr(e) => { 57 let e = self.lower_expr(e); 58 if tail.is_empty() { 59 expr = Some(e); 60 } else { 61 let hir_id = self.lower_node_id(s.id); 62 self.alias_attrs(hir_id, e.hir_id); 63 let kind = hir::StmtKind::Expr(e); 64 let span = self.lower_span(s.span); 65 stmts.push(hir::Stmt { hir_id, kind, span }); 66 } 67 } 68 StmtKind::Semi(e) => { 69 let e = self.lower_expr(e); 70 let hir_id = self.lower_node_id(s.id); 71 self.alias_attrs(hir_id, e.hir_id); 72 let kind = hir::StmtKind::Semi(e); 73 let span = self.lower_span(s.span); 74 stmts.push(hir::Stmt { hir_id, kind, span }); 75 } 76 StmtKind::Empty => {} 77 StmtKind::MacCall(..) => panic!("shouldn't exist here"), 78 } 79 ast_stmts = &ast_stmts[1..]; 80 } 81 (self.arena.alloc_from_iter(stmts), expr) 82 } 83 lower_local(&mut self, l: &Local) -> &'hir hir::Local<'hir>84 fn lower_local(&mut self, l: &Local) -> &'hir hir::Local<'hir> { 85 let ty = l 86 .ty 87 .as_ref() 88 .map(|t| self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); 89 let init = l.kind.init().map(|init| self.lower_expr(init)); 90 let hir_id = self.lower_node_id(l.id); 91 let pat = self.lower_pat(&l.pat); 92 let els = if let LocalKind::InitElse(_, els) = &l.kind { 93 Some(self.lower_block(els, false)) 94 } else { 95 None 96 }; 97 let span = self.lower_span(l.span); 98 let source = hir::LocalSource::Normal; 99 self.lower_attrs(hir_id, &l.attrs); 100 self.arena.alloc(hir::Local { hir_id, ty, pat, init, els, span, source }) 101 } 102 lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode103 fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode { 104 match *b { 105 BlockCheckMode::Default => hir::BlockCheckMode::DefaultBlock, 106 BlockCheckMode::Unsafe(u) => { 107 hir::BlockCheckMode::UnsafeBlock(self.lower_unsafe_source(u)) 108 } 109 } 110 } 111 } 112