]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast_lowering/src/block.rs
Refactor lower_stmts
[rust.git] / compiler / rustc_ast_lowering / src / block.rs
1 use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
2 use rustc_ast::{Block, BlockCheckMode, Local, 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(ref l) => {
36                     let l = self.lower_local(l);
37                     let hir_id = self.lower_node_id(s.id);
38                     self.alias_attrs(hir_id, l.hir_id);
39                     let kind = hir::StmtKind::Local(self.arena.alloc(l));
40                     let span = self.lower_span(s.span);
41                     stmts.push(hir::Stmt { hir_id, kind, span });
42                 }
43                 StmtKind::Item(ref it) => {
44                     stmts.extend(self.lower_item_id(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(ref 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(ref 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::Local<'hir> {
85         let ty = l
86             .ty
87             .as_ref()
88             .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding)));
89         let init = l.kind.init().map(|init| self.lower_expr(init));
90         let hir_id = self.lower_node_id(l.id);
91         self.lower_attrs(hir_id, &l.attrs);
92         hir::Local {
93             hir_id,
94             ty,
95             pat: self.lower_pat(&l.pat),
96             init,
97             span: self.lower_span(l.span),
98             source: hir::LocalSource::Normal,
99         }
100     }
101
102     fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
103         match *b {
104             BlockCheckMode::Default => hir::BlockCheckMode::DefaultBlock,
105             BlockCheckMode::Unsafe(u) => {
106                 hir::BlockCheckMode::UnsafeBlock(self.lower_unsafe_source(u))
107             }
108         }
109     }
110 }