]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast_lowering/src/block.rs
Rollup merge of #101802 - chriss0612:const_fn_trait_ref_impls, r=fee1-dead
[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.ty.as_ref().map(|t| {
88             self.lower_ty(t, &mut ImplTraitContext::Disallowed(ImplTraitPosition::Variable))
89         });
90         let init = l.kind.init().map(|init| self.lower_expr(init));
91         let hir_id = self.lower_node_id(l.id);
92         let pat = self.lower_pat(&l.pat);
93         let els = if let LocalKind::InitElse(_, els) = &l.kind {
94             if !self.tcx.features().let_else {
95                 feature_err(
96                     &self.tcx.sess.parse_sess,
97                     sym::let_else,
98                     l.span,
99                     "`let...else` statements are unstable",
100                 )
101                 .emit();
102             }
103             Some(self.lower_block(els, false))
104         } else {
105             None
106         };
107         let span = self.lower_span(l.span);
108         let source = hir::LocalSource::Normal;
109         self.lower_attrs(hir_id, &l.attrs);
110         self.arena.alloc(hir::Local { hir_id, ty, pat, init, els, span, source })
111     }
112
113     fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
114         match *b {
115             BlockCheckMode::Default => hir::BlockCheckMode::DefaultBlock,
116             BlockCheckMode::Unsafe(u) => {
117                 hir::BlockCheckMode::UnsafeBlock(self.lower_unsafe_source(u))
118             }
119         }
120     }
121 }