Lowering for hir::Expr.

This commit is contained in:
Camille GILLOT 2019-11-29 19:01:31 +01:00
parent 52e9825ba8
commit 58b908d09c
5 changed files with 347 additions and 229 deletions

View File

@ -125,14 +125,25 @@ macro_rules! arena_types {
// HIR types
[few] hir_forest: rustc::hir::map::Forest<$tcx>,
[] arm: rustc::hir::Arm<$tcx>,
[] attribute: syntax::ast::Attribute,
[] block: rustc::hir::Block<$tcx>,
[few] global_asm: rustc::hir::GlobalAsm,
[] expr: rustc::hir::Expr<$tcx>,
[] field: rustc::hir::Field<$tcx>,
[] field_pat: rustc::hir::FieldPat<$tcx>,
[] fn_decl: rustc::hir::FnDecl,
[] foreign_item: rustc::hir::ForeignItem<$tcx>,
[] impl_item_ref: rustc::hir::ImplItemRef,
[] inline_asm: rustc::hir::InlineAsm<$tcx>,
[] local: rustc::hir::Local<$tcx>,
[few] macro_def: rustc::hir::MacroDef<$tcx>,
[] param: rustc::hir::Param<$tcx>,
[] pat: rustc::hir::Pat<$tcx>,
[] path: rustc::hir::Path,
[] path_segment: rustc::hir::PathSegment,
[] qpath: rustc::hir::QPath,
[] stmt: rustc::hir::Stmt<$tcx>,
[] struct_field: rustc::hir::StructField<$tcx>,
[] trait_item_ref: rustc::hir::TraitItemRef,
[] ty: rustc::hir::Ty,

View File

@ -921,7 +921,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn with_new_scopes<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
F: FnOnce(&mut Self) -> T,
{
let was_in_loop_condition = self.is_in_loop_condition;
self.is_in_loop_condition = false;
@ -2031,21 +2031,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
let ty = l.ty.as_ref().map(|t| {
self.lower_ty(
t,
if self.sess.features_untracked().impl_trait_in_bindings {
ImplTraitContext::OpaqueTy(Some(parent_def_id))
} else {
ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
},
)
});
let ty = ty.map(|ty| -> &'hir hir::Ty { self.arena.alloc(ty.into_inner()) });
let init = l
.init
.as_ref()
.map(|e| -> &'hir hir::Expr<'hir> { self.arena.alloc(self.lower_expr(e)) });
(
hir::Local {
hir_id: self.lower_node_id(l.id),
ty: l.ty.as_ref().map(|t| {
self.lower_ty(
t,
if self.sess.features_untracked().impl_trait_in_bindings {
ImplTraitContext::OpaqueTy(Some(parent_def_id))
} else {
ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
},
)
}),
ty,
pat: self.lower_pat(&l.pat),
init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
init,
span: l.span,
attrs: l.attrs.clone(),
source: hir::LocalSource::Normal,
@ -2586,14 +2592,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
}
fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block<'hir>> {
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))
}
fn lower_block_noalloc(&mut self, b: &Block, targeted_by_break: bool) -> hir::Block<'hir> {
let mut stmts = vec![];
let mut expr = None;
let mut expr: Option<&'hir _> = None;
for (index, stmt) in b.stmts.iter().enumerate() {
if index == b.stmts.len() - 1 {
if let StmtKind::Expr(ref e) = stmt.kind {
expr = Some(P(self.lower_expr(e)));
expr = Some(self.arena.alloc(self.lower_expr(e)));
} else {
stmts.extend(self.lower_stmt(stmt));
}
@ -2602,14 +2612,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
P(hir::Block {
hir::Block {
hir_id: self.lower_node_id(b.id),
stmts: stmts.into(),
stmts: self.arena.alloc_from_iter(stmts),
expr,
rules: self.lower_block_check_mode(&b.rules),
span: b.span,
targeted_by_break,
})
}
}
/// Lowers a block directly to an expression, presuming that it
@ -2619,7 +2629,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.expr_block(block, AttrVec::new())
}
fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat<'hir>> {
fn lower_pat(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
let node = match p.kind {
PatKind::Wild => hir::PatKind::Wild,
PatKind::Ident(ref binding_mode, ident, ref sub) => {
@ -2627,7 +2637,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let node = self.lower_pat_ident(p, binding_mode, ident, lower_sub);
node
}
PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
PatKind::Lit(ref e) => hir::PatKind::Lit(self.arena.alloc(self.lower_expr(e))),
PatKind::TupleStruct(ref path, ref pats) => {
let qpath = self.lower_qpath(
p.id,
@ -2640,7 +2650,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::PatKind::TupleStruct(qpath, pats, ddpos)
}
PatKind::Or(ref pats) => {
hir::PatKind::Or(pats.iter().map(|x| self.lower_pat(x)).collect())
hir::PatKind::Or(self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))))
}
PatKind::Path(ref qself, ref path) => {
let qpath = self.lower_qpath(
@ -2661,16 +2671,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ImplTraitContext::disallowed(),
);
let fs = fields
.iter()
.map(|f| hir::FieldPat {
hir_id: self.next_id(),
ident: f.ident,
pat: self.lower_pat(&f.pat),
is_shorthand: f.is_shorthand,
span: f.span,
})
.collect();
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::FieldPat {
hir_id: self.next_id(),
ident: f.ident,
pat: self.lower_pat(&f.pat),
is_shorthand: f.is_shorthand,
span: f.span,
}));
hir::PatKind::Struct(qpath, fs, etc)
}
PatKind::Tuple(ref pats) => {
@ -2680,8 +2687,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
PatKind::Ref(ref inner, mutbl) => hir::PatKind::Ref(self.lower_pat(inner), mutbl),
PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range(
P(self.lower_expr(e1)),
P(self.lower_expr(e2)),
self.arena.alloc(self.lower_expr(e1)),
self.arena.alloc(self.lower_expr(e2)),
self.lower_range_end(end),
),
PatKind::Slice(ref pats) => self.lower_pat_slice(pats),
@ -2700,7 +2707,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
pats: &[AstP<Pat>],
ctx: &str,
) -> (HirVec<P<hir::Pat<'hir>>>, Option<usize>) {
) -> (&'hir [&'hir hir::Pat<'hir>], Option<usize>) {
let mut elems = Vec::with_capacity(pats.len());
let mut rest = None;
@ -2728,7 +2735,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
(elems.into(), rest.map(|(ddpos, _)| ddpos))
(self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos))
}
/// Lower a slice pattern of form `[pat_0, ..., pat_n]` into
@ -2788,7 +2795,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
hir::PatKind::Slice(before.into(), slice, after.into())
hir::PatKind::Slice(
self.arena.alloc_from_iter(before),
slice,
self.arena.alloc_from_iter(after),
)
}
fn lower_pat_ident(
@ -2796,7 +2807,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
p: &Pat,
binding_mode: &BindingMode,
ident: Ident,
lower_sub: impl FnOnce(&mut Self) -> Option<P<hir::Pat<'hir>>>,
lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
) -> hir::PatKind<'hir> {
match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
// `None` can occur in body-less function signatures
@ -2824,13 +2835,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> P<hir::Pat<'hir>> {
fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
self.pat_with_node_id_of(p, hir::PatKind::Wild)
}
/// Construct a `Pat` with the `HirId` of `p.id` lowered.
fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> P<hir::Pat<'hir>> {
P(hir::Pat { hir_id: self.lower_node_id(p.id), kind, span: p.span })
fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
self.arena.alloc(hir::Pat { hir_id: self.lower_node_id(p.id), kind, span: p.span })
}
/// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
@ -2883,7 +2894,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ids.push({
hir::Stmt {
hir_id: self.lower_node_id(s.id),
kind: hir::StmtKind::Local(P(l)),
kind: hir::StmtKind::Local(self.arena.alloc(l)),
span: s.span,
}
});
@ -2905,8 +2916,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
})
.collect();
}
StmtKind::Expr(ref e) => hir::StmtKind::Expr(P(self.lower_expr(e))),
StmtKind::Semi(ref e) => hir::StmtKind::Semi(P(self.lower_expr(e))),
StmtKind::Expr(ref e) => hir::StmtKind::Expr(self.arena.alloc(self.lower_expr(e))),
StmtKind::Semi(ref e) => hir::StmtKind::Semi(self.arena.alloc(self.lower_expr(e))),
StmtKind::Mac(..) => panic!("shouldn't exist here"),
};
smallvec![hir::Stmt { hir_id: self.lower_node_id(s.id), kind, span: s.span }]
@ -2949,30 +2960,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
fn stmt_expr(&mut self, span: Span, expr: hir::Expr<'hir>) -> hir::Stmt<'hir> {
self.stmt(span, hir::StmtKind::Expr(P(expr)))
self.stmt(span, hir::StmtKind::Expr(self.arena.alloc(expr)))
}
fn stmt_let_pat(
&mut self,
attrs: AttrVec,
span: Span,
init: Option<P<hir::Expr<'hir>>>,
pat: P<hir::Pat<'hir>>,
init: Option<&'hir hir::Expr<'hir>>,
pat: &'hir hir::Pat<'hir>,
source: hir::LocalSource,
) -> hir::Stmt<'hir> {
let local = hir::Local { attrs, hir_id: self.next_id(), init, pat, source, span, ty: None };
self.stmt(span, hir::StmtKind::Local(P(local)))
self.stmt(span, hir::StmtKind::Local(self.arena.alloc(local)))
}
fn block_expr(&mut self, expr: P<hir::Expr<'hir>>) -> hir::Block<'hir> {
self.block_all(expr.span, hir::HirVec::new(), Some(expr))
fn block_expr(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Block<'hir> {
self.block_all(expr.span, &[], Some(expr))
}
fn block_all(
&mut self,
span: Span,
stmts: hir::HirVec<hir::Stmt<'hir>>,
expr: Option<P<hir::Expr<'hir>>>,
stmts: &'hir [hir::Stmt<'hir>],
expr: Option<&'hir hir::Expr<'hir>>,
) -> hir::Block<'hir> {
hir::Block {
stmts,
@ -2985,33 +2996,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
/// Constructs a `true` or `false` literal pattern.
fn pat_bool(&mut self, span: Span, val: bool) -> P<hir::Pat<'hir>> {
fn pat_bool(&mut self, span: Span, val: bool) -> &'hir hir::Pat<'hir> {
let expr = self.expr_bool(span, val);
self.pat(span, hir::PatKind::Lit(P(expr)))
self.pat(span, hir::PatKind::Lit(self.arena.alloc(expr)))
}
fn pat_ok(&mut self, span: Span, pat: P<hir::Pat<'hir>>) -> P<hir::Pat<'hir>> {
self.pat_std_enum(span, &[sym::result, sym::Result, sym::Ok], hir_vec![pat])
fn pat_ok(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
self.pat_std_enum(span, &[sym::result, sym::Result, sym::Ok], arena_vec![self; pat])
}
fn pat_err(&mut self, span: Span, pat: P<hir::Pat<'hir>>) -> P<hir::Pat<'hir>> {
self.pat_std_enum(span, &[sym::result, sym::Result, sym::Err], hir_vec![pat])
fn pat_err(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
self.pat_std_enum(span, &[sym::result, sym::Result, sym::Err], arena_vec![self; pat])
}
fn pat_some(&mut self, span: Span, pat: P<hir::Pat<'hir>>) -> P<hir::Pat<'hir>> {
self.pat_std_enum(span, &[sym::option, sym::Option, sym::Some], hir_vec![pat])
fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
self.pat_std_enum(span, &[sym::option, sym::Option, sym::Some], arena_vec![self; pat])
}
fn pat_none(&mut self, span: Span) -> P<hir::Pat<'hir>> {
self.pat_std_enum(span, &[sym::option, sym::Option, sym::None], hir_vec![])
fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> {
self.pat_std_enum(span, &[sym::option, sym::Option, sym::None], &[])
}
fn pat_std_enum(
&mut self,
span: Span,
components: &[Symbol],
subpats: hir::HirVec<P<hir::Pat<'hir>>>,
) -> P<hir::Pat<'hir>> {
subpats: &'hir [&'hir hir::Pat<'hir>],
) -> &'hir hir::Pat<'hir> {
let path = self.std_path(span, components, None, true);
let qpath = hir::QPath::Resolved(None, P(path));
let pt = if subpats.is_empty() {
@ -3022,7 +3033,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.pat(span, pt)
}
fn pat_ident(&mut self, span: Span, ident: Ident) -> (P<hir::Pat<'hir>>, hir::HirId) {
fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) {
self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated)
}
@ -3031,11 +3042,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: Span,
ident: Ident,
bm: hir::BindingAnnotation,
) -> (P<hir::Pat<'hir>>, hir::HirId) {
) -> (&'hir hir::Pat<'hir>, hir::HirId) {
let hir_id = self.next_id();
(
P(hir::Pat {
self.arena.alloc(hir::Pat {
hir_id,
kind: hir::PatKind::Binding(bm, hir_id, ident.with_span_pos(span), None),
span,
@ -3044,12 +3055,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
)
}
fn pat_wild(&mut self, span: Span) -> P<hir::Pat<'hir>> {
fn pat_wild(&mut self, span: Span) -> &'hir hir::Pat<'hir> {
self.pat(span, hir::PatKind::Wild)
}
fn pat(&mut self, span: Span, kind: hir::PatKind<'hir>) -> P<hir::Pat<'hir>> {
P(hir::Pat { hir_id: self.next_id(), kind, span })
fn pat(&mut self, span: Span, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
self.arena.alloc(hir::Pat { hir_id: self.next_id(), kind, span })
}
/// Given a suffix `["b", "c", "d"]`, returns path `::std::b::c::d` when

View File

@ -1,7 +1,7 @@
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
use crate::hir;
use crate::hir::def::Res;
use crate::hir::ptr::P;
use crate::hir::{self, HirVec};
use rustc_data_structures::thin_vec::ThinVec;
@ -14,26 +14,28 @@ use syntax::symbol::{sym, Symbol};
use rustc_error_codes::*;
impl<'hir> LoweringContext<'_, 'hir> {
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> HirVec<hir::Expr<'hir>> {
exprs.iter().map(|x| self.lower_expr(x)).collect()
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr(x)))
}
pub(super) fn lower_expr(&mut self, e: &Expr) -> hir::Expr<'hir> {
let kind = match e.kind {
ExprKind::Box(ref inner) => hir::ExprKind::Box(P(self.lower_expr(inner))),
ExprKind::Box(ref inner) => {
hir::ExprKind::Box(self.arena.alloc(self.lower_expr(inner)))
}
ExprKind::Array(ref exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
ExprKind::Repeat(ref expr, ref count) => {
let expr = P(self.lower_expr(expr));
let expr = self.arena.alloc(self.lower_expr(expr));
let count = self.lower_anon_const(count);
hir::ExprKind::Repeat(expr, count)
}
ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
ExprKind::Call(ref f, ref args) => {
let f = P(self.lower_expr(f));
let f = self.arena.alloc(self.lower_expr(f));
hir::ExprKind::Call(f, self.lower_exprs(args))
}
ExprKind::MethodCall(ref seg, ref args) => {
let hir_seg = P(self.lower_path_segment(
let hir_seg = self.arena.alloc(self.lower_path_segment(
e.span,
seg,
ParamMode::Optional,
@ -47,26 +49,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
ExprKind::Binary(binop, ref lhs, ref rhs) => {
let binop = self.lower_binop(binop);
let lhs = P(self.lower_expr(lhs));
let rhs = P(self.lower_expr(rhs));
let lhs = self.arena.alloc(self.lower_expr(lhs));
let rhs = self.arena.alloc(self.lower_expr(rhs));
hir::ExprKind::Binary(binop, lhs, rhs)
}
ExprKind::Unary(op, ref ohs) => {
let op = self.lower_unop(op);
let ohs = P(self.lower_expr(ohs));
let ohs = self.arena.alloc(self.lower_expr(ohs));
hir::ExprKind::Unary(op, ohs)
}
ExprKind::Lit(ref l) => hir::ExprKind::Lit(respan(l.span, l.kind.clone())),
ExprKind::Cast(ref expr, ref ty) => {
let expr = P(self.lower_expr(expr));
hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::disallowed()))
let expr = self.arena.alloc(self.lower_expr(expr));
let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
hir::ExprKind::Cast(expr, self.arena.alloc(ty.into_inner()))
}
ExprKind::Type(ref expr, ref ty) => {
let expr = P(self.lower_expr(expr));
hir::ExprKind::Type(expr, self.lower_ty(ty, ImplTraitContext::disallowed()))
let expr = self.arena.alloc(self.lower_expr(expr));
let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
hir::ExprKind::Type(expr, self.arena.alloc(ty.into_inner()))
}
ExprKind::AddrOf(k, m, ref ohs) => {
let ohs = P(self.lower_expr(ohs));
let ohs = self.arena.alloc(self.lower_expr(ohs));
hir::ExprKind::AddrOf(k, m, ohs)
}
ExprKind::Let(ref pat, ref scrutinee) => self.lower_expr_let(e.span, pat, scrutinee),
@ -85,8 +89,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
}),
ExprKind::TryBlock(ref body) => self.lower_expr_try_block(body),
ExprKind::Match(ref expr, ref arms) => hir::ExprKind::Match(
P(self.lower_expr(expr)),
arms.iter().map(|x| self.lower_arm(x)).collect(),
self.arena.alloc(self.lower_expr(expr)),
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
hir::MatchSource::Normal,
),
ExprKind::Async(capture_clause, closure_node_id, ref block) => self.make_async_expr(
@ -122,18 +126,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_block(blk, opt_label.is_some()),
self.lower_label(opt_label),
),
ExprKind::Assign(ref el, ref er, span) => {
hir::ExprKind::Assign(P(self.lower_expr(el)), P(self.lower_expr(er)), span)
}
ExprKind::Assign(ref el, ref er, span) => hir::ExprKind::Assign(
self.arena.alloc(self.lower_expr(el)),
self.arena.alloc(self.lower_expr(er)),
span,
),
ExprKind::AssignOp(op, ref el, ref er) => hir::ExprKind::AssignOp(
self.lower_binop(op),
P(self.lower_expr(el)),
P(self.lower_expr(er)),
self.arena.alloc(self.lower_expr(el)),
self.arena.alloc(self.lower_expr(er)),
),
ExprKind::Field(ref el, ident) => hir::ExprKind::Field(P(self.lower_expr(el)), ident),
ExprKind::Index(ref el, ref er) => {
hir::ExprKind::Index(P(self.lower_expr(el)), P(self.lower_expr(er)))
ExprKind::Field(ref el, ident) => {
hir::ExprKind::Field(self.arena.alloc(self.lower_expr(el)), ident)
}
ExprKind::Index(ref el, ref er) => hir::ExprKind::Index(
self.arena.alloc(self.lower_expr(el)),
self.arena.alloc(self.lower_expr(er)),
),
ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => {
self.lower_expr_range_closed(e.span, e1, e2)
}
@ -150,26 +159,38 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
hir::ExprKind::Path(qpath)
}
ExprKind::Break(opt_label, ref opt_expr) => hir::ExprKind::Break(
self.lower_jump_destination(e.id, opt_label),
opt_expr.as_ref().map(|x| P(self.lower_expr(x))),
),
ExprKind::Break(opt_label, ref opt_expr) => {
let opt_expr = opt_expr
.as_ref()
.map(|x| -> &'hir hir::Expr<'hir> { self.arena.alloc(self.lower_expr(x)) });
hir::ExprKind::Break(self.lower_jump_destination(e.id, opt_label), opt_expr)
}
ExprKind::Continue(opt_label) => {
hir::ExprKind::Continue(self.lower_jump_destination(e.id, opt_label))
}
ExprKind::Ret(ref e) => hir::ExprKind::Ret(e.as_ref().map(|x| P(self.lower_expr(x)))),
ExprKind::Ret(ref e) => {
let e = e
.as_ref()
.map(|x| -> &'hir hir::Expr<'hir> { self.arena.alloc(self.lower_expr(x)) });
hir::ExprKind::Ret(e)
}
ExprKind::InlineAsm(ref asm) => self.lower_expr_asm(asm),
ExprKind::Struct(ref path, ref fields, ref maybe_expr) => hir::ExprKind::Struct(
P(self.lower_qpath(
e.id,
&None,
path,
ParamMode::Optional,
ImplTraitContext::disallowed(),
)),
fields.iter().map(|x| self.lower_field(x)).collect(),
maybe_expr.as_ref().map(|x| P(self.lower_expr(x))),
),
ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
let maybe_expr = maybe_expr
.as_ref()
.map(|x| -> &'hir hir::Expr<'hir> { self.arena.alloc(self.lower_expr(x)) });
hir::ExprKind::Struct(
self.arena.alloc(self.lower_qpath(
e.id,
&None,
path,
ParamMode::Optional,
ImplTraitContext::disallowed(),
)),
self.arena.alloc_from_iter(fields.iter().map(|x| self.lower_field(x))),
maybe_expr,
)
}
ExprKind::Paren(ref ex) => {
let mut ex = self.lower_expr(ex);
// Include parens in span, but only if it is a super-span.
@ -266,16 +287,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
let then_arm = {
let pat = self.lower_pat(pat);
let expr = self.expr_bool(span, true);
self.arm(pat, P(expr))
self.arm(pat, self.arena.alloc(expr))
};
let else_arm = {
let pat = self.pat_wild(span);
let expr = self.expr_bool(span, false);
self.arm(pat, P(expr))
self.arm(pat, self.arena.alloc(expr))
};
hir::ExprKind::Match(
P(scrutinee),
vec![then_arm, else_arm].into(),
self.arena.alloc(scrutinee),
arena_vec![self; then_arm, else_arm],
hir::MatchSource::Normal,
)
}
@ -295,7 +316,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
None => (self.expr_block_empty(span), false),
Some(els) => (self.lower_expr(els), true),
};
let else_arm = self.arm(else_pat, P(else_expr));
let else_arm = self.arm(else_pat, self.arena.alloc(else_expr));
// Handle then + scrutinee:
let then_expr = self.lower_block_expr(then);
@ -315,14 +336,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Wrap in a construct equivalent to `{ let _t = $cond; _t }`
// to preserve drop semantics since `if cond { ... }` does not
// let temporaries live outside of `cond`.
let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new());
let cond = self.expr_drop_temps(span_block, self.arena.alloc(cond), ThinVec::new());
let pat = self.pat_bool(span, true);
(pat, cond, hir::MatchSource::IfDesugar { contains_else_clause })
}
};
let then_arm = self.arm(then_pat, P(then_expr));
let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
hir::ExprKind::Match(P(scrutinee), vec![then_arm, else_arm].into(), desugar)
hir::ExprKind::Match(
self.arena.alloc(scrutinee),
arena_vec![self; then_arm, else_arm],
desugar,
)
}
fn lower_expr_while_in_loop_scope(
@ -379,20 +404,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Wrap in a construct equivalent to `{ let _t = $cond; _t }`
// to preserve drop semantics since `while cond { ... }` does not
// let temporaries live outside of `cond`.
let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new());
let cond = self.expr_drop_temps(span_block, self.arena.alloc(cond), ThinVec::new());
// `true => <then>`:
let pat = self.pat_bool(span, true);
(pat, cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While)
}
};
let then_arm = self.arm(then_pat, P(then_expr));
let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
// `match <scrutinee> { ... }`
let match_expr =
self.expr_match(scrutinee.span, P(scrutinee), hir_vec![then_arm, else_arm], desugar);
let match_expr = self.expr_match(
scrutinee.span,
self.arena.alloc(scrutinee),
arena_vec![self; then_arm, else_arm],
desugar,
);
// `[opt_ident]: loop { ... }`
hir::ExprKind::Loop(P(self.block_expr(P(match_expr))), self.lower_label(opt_label), source)
hir::ExprKind::Loop(
self.arena.alloc(self.block_expr(self.arena.alloc(match_expr))),
self.lower_label(opt_label),
source,
)
}
/// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_ok(<expr>) }`,
@ -400,7 +433,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// and save the block id to use it as a break target for desugaring of the `?` operator.
fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> {
self.with_catch_scope(body.id, |this| {
let mut block = this.lower_block(body, true).into_inner();
let mut block = this.lower_block_noalloc(body, true);
let try_span = this.mark_span_with_reason(
DesugaringKind::TryBlock,
@ -410,8 +443,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Final expression of the block (if present) or `()` with span at the end of block
let tail_expr = block.expr.take().map_or_else(
|| this.expr_unit(this.sess.source_map().end_point(try_span)),
|x: P<hir::Expr<'hir>>| x.into_inner(),
|| -> &'hir hir::Expr<'hir> {
this.arena.alloc(this.expr_unit(this.sess.source_map().end_point(try_span)))
},
|x: &'hir hir::Expr<'hir>| x,
);
let ok_wrapped_span =
@ -425,7 +460,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ok_wrapped_span,
));
hir::ExprKind::Block(P(block), None)
hir::ExprKind::Block(this.arena.alloc(block), None)
})
}
@ -433,24 +468,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
&mut self,
method: Symbol,
method_span: Span,
expr: hir::Expr<'hir>,
expr: &'hir hir::Expr<'hir>,
overall_span: Span,
) -> P<hir::Expr<'hir>> {
) -> &'hir hir::Expr<'hir> {
let path = &[sym::ops, sym::Try, method];
let constructor = P(self.expr_std_path(method_span, path, None, ThinVec::new()));
P(self.expr_call(overall_span, constructor, hir_vec![expr]))
let constructor =
self.arena.alloc(self.expr_std_path(method_span, path, None, ThinVec::new()));
self.arena.alloc(self.expr_call(overall_span, constructor, std::slice::from_ref(expr)))
}
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
hir::Arm {
hir_id: self.next_id(),
attrs: self.lower_attrs(&arm.attrs),
attrs: self.lower_attrs_arena(&arm.attrs),
pat: self.lower_pat(&arm.pat),
guard: match arm.guard {
Some(ref x) => Some(hir::Guard::If(P(self.lower_expr(x)))),
Some(ref x) => Some(hir::Guard::If(self.arena.alloc(self.lower_expr(x)))),
_ => None,
},
body: P(self.lower_expr(&arm.body)),
body: self.arena.alloc(self.lower_expr(&arm.body)),
span: arm.span,
}
}
@ -469,7 +505,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
None => FunctionRetTy::Default(span),
};
let ast_decl = FnDecl { inputs: vec![], output };
let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None);
let decl = self.arena.alloc(
self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None).into_inner(),
);
let body_id = self.lower_fn_body(&ast_decl, |this| {
this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind));
body(this)
@ -501,7 +539,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
// `future::from_generator(generator)`:
hir::ExprKind::Call(P(gen_future), hir_vec![generator])
hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
}
/// Desugar `<expr>.await` into:
@ -550,7 +588,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// ::std::pin::Pin::new_unchecked(&mut pinned)
// })`
let poll_expr = {
let pinned = P(self.expr_ident(span, pinned_ident, pinned_pat_hid));
let pinned = self.arena.alloc(self.expr_ident(span, pinned_ident, pinned_pat_hid));
let ref_mut_pinned = self.expr_mut_addr_of(span, pinned);
let pin_ty_id = self.next_id();
let new_unchecked_expr_kind = self.expr_call_std_assoc_fn(
@ -558,14 +596,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
span,
&[sym::pin, sym::Pin],
"new_unchecked",
hir_vec![ref_mut_pinned],
arena_vec![self; ref_mut_pinned],
);
let new_unchecked = P(self.expr(span, new_unchecked_expr_kind, ThinVec::new()));
let new_unchecked =
self.arena.alloc(self.expr(span, new_unchecked_expr_kind, ThinVec::new()));
let unsafe_expr = self.expr_unsafe(new_unchecked);
P(self.expr_call_std_path(
self.arena.alloc(self.expr_call_std_path(
gen_future_span,
&[sym::future, sym::poll_with_tls_context],
hir_vec![unsafe_expr],
arena_vec![self; unsafe_expr],
))
};
@ -575,22 +614,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
let ready_arm = {
let x_ident = Ident::with_dummy_span(sym::result);
let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid));
let ready_pat =
self.pat_std_enum(span, &[sym::task, sym::Poll, sym::Ready], hir_vec![x_pat]);
let break_x = self.with_loop_scope(loop_node_id, |this| {
let x_expr = self.arena.alloc(self.expr_ident(span, x_ident, x_pat_hid));
let ready_pat = self.pat_std_enum(
span,
&[sym::task, sym::Poll, sym::Ready],
arena_vec![self; x_pat],
);
let break_x = self.with_loop_scope(loop_node_id, move |this| {
let expr_break =
hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
P(this.expr(await_span, expr_break, ThinVec::new()))
this.arena.alloc(this.expr(await_span, expr_break, ThinVec::new()))
});
self.arm(ready_pat, break_x)
};
// `::std::task::Poll::Pending => {}`
let pending_arm = {
let pending_pat =
self.pat_std_enum(span, &[sym::task, sym::Poll, sym::Pending], hir_vec![]);
let empty_block = P(self.expr_block_empty(span));
let pending_pat = self.pat_std_enum(span, &[sym::task, sym::Poll, sym::Pending], &[]);
let empty_block = self.arena.alloc(self.expr_block_empty(span));
self.arm(pending_pat, empty_block)
};
@ -598,7 +639,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let match_expr = self.expr_match(
span,
poll_expr,
hir_vec![ready_arm, pending_arm],
arena_vec![self; ready_arm, pending_arm],
hir::MatchSource::AwaitDesugar,
);
self.stmt_expr(span, match_expr)
@ -608,16 +649,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
let unit = self.expr_unit(span);
let yield_expr = self.expr(
span,
hir::ExprKind::Yield(P(unit), hir::YieldSource::Await),
hir::ExprKind::Yield(self.arena.alloc(unit), hir::YieldSource::Await),
ThinVec::new(),
);
self.stmt_expr(span, yield_expr)
};
let loop_block = P(self.block_all(span, hir_vec![inner_match_stmt, yield_stmt], None));
let loop_block = self.arena.alloc(self.block_all(
span,
arena_vec![self; inner_match_stmt, yield_stmt],
None,
));
// loop { .. }
let loop_expr = P(hir::Expr {
let loop_expr = self.arena.alloc(hir::Expr {
hir_id: loop_hir_id,
kind: hir::ExprKind::Loop(loop_block, None, hir::LoopSource::Loop),
span,
@ -630,8 +675,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
// match <expr> {
// mut pinned => loop { .. }
// }
let expr = P(self.lower_expr(expr));
hir::ExprKind::Match(expr, hir_vec![pinned_arm], hir::MatchSource::AwaitDesugar)
let expr = self.arena.alloc(self.lower_expr(expr));
hir::ExprKind::Match(expr, arena_vec![self; pinned_arm], hir::MatchSource::AwaitDesugar)
}
fn lower_expr_closure(
@ -644,8 +689,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
) -> hir::ExprKind<'hir> {
// Lower outside new scope to preserve `is_in_loop_condition`.
let fn_decl = self.lower_fn_decl(decl, None, false, None);
let fn_decl = self.arena.alloc(fn_decl.into_inner());
self.with_new_scopes(|this| {
self.with_new_scopes(move |this| {
let prev = this.current_item;
this.current_item = Some(fn_decl_span);
let mut generator_kind = None;
@ -706,8 +752,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
// have to conserve the state of being inside a loop condition for the
// closure argument types.
let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
let fn_decl = self.arena.alloc(fn_decl.into_inner());
self.with_new_scopes(|this| {
self.with_new_scopes(move |this| {
// FIXME(cramertj): allow `async` non-`move` closures with arguments.
if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
struct_span_err!(
@ -752,7 +799,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
span,
&[sym::ops, sym::RangeInclusive],
"new",
hir_vec![e1, e2],
arena_vec![self; e1, e2],
)
}
@ -777,16 +824,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
};
let fields = e1
.iter()
.map(|e| ("start", e))
.chain(e2.iter().map(|e| ("end", e)))
.map(|(s, e)| {
let expr = P(self.lower_expr(&e));
let fields = self.arena.alloc_from_iter(
e1.iter().map(|e| ("start", e)).chain(e2.iter().map(|e| ("end", e))).map(|(s, e)| {
let expr = self.arena.alloc(self.lower_expr(&e));
let ident = Ident::new(Symbol::intern(s), e.span);
self.field(ident, expr, e.span)
})
.collect::<P<[hir::Field<'hir>]>>();
}),
);
let is_unit = fields.is_empty();
let struct_path = [sym::ops, path];
@ -796,7 +840,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
if is_unit {
hir::ExprKind::Path(struct_path)
} else {
hir::ExprKind::Struct(P(struct_path), fields, None)
hir::ExprKind::Struct(self.arena.alloc(struct_path), fields, None)
}
}
@ -837,7 +881,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn with_catch_scope<T, F>(&mut self, catch_id: NodeId, f: F) -> T
where
F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
F: FnOnce(&mut Self) -> T,
{
let len = self.catch_scopes.len();
self.catch_scopes.push(catch_id);
@ -856,7 +900,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
where
F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
F: FnOnce(&mut Self) -> T,
{
// We're no longer in the base loop's condition; we're in another loop.
let was_in_loop_condition = self.is_in_loop_condition;
@ -881,7 +925,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn with_loop_condition_scope<T, F>(&mut self, f: F) -> T
where
F: FnOnce(&mut LoweringContext<'_, '_>) -> T,
F: FnOnce(&mut Self) -> T,
{
let was_in_loop_condition = self.is_in_loop_condition;
self.is_in_loop_condition = true;
@ -915,17 +959,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
};
let hir_asm = hir::InlineAsm {
inner,
inputs_exprs: asm.inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect(),
outputs_exprs: asm.outputs.iter().map(|out| self.lower_expr(&out.expr)).collect(),
inputs_exprs: self
.arena
.alloc_from_iter(asm.inputs.iter().map(|&(_, ref input)| self.lower_expr(input))),
outputs_exprs: self
.arena
.alloc_from_iter(asm.outputs.iter().map(|out| self.lower_expr(&out.expr))),
};
hir::ExprKind::InlineAsm(P(hir_asm))
hir::ExprKind::InlineAsm(self.arena.alloc(hir_asm))
}
fn lower_field(&mut self, f: &Field) -> hir::Field<'hir> {
hir::Field {
hir_id: self.next_id(),
ident: f.ident,
expr: P(self.lower_expr(&f.expr)),
expr: self.arena.alloc(self.lower_expr(&f.expr)),
span: f.span,
is_shorthand: f.is_shorthand,
}
@ -944,7 +992,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let expr =
opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
hir::ExprKind::Yield(P(expr), hir::YieldSource::Yield)
hir::ExprKind::Yield(self.arena.alloc(expr), hir::YieldSource::Yield)
}
/// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
@ -992,9 +1040,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
let pat_arm = {
let val_ident = Ident::with_dummy_span(sym::val);
let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
let assign = P(self.expr(
let val_expr = self.arena.alloc(self.expr_ident(pat.span, val_ident, val_pat_hid));
let next_expr = self.arena.alloc(self.expr_ident(pat.span, next_ident, next_pat_hid));
let assign = self.arena.alloc(self.expr(
pat.span,
hir::ExprKind::Assign(next_expr, val_expr, pat.span),
ThinVec::new(),
@ -1017,18 +1065,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
let match_expr = {
let iter = P(self.expr_ident(desugared_span, iter, iter_pat_nid));
let iter = self.arena.alloc(self.expr_ident(desugared_span, iter, iter_pat_nid));
let ref_mut_iter = self.expr_mut_addr_of(desugared_span, iter);
let next_path = &[sym::iter, sym::Iterator, sym::next];
let next_expr =
P(self.expr_call_std_path(desugared_span, next_path, hir_vec![ref_mut_iter]));
let arms = hir_vec![pat_arm, break_arm];
let next_expr = self.arena.alloc(self.expr_call_std_path(
desugared_span,
next_path,
arena_vec![self; ref_mut_iter],
));
let arms = arena_vec![self; pat_arm, break_arm];
self.expr_match(desugared_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
};
let match_stmt = self.stmt_expr(desugared_span, match_expr);
let next_expr = P(self.expr_ident(desugared_span, next_ident, next_pat_hid));
let next_expr = self.arena.alloc(self.expr_ident(desugared_span, next_ident, next_pat_hid));
// `let mut __next`
let next_let = self.stmt_let_pat(
@ -1053,13 +1104,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
let body_expr = self.expr_block(body_block, ThinVec::new());
let body_stmt = self.stmt_expr(body.span, body_expr);
let loop_block =
P(self.block_all(e.span, hir_vec![next_let, match_stmt, pat_let, body_stmt], None));
let loop_block = self.arena.alloc(self.block_all(
e.span,
arena_vec![self; next_let, match_stmt, pat_let, body_stmt],
None,
));
// `[opt_ident]: loop { ... }`
let kind =
hir::ExprKind::Loop(loop_block, self.lower_label(opt_label), hir::LoopSource::ForLoop);
let loop_expr = P(hir::Expr {
let loop_expr = self.arena.alloc(hir::Expr {
hir_id: self.lower_node_id(e.id),
kind,
span: e.span,
@ -1072,13 +1126,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
let into_iter_expr = {
let into_iter_path = &[sym::iter, sym::IntoIterator, sym::into_iter];
P(self.expr_call_std_path(desugared_span, into_iter_path, hir_vec![head]))
self.arena.alloc(self.expr_call_std_path(
desugared_span,
into_iter_path,
arena_vec![self; head],
))
};
let match_expr = P(self.expr_match(
let match_expr = self.arena.alloc(self.expr_match(
desugared_span,
into_iter_expr,
hir_vec![iter_arm],
arena_vec![self; iter_arm],
hir::MatchSource::ForLoopDesugar,
));
@ -1121,7 +1179,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let sub_expr = self.lower_expr(sub_expr);
let path = &[sym::ops, sym::Try, sym::into_result];
P(self.expr_call_std_path(unstable_span, path, hir_vec![sub_expr]))
self.arena.alloc(self.expr_call_std_path(
unstable_span,
path,
arena_vec![self; sub_expr],
))
};
// `#[allow(unreachable_code)]`
@ -1141,7 +1203,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let ok_arm = {
let val_ident = Ident::with_dummy_span(sym::val);
let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
let val_expr = P(self.expr_ident_with_attrs(
let val_expr = self.arena.alloc(self.expr_ident_with_attrs(
span,
val_ident,
val_pat_nid,
@ -1159,7 +1221,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let from_expr = {
let from_path = &[sym::convert, sym::From, sym::from];
let err_expr = self.expr_ident(try_span, err_ident, err_local_nid);
self.expr_call_std_path(try_span, from_path, hir_vec![err_expr])
self.arena.alloc(self.expr_call_std_path(
try_span,
from_path,
arena_vec![self; err_expr],
))
};
let from_err_expr =
self.wrap_in_try_constructor(sym::from_error, unstable_span, from_expr, try_span);
@ -1167,7 +1233,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let catch_scope = self.catch_scopes.last().map(|x| *x);
let ret_expr = if let Some(catch_node) = catch_scope {
let target_id = Ok(self.lower_node_id(catch_node));
P(self.expr(
self.arena.alloc(self.expr(
try_span,
hir::ExprKind::Break(
hir::Destination { label: None, target_id },
@ -1176,14 +1242,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
thin_attrs,
))
} else {
P(self.expr(try_span, hir::ExprKind::Ret(Some(from_err_expr)), thin_attrs))
self.arena.alloc(self.expr(
try_span,
hir::ExprKind::Ret(Some(from_err_expr)),
thin_attrs,
))
};
let err_pat = self.pat_err(try_span, err_local);
self.arm(err_pat, ret_expr)
};
hir::ExprKind::Match(scrutinee, hir_vec![err_arm, ok_arm], hir::MatchSource::TryDesugar)
hir::ExprKind::Match(
scrutinee,
arena_vec![self; err_arm, ok_arm],
hir::MatchSource::TryDesugar,
)
}
// =========================================================================
@ -1205,7 +1279,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn expr_drop_temps(
&mut self,
span: Span,
expr: P<hir::Expr<'hir>>,
expr: &'hir hir::Expr<'hir>,
attrs: AttrVec,
) -> hir::Expr<'hir> {
self.expr(span, hir::ExprKind::DropTemps(expr), attrs)
@ -1214,19 +1288,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn expr_match(
&mut self,
span: Span,
arg: P<hir::Expr<'hir>>,
arms: hir::HirVec<hir::Arm<'hir>>,
arg: &'hir hir::Expr<'hir>,
arms: &'hir [hir::Arm<'hir>],
source: hir::MatchSource,
) -> hir::Expr<'hir> {
self.expr(span, hir::ExprKind::Match(arg, arms, source), ThinVec::new())
}
fn expr_break(&mut self, span: Span, attrs: AttrVec) -> P<hir::Expr<'hir>> {
fn expr_break(&mut self, span: Span, attrs: AttrVec) -> &'hir hir::Expr<'hir> {
let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None);
P(self.expr(span, expr_break, attrs))
self.arena.alloc(self.expr(span, expr_break, attrs))
}
fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr<'_>>) -> hir::Expr<'_> {
fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
self.expr(
span,
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e),
@ -1235,18 +1309,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
fn expr_unit(&mut self, sp: Span) -> hir::Expr<'hir> {
self.expr_tuple(sp, hir_vec![])
self.expr_tuple(sp, &[])
}
fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<hir::Expr<'hir>>) -> hir::Expr<'hir> {
fn expr_tuple(&mut self, sp: Span, exprs: &'hir [hir::Expr<'hir>]) -> hir::Expr<'hir> {
self.expr(sp, hir::ExprKind::Tup(exprs), ThinVec::new())
}
fn expr_call(
&mut self,
span: Span,
e: P<hir::Expr<'hir>>,
args: hir::HirVec<hir::Expr<'hir>>,
e: &'hir hir::Expr<'hir>,
args: &'hir [hir::Expr<'hir>],
) -> hir::Expr<'hir> {
self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new())
}
@ -1256,9 +1330,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
&mut self,
span: Span,
path_components: &[Symbol],
args: hir::HirVec<hir::Expr<'hir>>,
args: &'hir [hir::Expr<'hir>],
) -> hir::Expr<'hir> {
let path = P(self.expr_std_path(span, path_components, None, ThinVec::new()));
let path =
self.arena.alloc(self.expr_std_path(span, path_components, None, ThinVec::new()));
self.expr_call(span, path, args)
}
@ -1277,13 +1352,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
span: Span,
ty_path_components: &[Symbol],
assoc_fn_name: &str,
args: hir::HirVec<hir::Expr<'hir>>,
args: &'hir [hir::Expr<'hir>],
) -> hir::ExprKind<'hir> {
let ty_path = P(self.std_path(span, ty_path_components, None, false));
let ty = P(self.ty_path(ty_path_id, span, hir::QPath::Resolved(None, ty_path)));
let fn_seg = P(hir::PathSegment::from_ident(Ident::from_str(assoc_fn_name)));
let fn_path = hir::QPath::TypeRelative(ty, fn_seg);
let fn_expr = P(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
let fn_expr =
self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
hir::ExprKind::Call(fn_expr, args)
}
@ -1326,14 +1402,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.expr(span, expr_path, attrs)
}
fn expr_unsafe(&mut self, expr: P<hir::Expr<'hir>>) -> hir::Expr<'hir> {
fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
let hir_id = self.next_id();
let span = expr.span;
self.expr(
span,
hir::ExprKind::Block(
P(hir::Block {
stmts: hir_vec![],
self.arena.alloc(hir::Block {
stmts: &[],
expr: Some(expr),
hir_id,
rules: hir::UnsafeBlock(hir::CompilerGenerated),
@ -1347,11 +1423,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
fn expr_block_empty(&mut self, span: Span) -> hir::Expr<'hir> {
let blk = self.block_all(span, hir_vec![], None);
self.expr_block(P(blk), ThinVec::new())
let blk = self.block_all(span, &[], None);
self.expr_block(self.arena.alloc(blk), ThinVec::new())
}
pub(super) fn expr_block(&mut self, b: P<hir::Block<'hir>>, attrs: AttrVec) -> hir::Expr<'hir> {
pub(super) fn expr_block(
&mut self,
b: &'hir hir::Block<'hir>,
attrs: AttrVec,
) -> hir::Expr<'hir> {
self.expr(b.span, hir::ExprKind::Block(b, None), attrs)
}
@ -1364,14 +1444,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::Expr { hir_id: self.next_id(), kind, span, attrs }
}
fn field(&mut self, ident: Ident, expr: P<hir::Expr<'hir>>, span: Span) -> hir::Field<'hir> {
fn field(&mut self, ident: Ident, expr: &'hir hir::Expr<'hir>, span: Span) -> hir::Field<'hir> {
hir::Field { hir_id: self.next_id(), ident, span, expr, is_shorthand: false }
}
fn arm(&mut self, pat: P<hir::Pat<'hir>>, expr: P<hir::Expr<'hir>>) -> hir::Arm<'hir> {
fn arm(&mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>) -> hir::Arm<'hir> {
hir::Arm {
hir_id: self.next_id(),
attrs: hir_vec![],
attrs: &[],
pat,
guard: None,
span: expr.span,

View File

@ -1005,7 +1005,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> {
hir::Param {
attrs: self.lower_attrs(&param.attrs),
attrs: self.lower_attrs_arena(&param.attrs),
hir_id: self.lower_node_id(param.id),
pat: self.lower_pat(&param.pat),
span: param.span,
@ -1066,8 +1066,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
};
self.lower_body(|this| {
let mut parameters: Vec<hir::Param<'hir>> = Vec::new();
let mut statements: Vec<hir::Stmt<'hir>> = Vec::new();
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
// Async function parameters are lowered into the closure body so that they are
// captured and so that the drop order matches the equivalent non-async functions.
@ -1145,7 +1145,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let stmt = this.stmt_let_pat(
stmt_attrs,
desugared_span,
Some(P(expr)),
Some(this.arena.alloc(expr)),
parameter.pat,
hir::LocalSource::AsyncFn,
);
@ -1175,7 +1175,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let move_stmt = this.stmt_let_pat(
AttrVec::new(),
desugared_span,
Some(P(move_expr)),
Some(this.arena.alloc(move_expr)),
move_pat,
hir::LocalSource::AsyncFn,
);
@ -1186,7 +1186,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let pattern_stmt = this.stmt_let_pat(
stmt_attrs,
desugared_span,
Some(P(pattern_expr)),
Some(this.arena.alloc(pattern_expr)),
parameter.pat,
hir::LocalSource::AsyncFn,
);
@ -1212,8 +1212,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Transform into `drop-temps { <user-body> }`, an expression:
let desugared_span =
this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
let user_body =
this.expr_drop_temps(desugared_span, P(user_body), AttrVec::new());
let user_body = this.expr_drop_temps(
desugared_span,
this.arena.alloc(user_body),
AttrVec::new(),
);
// As noted above, create the final block like
//
@ -1224,9 +1227,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
// drop-temps { <user-body> }
// }
// ```
let body =
this.block_all(desugared_span, statements.into(), Some(P(user_body)));
this.expr_block(P(body), AttrVec::new())
let body = this.block_all(
desugared_span,
this.arena.alloc_from_iter(statements),
Some(this.arena.alloc(user_body)),
);
this.expr_block(this.arena.alloc(body), AttrVec::new())
},
);

View File

@ -50,6 +50,15 @@ macro_rules! hir_vec {
);
}
macro_rules! arena_vec {
() => (
&[]
);
($this:expr; $($x:expr),*) => (
$this.arena.alloc_from_iter(vec![$($x),*])
);
}
pub mod check_attr;
pub mod def;
pub mod def_id;