1 use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
2 use rustc_ast::{AttrVec, Block, BlockCheckMode, Expr, Local, LocalKind, Stmt, StmtKind};
4 use rustc_session::parse::feature_err;
5 use rustc_span::{sym, DesugaringKind};
7 use smallvec::SmallVec;
9 impl<'a, 'hir> LoweringContext<'a, 'hir> {
10 pub(super) fn lower_block(
13 targeted_by_break: bool,
14 ) -> &'hir hir::Block<'hir> {
15 self.arena.alloc(self.lower_block_noalloc(b, targeted_by_break))
18 pub(super) fn lower_block_noalloc(
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 }
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();
35 while let [s, tail @ ..] = ast_stmts {
37 StmtKind::Local(ref local) => {
38 let hir_id = self.lower_node_id(s.id);
40 LocalKind::InitElse(init, els) => {
41 let e = self.lower_let_else(hir_id, local, init, els, tail);
43 // remaining statements are in let-else expression
47 let local = self.lower_local(local);
48 self.alias_attrs(hir_id, local.hir_id);
49 let kind = hir::StmtKind::Local(local);
50 let span = self.lower_span(s.span);
51 stmts.push(hir::Stmt { hir_id, kind, span });
55 StmtKind::Item(ref it) => {
56 stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map(
58 let hir_id = match i {
59 0 => self.lower_node_id(s.id),
62 let kind = hir::StmtKind::Item(item_id);
63 let span = self.lower_span(s.span);
64 hir::Stmt { hir_id, kind, span }
68 StmtKind::Expr(ref e) => {
69 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 let kind = hir::StmtKind::Expr(e);
76 let span = self.lower_span(s.span);
77 stmts.push(hir::Stmt { hir_id, kind, span });
80 StmtKind::Semi(ref e) => {
81 let e = self.lower_expr(e);
82 let hir_id = self.lower_node_id(s.id);
83 self.alias_attrs(hir_id, e.hir_id);
84 let kind = hir::StmtKind::Semi(e);
85 let span = self.lower_span(s.span);
86 stmts.push(hir::Stmt { hir_id, kind, span });
89 StmtKind::MacCall(..) => panic!("shouldn't exist here"),
91 ast_stmts = &ast_stmts[1..];
93 (self.arena.alloc_from_iter(stmts), expr)
96 fn lower_local(&mut self, l: &Local) -> &'hir hir::Local<'hir> {
100 .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding)));
101 let init = l.kind.init().map(|init| self.lower_expr(init));
102 let hir_id = self.lower_node_id(l.id);
103 let pat = self.lower_pat(&l.pat);
104 let span = self.lower_span(l.span);
105 let source = hir::LocalSource::Normal;
106 self.lower_attrs(hir_id, &l.attrs);
107 self.arena.alloc(hir::Local { hir_id, ty, pat, init, span, source })
110 fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
112 BlockCheckMode::Default => hir::BlockCheckMode::DefaultBlock,
113 BlockCheckMode::Unsafe(u) => {
114 hir::BlockCheckMode::UnsafeBlock(self.lower_unsafe_source(u))
121 stmt_hir_id: hir::HirId,
126 ) -> &'hir hir::Expr<'hir> {
130 .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding)));
131 let span = self.lower_span(local.span);
132 let span = self.mark_span_with_reason(DesugaringKind::LetElse, span, None);
133 let init = self.lower_expr(init);
134 let local_hir_id = self.lower_node_id(local.id);
135 self.lower_attrs(local_hir_id, &local.attrs);
137 let lex = self.arena.alloc(hir::Let {
138 hir_id: local_hir_id,
139 pat: self.lower_pat(&local.pat),
144 self.arena.alloc(self.expr(span, hir::ExprKind::Let(lex), AttrVec::new()))
147 let (stmts, expr) = self.lower_stmts(tail);
148 let block = self.block_all(span, stmts, expr);
149 self.arena.alloc(self.expr_block(block, AttrVec::new()))
152 let block = self.lower_block(els, false);
153 self.arena.alloc(self.expr_block(block, AttrVec::new()))
155 self.alias_attrs(let_expr.hir_id, local_hir_id);
156 self.alias_attrs(else_expr.hir_id, local_hir_id);
157 let if_expr = self.arena.alloc(hir::Expr {
160 kind: hir::ExprKind::If(let_expr, then_expr, Some(else_expr)),
162 if !self.sess.features_untracked().let_else {
164 &self.sess.parse_sess,
167 "`let...else` statements are unstable",