]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast_lowering/src/block.rs
Rollup merge of #106144 - tgross35:patch-1, r=Mark-Simulacrum
[rust.git] / compiler / rustc_ast_lowering / src / block.rs
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> {
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
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
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
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
103     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 }