From cc2e6ff646fb85f31cb230b56dc7c3080df334de Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 8 Feb 2019 10:01:39 +1100 Subject: [PATCH] Don't store a `Span` for `ExprKind::Lit` in the AST. Because it's always the same as the `Span` for the surrounding `Expr`. This reduces instruction counts on various benchmarks by up to 0.5%. --- src/librustc/hir/lowering.rs | 2 +- src/librustc/hir/mod.rs | 7 ++++++- src/librustc_passes/ast_validation.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/attr/mod.rs | 2 +- src/libsyntax/ext/base.rs | 5 +++-- src/libsyntax/ext/build.rs | 2 +- src/libsyntax/parse/parser.rs | 12 +++++++++--- src/libsyntax/print/pprust.rs | 12 ++++++++---- src/libsyntax_ext/concat.rs | 2 +- 10 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e3c913313adee..04a7dcfdbe689 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3852,7 +3852,7 @@ impl<'a> LoweringContext<'a> { let ohs = P(self.lower_expr(ohs)); hir::ExprKind::Unary(op, ohs) } - ExprKind::Lit(ref l) => hir::ExprKind::Lit((*l).clone()), + ExprKind::Lit(ref l) => hir::ExprKind::Lit(respan(e.span, (*l).clone())), ExprKind::Cast(ref expr, ref ty) => { let expr = P(self.lower_expr(expr)); hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::disallowed())) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 924b044da5fc3..cee5d0e97072b 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1450,7 +1450,12 @@ pub enum ExprKind { Binary(BinOp, P, P), /// A unary operation (For example: `!x`, `*x`) Unary(UnOp, P), - /// A literal (For example: `1`, `"foo"`) + /// A literal (For example: `1`, `"foo"`). Unlike the AST, HIR stores a + /// Span for the literal. This is because that Span may be different to the + /// Span of the enclosing expression, due to HIR not explicitly + /// representing parentheses around expressions. E.g. in the expression + /// "(1.0)", the expression's Span covers the whole thing, while the + /// literal's Span covers only "1.0". Lit(Lit), /// A cast (`foo as f64`) Cast(P, P), diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 3deb2ff8d8a0b..ee6d6815b2594 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -292,7 +292,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { " ); match val.node { - ExprKind::Lit(ref v) if v.node.is_numeric() => { + ExprKind::Lit(ref v) if v.is_numeric() => { err.span_suggestion( place.span.between(val.span), "if you meant to write a comparison against a negative value, add a \ diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 4f3f5631cc39c..698b84548372a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1076,7 +1076,7 @@ pub enum ExprKind { /// A unary operation (e.g., `!x`, `*x`). Unary(UnOp, P), /// A literal (e.g., `1`, `"foo"`). - Lit(Lit), + Lit(LitKind), /// A cast (e.g., `foo as f64`). Cast(P, P), Type(P, P), diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index c5a397e048078..cc6ed6ae978a1 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -678,7 +678,7 @@ impl LitKind { Token::Ident(ident, false) if ident.name == "false" => Some(LitKind::Bool(false)), Token::Interpolated(ref nt) => match nt.0 { token::NtExpr(ref v) | token::NtLiteral(ref v) => match v.node { - ExprKind::Lit(ref lit) => Some(lit.node.clone()), + ExprKind::Lit(ref lit) => Some(lit.clone()), _ => None, }, _ => None, diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index b53068f5bc2a4..6d515fd22a5ac 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -984,14 +984,15 @@ pub fn expr_to_spanned_string<'a>( err_msg: &str, ) -> Result, Option>> { // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation. + let lit_span = expr.span; expr.span = expr.span.apply_mark(cx.current_expansion.mark); // we want to be able to handle e.g., `concat!("foo", "bar")` cx.expander().visit_expr(&mut expr); Err(match expr.node { - ast::ExprKind::Lit(ref l) => match l.node { + ast::ExprKind::Lit(ref l) => match *l { ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))), - _ => Some(cx.struct_span_err(l.span, err_msg)) + _ => Some(cx.struct_span_err(lit_span, err_msg)) }, ast::ExprKind::Err => None, _ => Some(cx.struct_span_err(expr.span, err_msg)) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index a8eec1a74dd2b..ad03d6b832e80 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -682,7 +682,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_lit(&self, sp: Span, lit: ast::LitKind) -> P { - self.expr(sp, ast::ExprKind::Lit(respan(sp, lit))) + self.expr(sp, ast::ExprKind::Lit(lit)) } fn expr_usize(&self, span: Span, i: usize) -> P { self.expr_lit(span, ast::LitKind::Int(i as u128, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index bbd1770e9c634..f353bca65c409 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1996,7 +1996,7 @@ impl<'a> Parser<'a> { let out = match self.token { token::Interpolated(ref nt) => match nt.0 { token::NtExpr(ref v) | token::NtLiteral(ref v) => match v.node { - ExprKind::Lit(ref lit) => { lit.node.clone() } + ExprKind::Lit(ref lit) => { lit.clone() } _ => { return self.unexpected_last(&self.token); } }, _ => { return self.unexpected_last(&self.token); } @@ -2079,8 +2079,14 @@ impl<'a> Parser<'a> { let minus_present = self.eat(&token::BinOp(token::Minus)); let lo = self.span; let literal = self.parse_lit()?; - let hi = self.prev_span; - let expr = self.mk_expr(lo.to(hi), ExprKind::Lit(literal), ThinVec::new()); + // We don't store a span for the literal because it would be the same + // as the span for the expression. (Check this.) + debug_assert_eq!(literal.span, + { let hi = self.prev_span; + let expr_span = lo.to(hi); + expr_span + }); + let expr = self.mk_expr(literal.span, ExprKind::Lit(literal.node), ThinVec::new()); if minus_present { let minus_hi = self.prev_span; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 7cecf4b9af73f..5a8bd633925e3 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -598,11 +598,15 @@ pub trait PrintState<'a> { } fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> { - self.maybe_print_comment(lit.span.lo())?; - if let Some(ltrl) = self.next_lit(lit.span.lo()) { + self.print_literal_kind(&lit.node, lit.span) + } + + fn print_literal_kind(&mut self, lit: &ast::LitKind, span: syntax_pos::Span) -> io::Result<()> { + self.maybe_print_comment(span.lo())?; + if let Some(ltrl) = self.next_lit(span.lo()) { return self.writer().word(ltrl.lit.clone()); } - match lit.node { + match *lit { ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style), ast::LitKind::Err(st) => { let st = st.as_str().escape_debug(); @@ -2121,7 +2125,7 @@ impl<'a> State<'a> { self.print_expr_addr_of(m, expr)?; } ast::ExprKind::Lit(ref lit) => { - self.print_literal(lit)?; + self.print_literal_kind(lit, expr.span)?; } ast::ExprKind::Cast(ref expr, ref ty) => { let prec = AssocOp::As.precedence() as i8; diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index f148f8e003df3..4184104cb4001 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -21,7 +21,7 @@ pub fn expand_syntax_ext( let mut has_errors = false; for e in es { match e.node { - ast::ExprKind::Lit(ref lit) => match lit.node { + ast::ExprKind::Lit(ref lit) => match *lit { ast::LitKind::Str(ref s, _) | ast::LitKind::Err(ref s) | ast::LitKind::Float(ref s, _)