2021-08-04 13:09:02 -05:00
|
|
|
use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
|
2021-08-29 17:48:05 -05:00
|
|
|
use rustc_ast::{AttrVec, Block, BlockCheckMode, Expr, Local, LocalKind, Stmt, StmtKind};
|
2021-08-04 13:09:02 -05:00
|
|
|
use rustc_hir as hir;
|
2021-06-23 16:40:06 -05:00
|
|
|
use rustc_session::parse::feature_err;
|
2021-08-29 17:48:05 -05:00
|
|
|
use rustc_span::{sym, DesugaringKind};
|
2021-08-04 13:09:02 -05:00
|
|
|
|
2021-08-04 12:47:58 -05:00
|
|
|
use smallvec::SmallVec;
|
2021-08-04 13:09:02 -05:00
|
|
|
|
|
|
|
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|
|
|
pub(super) fn lower_block(
|
|
|
|
&mut self,
|
|
|
|
b: &Block,
|
|
|
|
targeted_by_break: bool,
|
|
|
|
) -> &'hir hir::Block<'hir> {
|
|
|
|
self.arena.alloc(self.lower_block_noalloc(b, targeted_by_break))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn lower_block_noalloc(
|
|
|
|
&mut self,
|
|
|
|
b: &Block,
|
|
|
|
targeted_by_break: bool,
|
|
|
|
) -> hir::Block<'hir> {
|
2021-08-04 12:47:58 -05:00
|
|
|
let (stmts, expr) = self.lower_stmts(&b.stmts);
|
2021-08-04 13:09:02 -05:00
|
|
|
let rules = self.lower_block_check_mode(&b.rules);
|
|
|
|
let hir_id = self.lower_node_id(b.id);
|
|
|
|
hir::Block { hir_id, stmts, expr, rules, span: self.lower_span(b.span), targeted_by_break }
|
|
|
|
}
|
|
|
|
|
2021-08-04 12:47:58 -05:00
|
|
|
fn lower_stmts(
|
|
|
|
&mut self,
|
|
|
|
mut ast_stmts: &[Stmt],
|
|
|
|
) -> (&'hir [hir::Stmt<'hir>], Option<&'hir hir::Expr<'hir>>) {
|
|
|
|
let mut stmts = SmallVec::<[hir::Stmt<'hir>; 8]>::new();
|
|
|
|
let mut expr = None;
|
|
|
|
while let [s, tail @ ..] = ast_stmts {
|
|
|
|
match s.kind {
|
2021-08-29 17:48:05 -05:00
|
|
|
StmtKind::Local(ref local) => {
|
2021-08-04 12:47:58 -05:00
|
|
|
let hir_id = self.lower_node_id(s.id);
|
2021-08-29 17:48:05 -05:00
|
|
|
match &local.kind {
|
|
|
|
LocalKind::InitElse(init, els) => {
|
2021-10-13 16:39:06 +11:00
|
|
|
let e = self.lower_let_else(hir_id, local, init, els, tail);
|
2021-08-29 17:48:05 -05:00
|
|
|
expr = Some(e);
|
|
|
|
// remaining statements are in let-else expression
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
let local = self.lower_local(local);
|
|
|
|
self.alias_attrs(hir_id, local.hir_id);
|
|
|
|
let kind = hir::StmtKind::Local(local);
|
|
|
|
let span = self.lower_span(s.span);
|
|
|
|
stmts.push(hir::Stmt { hir_id, kind, span });
|
|
|
|
}
|
|
|
|
}
|
2021-08-04 12:47:58 -05:00
|
|
|
}
|
|
|
|
StmtKind::Item(ref it) => {
|
2021-07-14 18:54:56 +02:00
|
|
|
stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map(
|
2021-08-04 12:47:58 -05:00
|
|
|
|(i, item_id)| {
|
|
|
|
let hir_id = match i {
|
|
|
|
0 => self.lower_node_id(s.id),
|
|
|
|
_ => self.next_id(),
|
|
|
|
};
|
|
|
|
let kind = hir::StmtKind::Item(item_id);
|
|
|
|
let span = self.lower_span(s.span);
|
|
|
|
hir::Stmt { hir_id, kind, span }
|
|
|
|
},
|
|
|
|
));
|
|
|
|
}
|
|
|
|
StmtKind::Expr(ref e) => {
|
|
|
|
let e = self.lower_expr(e);
|
|
|
|
if tail.is_empty() {
|
|
|
|
expr = Some(e);
|
|
|
|
} else {
|
|
|
|
let hir_id = self.lower_node_id(s.id);
|
|
|
|
self.alias_attrs(hir_id, e.hir_id);
|
|
|
|
let kind = hir::StmtKind::Expr(e);
|
|
|
|
let span = self.lower_span(s.span);
|
|
|
|
stmts.push(hir::Stmt { hir_id, kind, span });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
StmtKind::Semi(ref e) => {
|
|
|
|
let e = self.lower_expr(e);
|
|
|
|
let hir_id = self.lower_node_id(s.id);
|
|
|
|
self.alias_attrs(hir_id, e.hir_id);
|
|
|
|
let kind = hir::StmtKind::Semi(e);
|
|
|
|
let span = self.lower_span(s.span);
|
|
|
|
stmts.push(hir::Stmt { hir_id, kind, span });
|
|
|
|
}
|
|
|
|
StmtKind::Empty => {}
|
|
|
|
StmtKind::MacCall(..) => panic!("shouldn't exist here"),
|
2021-08-04 13:09:02 -05:00
|
|
|
}
|
2021-08-04 12:47:58 -05:00
|
|
|
ast_stmts = &ast_stmts[1..];
|
|
|
|
}
|
|
|
|
(self.arena.alloc_from_iter(stmts), expr)
|
2021-08-04 13:09:02 -05:00
|
|
|
}
|
|
|
|
|
2021-08-29 17:48:05 -05:00
|
|
|
fn lower_local(&mut self, l: &Local) -> &'hir hir::Local<'hir> {
|
2021-08-04 13:09:02 -05:00
|
|
|
let ty = l
|
|
|
|
.ty
|
|
|
|
.as_ref()
|
2022-01-11 19:00:34 -08:00
|
|
|
.map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable)));
|
2021-08-04 13:09:02 -05:00
|
|
|
let init = l.kind.init().map(|init| self.lower_expr(init));
|
|
|
|
let hir_id = self.lower_node_id(l.id);
|
2021-08-29 17:48:05 -05:00
|
|
|
let pat = self.lower_pat(&l.pat);
|
|
|
|
let span = self.lower_span(l.span);
|
|
|
|
let source = hir::LocalSource::Normal;
|
2021-08-04 13:09:02 -05:00
|
|
|
self.lower_attrs(hir_id, &l.attrs);
|
2021-08-29 17:48:05 -05:00
|
|
|
self.arena.alloc(hir::Local { hir_id, ty, pat, init, span, source })
|
2021-08-04 13:09:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
|
|
|
|
match *b {
|
|
|
|
BlockCheckMode::Default => hir::BlockCheckMode::DefaultBlock,
|
|
|
|
BlockCheckMode::Unsafe(u) => {
|
|
|
|
hir::BlockCheckMode::UnsafeBlock(self.lower_unsafe_source(u))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-29 17:48:05 -05:00
|
|
|
|
|
|
|
fn lower_let_else(
|
|
|
|
&mut self,
|
|
|
|
stmt_hir_id: hir::HirId,
|
|
|
|
local: &Local,
|
|
|
|
init: &Expr,
|
|
|
|
els: &Block,
|
|
|
|
tail: &[Stmt],
|
2021-10-13 16:39:06 +11:00
|
|
|
) -> &'hir hir::Expr<'hir> {
|
2021-08-29 17:48:05 -05:00
|
|
|
let ty = local
|
|
|
|
.ty
|
|
|
|
.as_ref()
|
2022-01-11 19:00:34 -08:00
|
|
|
.map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable)));
|
2021-08-29 17:48:05 -05:00
|
|
|
let span = self.lower_span(local.span);
|
|
|
|
let span = self.mark_span_with_reason(DesugaringKind::LetElse, span, None);
|
2021-10-13 16:39:06 +11:00
|
|
|
let init = self.lower_expr(init);
|
2021-08-29 17:48:05 -05:00
|
|
|
let local_hir_id = self.lower_node_id(local.id);
|
|
|
|
self.lower_attrs(local_hir_id, &local.attrs);
|
2021-10-13 16:39:06 +11:00
|
|
|
let let_expr = {
|
|
|
|
let lex = self.arena.alloc(hir::Let {
|
2021-08-29 17:48:05 -05:00
|
|
|
hir_id: local_hir_id,
|
2021-10-13 16:39:06 +11:00
|
|
|
pat: self.lower_pat(&local.pat),
|
2021-08-29 17:48:05 -05:00
|
|
|
ty,
|
|
|
|
init,
|
|
|
|
span,
|
|
|
|
});
|
2021-10-13 16:39:06 +11:00
|
|
|
self.arena.alloc(self.expr(span, hir::ExprKind::Let(lex), AttrVec::new()))
|
2021-08-29 17:48:05 -05:00
|
|
|
};
|
|
|
|
let then_expr = {
|
|
|
|
let (stmts, expr) = self.lower_stmts(tail);
|
|
|
|
let block = self.block_all(span, stmts, expr);
|
|
|
|
self.arena.alloc(self.expr_block(block, AttrVec::new()))
|
|
|
|
};
|
|
|
|
let else_expr = {
|
|
|
|
let block = self.lower_block(els, false);
|
|
|
|
self.arena.alloc(self.expr_block(block, AttrVec::new()))
|
|
|
|
};
|
2021-10-13 18:08:43 +11:00
|
|
|
self.alias_attrs(let_expr.hir_id, local_hir_id);
|
2021-08-29 17:48:05 -05:00
|
|
|
self.alias_attrs(else_expr.hir_id, local_hir_id);
|
|
|
|
let if_expr = self.arena.alloc(hir::Expr {
|
2021-10-13 16:39:06 +11:00
|
|
|
hir_id: stmt_hir_id,
|
2021-08-29 17:48:05 -05:00
|
|
|
span,
|
|
|
|
kind: hir::ExprKind::If(let_expr, then_expr, Some(else_expr)),
|
|
|
|
});
|
2022-05-02 20:32:17 +02:00
|
|
|
if !self.tcx.features().let_else {
|
2021-06-23 16:40:06 -05:00
|
|
|
feature_err(
|
2022-05-02 20:32:17 +02:00
|
|
|
&self.tcx.sess.parse_sess,
|
2021-06-23 16:40:06 -05:00
|
|
|
sym::let_else,
|
|
|
|
local.span,
|
|
|
|
"`let...else` statements are unstable",
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
}
|
2021-10-13 16:39:06 +11:00
|
|
|
if_expr
|
2021-08-29 17:48:05 -05:00
|
|
|
}
|
2021-08-04 13:09:02 -05:00
|
|
|
}
|