rustc_ast_lowering/
block.rs1use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind};
2use rustc_hir as hir;
3use rustc_hir::Target;
4use rustc_span::sym;
5use smallvec::SmallVec;
6
7use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
8
9impl<'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 }
18
19 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 }
29
30 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 let item_id = self.lower_item_ref(it);
48 let hir_id = self.lower_node_id(s.id);
49 let kind = hir::StmtKind::Item(item_id);
50 let span = self.lower_span(s.span);
51 stmts.push(hir::Stmt { hir_id, kind, span });
52 }
53 StmtKind::Expr(e) => {
54 let e = self.lower_expr(e);
55 if tail.is_empty() {
56 expr = Some(e);
57 } else {
58 let hir_id = self.lower_node_id(s.id);
59 self.alias_attrs(hir_id, e.hir_id);
60 let kind = hir::StmtKind::Expr(e);
61 let span = self.lower_span(s.span);
62 stmts.push(hir::Stmt { hir_id, kind, span });
63 }
64 }
65 StmtKind::Semi(e) => {
66 let e = self.lower_expr(e);
67 let hir_id = self.lower_node_id(s.id);
68 self.alias_attrs(hir_id, e.hir_id);
69 let kind = hir::StmtKind::Semi(e);
70 let span = self.lower_span(s.span);
71 stmts.push(hir::Stmt { hir_id, kind, span });
72 }
73 StmtKind::Empty => {}
74 StmtKind::MacCall(..) => { ::core::panicking::panic_fmt(format_args!("shouldn\'t exist here")); }panic!("shouldn't exist here"),
75 }
76 ast_stmts = tail;
77 }
78 (self.arena.alloc_from_iter(stmts), expr)
79 }
80
81 fn impl_trait_in_bindings_ctxt(&self, position: ImplTraitPosition) -> ImplTraitContext {
84 if self.tcx.features().impl_trait_in_bindings() {
85 ImplTraitContext::InBinding
86 } else {
87 ImplTraitContext::FeatureGated(position, sym::impl_trait_in_bindings)
88 }
89 }
90
91 fn lower_local(&mut self, l: &Local) -> &'hir hir::LetStmt<'hir> {
92 let super_ = l.super_.map(|span| self.lower_span(span));
94 let ty = l.ty.as_ref().map(|t| {
95 self.lower_ty_alloc(t, self.impl_trait_in_bindings_ctxt(ImplTraitPosition::Variable))
96 });
97 let init = l.kind.init().map(|init| self.lower_expr(init));
98 let hir_id = self.lower_node_id(l.id);
99 let pat = self.lower_pat(&l.pat);
100 let els = if let LocalKind::InitElse(_, els) = &l.kind {
101 Some(self.lower_block(els, false))
102 } else {
103 None
104 };
105 let span = self.lower_span(l.span);
106 let source = hir::LocalSource::Normal;
107 self.lower_attrs(hir_id, &l.attrs, l.span, Target::Statement);
108 self.arena.alloc(hir::LetStmt { hir_id, super_, ty, pat, init, els, span, source })
109 }
110
111 fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
112 match *b {
113 BlockCheckMode::Default => hir::BlockCheckMode::DefaultBlock,
114 BlockCheckMode::Unsafe(u) => {
115 hir::BlockCheckMode::UnsafeBlock(self.lower_unsafe_source(u))
116 }
117 }
118 }
119}