]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast_lowering/src/block.rs
223825ad896d4e87307b1bd476e25e616daf6bd6
[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, 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) = match &*b.stmts {
22             [stmts @ .., Stmt { kind: StmtKind::Expr(e), .. }] => (stmts, Some(&*e)),
23             stmts => (stmts, None),
24         };
25         let stmts = self.arena.alloc_from_iter(stmts.iter().flat_map(|stmt| self.lower_stmt(stmt)));
26         let expr = expr.map(|e| self.lower_expr(e));
27         let rules = self.lower_block_check_mode(&b.rules);
28         let hir_id = self.lower_node_id(b.id);
29
30         hir::Block { hir_id, stmts, expr, rules, span: self.lower_span(b.span), targeted_by_break }
31     }
32
33     fn lower_stmt(&mut self, s: &Stmt) -> SmallVec<[hir::Stmt<'hir>; 1]> {
34         let (hir_id, kind) = 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                 return smallvec![hir::Stmt {
40                     hir_id,
41                     kind: hir::StmtKind::Local(self.arena.alloc(l)),
42                     span: self.lower_span(s.span),
43                 }];
44             }
45             StmtKind::Item(ref it) => {
46                 // Can only use the ID once.
47                 let mut id = Some(s.id);
48                 return self
49                     .lower_item_id(it)
50                     .into_iter()
51                     .map(|item_id| {
52                         let hir_id = id
53                             .take()
54                             .map(|id| self.lower_node_id(id))
55                             .unwrap_or_else(|| self.next_id());
56
57                         hir::Stmt {
58                             hir_id,
59                             kind: hir::StmtKind::Item(item_id),
60                             span: self.lower_span(s.span),
61                         }
62                     })
63                     .collect();
64             }
65             StmtKind::Expr(ref 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                 (hir_id, hir::StmtKind::Expr(e))
70             }
71             StmtKind::Semi(ref 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                 (hir_id, hir::StmtKind::Semi(e))
76             }
77             StmtKind::Empty => return smallvec![],
78             StmtKind::MacCall(..) => panic!("shouldn't exist here"),
79         };
80         smallvec![hir::Stmt { hir_id, kind, span: self.lower_span(s.span) }]
81     }
82
83     fn lower_local(&mut self, l: &Local) -> hir::Local<'hir> {
84         let ty = l
85             .ty
86             .as_ref()
87             .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding)));
88         let init = l.kind.init().map(|init| self.lower_expr(init));
89         let hir_id = self.lower_node_id(l.id);
90         self.lower_attrs(hir_id, &l.attrs);
91         hir::Local {
92             hir_id,
93             ty,
94             pat: self.lower_pat(&l.pat),
95             init,
96             span: self.lower_span(l.span),
97             source: hir::LocalSource::Normal,
98         }
99     }
100
101     fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
102         match *b {
103             BlockCheckMode::Default => hir::BlockCheckMode::DefaultBlock,
104             BlockCheckMode::Unsafe(u) => {
105                 hir::BlockCheckMode::UnsafeBlock(self.lower_unsafe_source(u))
106             }
107         }
108     }
109 }