rust/compiler/rustc_ast_lowering/src/block.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

123 lines
4.7 KiB
Rust
Raw Normal View History

2021-08-04 13:09:02 -05:00
use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
2022-06-02 09:39:47 -05:00
use rustc_ast::{Block, BlockCheckMode, 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;
2022-06-02 09:39:47 -05:00
use rustc_span::sym;
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);
2022-06-02 09:39:47 -05:00
let local = self.lower_local(local);
self.alias_attrs(hir_id, local.hir_id);
let kind = hir::StmtKind::Local(local);
2022-06-02 09:39:47 -05:00
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 11:54:56 -05: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()
.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 els = if let LocalKind::InitElse(_, els) = &l.kind {
if !self.tcx.features().let_else {
feature_err(
&self.tcx.sess.parse_sess,
sym::let_else,
l.span,
"`let...else` statements are unstable",
)
.emit();
}
Some(self.lower_block(els, false))
} else {
None
};
2021-08-29 17:48:05 -05:00
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);
self.arena.alloc(hir::Local { hir_id, ty, pat, init, els, 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))
}
}
}
}