1use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind};2use rustc_hir as hir;3use rustc_hir::Target;4use rustc_span::sym;5use smallvec::SmallVec;67use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};89impl<'hir> LoweringContext<'_, 'hir> {10 pub(super) fn lower_block(11 &mut self,12 b: &Block,13 targeted_by_break: bool,14 ) -> &'hir hir::Block<'hir> {15 let hir_id = self.lower_node_id(b.id);16 self.arena.alloc(self.lower_block_noalloc(hir_id, b, targeted_by_break))17 }1819 pub(super) fn lower_block_noalloc(20 &mut self,21 hir_id: hir::HirId,22 b: &Block,23 targeted_by_break: bool,24 ) -> hir::Block<'hir> {25 let (stmts, expr) = self.lower_stmts(&b.stmts);26 let rules = self.lower_block_check_mode(&b.rules);27 hir::Block { hir_id, stmts, expr, rules, span: self.lower_span(b.span), targeted_by_break }28 }2930 pub(super) fn lower_stmts(31 &mut self,32 mut ast_stmts: &[Stmt],33 ) -> (&'hir [hir::Stmt<'hir>], Option<&'hir hir::Expr<'hir>>) {34 let mut stmts = SmallVec::<[hir::Stmt<'hir>; 8]>::new();35 let mut expr = None;36 while let [s, tail @ ..] = ast_stmts {37 match &s.kind {38 StmtKind::Let(local) => {39 let hir_id = self.lower_node_id(s.id);40 let local = self.lower_local(local);41 self.alias_attrs(hir_id, local.hir_id);42 let kind = hir::StmtKind::Let(local);43 let span = self.lower_span(s.span);44 stmts.push(hir::Stmt { hir_id, kind, span });45 }46 StmtKind::Item(it) => {47 stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map(48 |(i, item_id)| {49 let hir_id = match i {50 0 => self.lower_node_id(s.id),51 _ => self.next_id(),52 };53 let kind = hir::StmtKind::Item(item_id);54 let span = self.lower_span(s.span);55 hir::Stmt { hir_id, kind, span }56 },57 ));58 }59 StmtKind::Expr(e) => {60 let e = self.lower_expr(e);61 if tail.is_empty() {62 expr = Some(e);63 } else {64 let hir_id = self.lower_node_id(s.id);65 self.alias_attrs(hir_id, e.hir_id);66 let kind = hir::StmtKind::Expr(e);67 let span = self.lower_span(s.span);68 stmts.push(hir::Stmt { hir_id, kind, span });69 }70 }71 StmtKind::Semi(e) => {72 let e = self.lower_expr(e);73 let hir_id = self.lower_node_id(s.id);74 self.alias_attrs(hir_id, e.hir_id);75 let kind = hir::StmtKind::Semi(e);76 let span = self.lower_span(s.span);77 stmts.push(hir::Stmt { hir_id, kind, span });78 }79 StmtKind::Empty => {}80 StmtKind::MacCall(..) => panic!("shouldn't exist here"),81 }82 ast_stmts = tail;83 }84 (self.arena.alloc_from_iter(stmts), expr)85 }8687 /// Return an `ImplTraitContext` that allows impl trait in bindings if88 /// the feature gate is enabled, or issues a feature error if it is not.89 fn impl_trait_in_bindings_ctxt(&self, position: ImplTraitPosition) -> ImplTraitContext {90 if self.tcx.features().impl_trait_in_bindings() {91 ImplTraitContext::InBinding92 } else {93 ImplTraitContext::FeatureGated(position, sym::impl_trait_in_bindings)94 }95 }9697 fn lower_local(&mut self, l: &Local) -> &'hir hir::LetStmt<'hir> {98 // Let statements are allowed to have impl trait in bindings.99 let super_ = l.super_.map(|span| self.lower_span(span));100 let ty = l.ty.as_ref().map(|t| {101 self.lower_ty_alloc(t, self.impl_trait_in_bindings_ctxt(ImplTraitPosition::Variable))102 });103 let init = l.kind.init().map(|init| self.lower_expr(init));104 let hir_id = self.lower_node_id(l.id);105 let pat = self.lower_pat(&l.pat);106 let els = if let LocalKind::InitElse(_, els) = &l.kind {107 Some(self.lower_block(els, false))108 } else {109 None110 };111 let span = self.lower_span(l.span);112 let source = hir::LocalSource::Normal;113 self.lower_attrs(hir_id, &l.attrs, l.span, Target::Statement);114 self.arena.alloc(hir::LetStmt { hir_id, super_, ty, pat, init, els, span, source })115 }116117 fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {118 match *b {119 BlockCheckMode::Default => hir::BlockCheckMode::DefaultBlock,120 BlockCheckMode::Unsafe(u) => {121 hir::BlockCheckMode::UnsafeBlock(self.lower_unsafe_source(u))122 }123 }124 }125}