ast: Reduce size of `ExprKind` by boxing fields of `ExprKind::Struct`

This commit is contained in:
Vadim Petrochenkov 2021-03-16 03:15:53 +03:00
parent b25d3ba781
commit d1522b39dd
12 changed files with 48 additions and 28 deletions

View File

@ -1074,7 +1074,7 @@ pub struct Expr {
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Expr, 120); rustc_data_structures::static_assert_size!(Expr, 104);
impl Expr { impl Expr {
/// Returns `true` if this expression would be valid somewhere that expects a value; /// Returns `true` if this expression would be valid somewhere that expects a value;
@ -1244,6 +1244,13 @@ pub enum StructRest {
None, None,
} }
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct StructExpr {
pub path: Path,
pub fields: Vec<ExprField>,
pub rest: StructRest,
}
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
pub enum ExprKind { pub enum ExprKind {
/// A `box x` expression. /// A `box x` expression.
@ -1369,7 +1376,7 @@ pub enum ExprKind {
/// A struct literal expression. /// A struct literal expression.
/// ///
/// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. rest}`. /// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. rest}`.
Struct(Path, Vec<ExprField>, StructRest), Struct(P<StructExpr>),
/// An array literal constructed from one repeated element. /// An array literal constructed from one repeated element.
/// ///

View File

@ -1286,10 +1286,11 @@ pub fn noop_visit_expr<T: MutVisitor>(
visit_vec(inputs, |(_c, expr)| vis.visit_expr(expr)); visit_vec(inputs, |(_c, expr)| vis.visit_expr(expr));
} }
ExprKind::MacCall(mac) => vis.visit_mac_call(mac), ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
ExprKind::Struct(path, fields, expr) => { ExprKind::Struct(se) => {
let StructExpr { path, fields, rest } = se.deref_mut();
vis.visit_path(path); vis.visit_path(path);
fields.flat_map_in_place(|field| vis.flat_map_expr_field(field)); fields.flat_map_in_place(|field| vis.flat_map_expr_field(field));
match expr { match rest {
StructRest::Base(expr) => vis.visit_expr(expr), StructRest::Base(expr) => vis.visit_expr(expr),
StructRest::Rest(_span) => {} StructRest::Rest(_span) => {}
StructRest::None => {} StructRest::None => {}

View File

@ -721,10 +721,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr(element); visitor.visit_expr(element);
visitor.visit_anon_const(count) visitor.visit_anon_const(count)
} }
ExprKind::Struct(ref path, ref fields, ref optional_base) => { ExprKind::Struct(ref se) => {
visitor.visit_path(path, expression.id); visitor.visit_path(&se.path, expression.id);
walk_list!(visitor, visit_expr_field, fields); walk_list!(visitor, visit_expr_field, &se.fields);
match optional_base { match &se.rest {
StructRest::Base(expr) => visitor.visit_expr(expr), StructRest::Base(expr) => visitor.visit_expr(expr),
StructRest::Rest(_span) => {} StructRest::Rest(_span) => {}
StructRest::None => {} StructRest::None => {}

View File

@ -224,8 +224,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
ExprKind::InlineAsm(ref asm) => self.lower_expr_asm(e.span, asm), ExprKind::InlineAsm(ref asm) => self.lower_expr_asm(e.span, asm),
ExprKind::LlvmInlineAsm(ref asm) => self.lower_expr_llvm_asm(asm), ExprKind::LlvmInlineAsm(ref asm) => self.lower_expr_llvm_asm(asm),
ExprKind::Struct(ref path, ref fields, ref rest) => { ExprKind::Struct(ref se) => {
let rest = match rest { let rest = match &se.rest {
StructRest::Base(e) => Some(self.lower_expr(e)), StructRest::Base(e) => Some(self.lower_expr(e)),
StructRest::Rest(sp) => { StructRest::Rest(sp) => {
self.sess self.sess
@ -240,11 +240,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.arena.alloc(self.lower_qpath( self.arena.alloc(self.lower_qpath(
e.id, e.id,
&None, &None,
path, &se.path,
ParamMode::Optional, ParamMode::Optional,
ImplTraitContext::disallowed(), ImplTraitContext::disallowed(),
)), )),
self.arena.alloc_from_iter(fields.iter().map(|x| self.lower_expr_field(x))), self.arena
.alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))),
rest, rest,
) )
} }
@ -1110,8 +1111,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
} }
// Structs. // Structs.
ExprKind::Struct(path, fields, rest) => { ExprKind::Struct(se) => {
let field_pats = self.arena.alloc_from_iter(fields.iter().map(|f| { let field_pats = self.arena.alloc_from_iter(se.fields.iter().map(|f| {
let pat = self.destructure_assign(&f.expr, eq_sign_span, assignments); let pat = self.destructure_assign(&f.expr, eq_sign_span, assignments);
hir::PatField { hir::PatField {
hir_id: self.next_id(), hir_id: self.next_id(),
@ -1124,11 +1125,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let qpath = self.lower_qpath( let qpath = self.lower_qpath(
lhs.id, lhs.id,
&None, &None,
path, &se.path,
ParamMode::Optional, ParamMode::Optional,
ImplTraitContext::disallowed(), ImplTraitContext::disallowed(),
); );
let fields_omitted = match rest { let fields_omitted = match &se.rest {
StructRest::Base(e) => { StructRest::Base(e) => {
self.sess self.sess
.struct_span_err( .struct_span_err(

View File

@ -1873,8 +1873,8 @@ impl<'a> State<'a> {
ast::ExprKind::Repeat(ref element, ref count) => { ast::ExprKind::Repeat(ref element, ref count) => {
self.print_expr_repeat(element, count, attrs); self.print_expr_repeat(element, count, attrs);
} }
ast::ExprKind::Struct(ref path, ref fields, ref rest) => { ast::ExprKind::Struct(ref se) => {
self.print_expr_struct(path, &fields[..], rest, attrs); self.print_expr_struct(&se.path, &se.fields, &se.rest, attrs);
} }
ast::ExprKind::Tup(ref exprs) => { ast::ExprKind::Tup(ref exprs) => {
self.print_expr_tup(&exprs[..], attrs); self.print_expr_tup(&exprs[..], attrs);

View File

@ -284,7 +284,10 @@ impl<'a> ExtCtxt<'a> {
path: ast::Path, path: ast::Path,
fields: Vec<ast::ExprField>, fields: Vec<ast::ExprField>,
) -> P<ast::Expr> { ) -> P<ast::Expr> {
self.expr(span, ast::ExprKind::Struct(path, fields, ast::StructRest::None)) self.expr(
span,
ast::ExprKind::Struct(P(ast::StructExpr { path, fields, rest: ast::StructRest::None })),
)
} }
pub fn expr_struct_ident( pub fn expr_struct_ident(
&self, &self,

View File

@ -2373,7 +2373,11 @@ impl<'a> Parser<'a> {
let span = pth.span.to(self.token.span); let span = pth.span.to(self.token.span);
self.expect(&token::CloseDelim(token::Brace))?; self.expect(&token::CloseDelim(token::Brace))?;
let expr = if recover_async { ExprKind::Err } else { ExprKind::Struct(pth, fields, base) }; let expr = if recover_async {
ExprKind::Err
} else {
ExprKind::Struct(P(ast::StructExpr { path: pth, fields, rest: base }))
};
Ok(self.mk_expr(span, expr, attrs)) Ok(self.mk_expr(span, expr, attrs))
} }

View File

@ -2251,8 +2251,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
visit::walk_expr(self, expr); visit::walk_expr(self, expr);
} }
ExprKind::Struct(ref path, ..) => { ExprKind::Struct(ref se) => {
self.smart_resolve_path(expr.id, None, path, PathSource::Struct); self.smart_resolve_path(expr.id, None, &se.path, PathSource::Struct);
visit::walk_expr(self, expr); visit::walk_expr(self, expr);
} }

View File

@ -155,7 +155,9 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
}, },
17 => { 17 => {
let path = Path::from_ident(Ident::from_str("S")); let path = Path::from_ident(Ident::from_str("S"));
g(ExprKind::Struct(path, vec![], StructRest::Base(make_x()))); g(ExprKind::Struct(P(StructExpr {
path, fields: vec![], rest: StructRest::Base(make_x())
})));
}, },
18 => { 18 => {
iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e))); iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e)));

View File

@ -58,8 +58,8 @@ impl EarlyLintPass for RedundantFieldNames {
if in_external_macro(cx.sess, expr.span) { if in_external_macro(cx.sess, expr.span) {
return; return;
} }
if let ExprKind::Struct(_, ref fields, _) = expr.kind { if let ExprKind::Struct(ref se) = expr.kind {
for field in fields { for field in &se.fields {
if field.is_shorthand { if field.is_shorthand {
continue; continue;
} }

View File

@ -564,7 +564,7 @@ fn ident_difference_expr_with_base_location(
| (Try(_), Try(_)) | (Try(_), Try(_))
| (Paren(_), Paren(_)) | (Paren(_), Paren(_))
| (Repeat(_, _), Repeat(_, _)) | (Repeat(_, _), Repeat(_, _))
| (Struct(_, _, _), Struct(_, _, _)) | (Struct(_), Struct(_))
| (MacCall(_), MacCall(_)) | (MacCall(_), MacCall(_))
| (LlvmInlineAsm(_), LlvmInlineAsm(_)) | (LlvmInlineAsm(_), LlvmInlineAsm(_))
| (InlineAsm(_), InlineAsm(_)) | (InlineAsm(_), InlineAsm(_))

View File

@ -168,8 +168,10 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
(AddrOf(lbk, lm, le), AddrOf(rbk, rm, re)) => lbk == rbk && lm == rm && eq_expr(le, re), (AddrOf(lbk, lm, le), AddrOf(rbk, rm, re)) => lbk == rbk && lm == rm && eq_expr(le, re),
(Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp), (Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp),
(MacCall(l), MacCall(r)) => eq_mac_call(l, r), (MacCall(l), MacCall(r)) => eq_mac_call(l, r),
(Struct(lp, lfs, lb), Struct(rp, rfs, rb)) => { (Struct(lse), Struct(rse)) => {
eq_path(lp, rp) && eq_struct_rest(lb, rb) && unordered_over(lfs, rfs, |l, r| eq_field(l, r)) eq_path(&lse.path, &rse.path) &&
eq_struct_rest(&lse.rest, &rse.rest) &&
unordered_over(&lse.fields, &rse.fields, |l, r| eq_field(l, r))
}, },
_ => false, _ => false,
} }