]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast_lowering/src/block.rs
Auto merge of #98208 - ivanloz:master, r=nagisa
[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 use rustc_session::parse::feature_err;
5 use rustc_span::sym;
6
7 use smallvec::SmallVec;
8
9 impl<'a, 'hir> LoweringContext<'a, 'hir> {
10     pub(super) fn lower_block(
11         &mut self,
12         b: &Block,
13         targeted_by_break: bool,
14     ) -> &'hir hir::Block<'hir> {
15         self.arena.alloc(self.lower_block_noalloc(b, targeted_by_break))
16     }
17
18     pub(super) fn lower_block_noalloc(
19         &mut self,
20         b: &Block,
21         targeted_by_break: bool,
22     ) -> hir::Block<'hir> {
23         let (stmts, expr) = self.lower_stmts(&b.stmts);
24         let rules = self.lower_block_check_mode(&b.rules);
25         let hir_id = self.lower_node_id(b.id);
26         hir::Block { hir_id, stmts, expr, rules, span: self.lower_span(b.span), targeted_by_break }
27     }
28
29     fn lower_stmts(
30         &mut self,
31         mut ast_stmts: &[Stmt],
32     ) -> (&'hir [hir::Stmt<'hir>], Option<&'hir hir::Expr<'hir>>) {
33         let mut stmts = SmallVec::<[hir::Stmt<'hir>; 8]>::new();
34         let mut expr = None;
35         while let [s, tail @ ..] = ast_stmts {
36             match s.kind {
37                 StmtKind::Local(ref local) => {
38                     let hir_id = self.lower_node_id(s.id);
39                     let local = self.lower_local(local);
40                     self.alias_attrs(hir_id, local.hir_id);
41                     let kind = hir::StmtKind::Local(local);
42                     let span = self.lower_span(s.span);
43                     stmts.push(hir::Stmt { hir_id, kind, span });
44                 }
45                 StmtKind::Item(ref it) => {
46                     stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map(
47                         |(i, item_id)| {
48                             let hir_id = match i {
49                                 0 => self.lower_node_id(s.id),
50                                 _ => self.next_id(),
51                             };
52                             let kind = hir::StmtKind::Item(item_id);
53                             let span = self.lower_span(s.span);
54                             hir::Stmt { hir_id, kind, span }
55                         },
56                     ));
57                 }
58                 StmtKind::Expr(ref e) => {
59                     let e = self.lower_expr(e);
60                     if tail.is_empty() {
61                         expr = Some(e);
62                     } else {
63                         let hir_id = self.lower_node_id(s.id);
64                         self.alias_attrs(hir_id, e.hir_id);
65                         let kind = hir::StmtKind::Expr(e);
66                         let span = self.lower_span(s.span);
67                         stmts.push(hir::Stmt { hir_id, kind, span });
68                     }
69                 }
70                 StmtKind::Semi(ref e) => {
71                     let e = self.lower_expr(e);
72                     let hir_id = self.lower_node_id(s.id);
73                     self.alias_attrs(hir_id, e.hir_id);
74                     let kind = hir::StmtKind::Semi(e);
75                     let span = self.lower_span(s.span);
76                     stmts.push(hir::Stmt { hir_id, kind, span });
77                 }
78                 StmtKind::Empty => {}
79                 StmtKind::MacCall(..) => panic!("shouldn't exist here"),
80             }
81             ast_stmts = &ast_stmts[1..];
82         }
83         (self.arena.alloc_from_iter(stmts), expr)
84     }
85
86     fn lower_local(&mut self, l: &Local) -> &'hir hir::Local<'hir> {
87         let ty = l
88             .ty
89             .as_ref()
90             .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable)));
91         let init = l.kind.init().map(|init| self.lower_expr(init));
92         let hir_id = self.lower_node_id(l.id);
93         let pat = self.lower_pat(&l.pat);
94         let els = if let LocalKind::InitElse(_, els) = &l.kind {
95             if !self.tcx.features().let_else {
96                 feature_err(
97                     &self.tcx.sess.parse_sess,
98                     sym::let_else,
99                     l.span,
100                     "`let...else` statements are unstable",
101                 )
102                 .emit();
103             }
104             Some(self.lower_block(els, false))
105         } else {
106             None
107         };
108         let span = self.lower_span(l.span);
109         let source = hir::LocalSource::Normal;
110         self.lower_attrs(hir_id, &l.attrs);
111         self.arena.alloc(hir::Local { hir_id, ty, pat, init, els, span, source })
112     }
113
114     fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
115         match *b {
116             BlockCheckMode::Default => hir::BlockCheckMode::DefaultBlock,
117             BlockCheckMode::Unsafe(u) => {
118                 hir::BlockCheckMode::UnsafeBlock(self.lower_unsafe_source(u))
119             }
120         }
121     }
122 }