1
Fork 0

Remove token::Lit from ast::MetaItemLit.

`token::Lit` contains a `kind` field that indicates what kind of literal
it is. `ast::MetaItemLit` currently wraps a `token::Lit` but also has
its own `kind` field. This means that `ast::MetaItemLit` encodes the
literal kind in two different ways.

This commit changes `ast::MetaItemLit` so it no longer wraps
`token::Lit`. It now contains the `symbol` and `suffix` fields from
`token::Lit`, but not the `kind` field, eliminating the redundancy.
This commit is contained in:
Nicholas Nethercote 2022-11-29 13:36:00 +11:00
parent a7f35c42d4
commit 2fd364acff
9 changed files with 56 additions and 23 deletions

View file

@ -1733,8 +1733,10 @@ pub enum StrStyle {
/// A literal in a meta item. /// A literal in a meta item.
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct MetaItemLit { pub struct MetaItemLit {
/// The original literal token as written in source code. /// The original literal as written in the source code.
pub token_lit: token::Lit, pub symbol: Symbol,
/// The original suffix as written in the source code.
pub suffix: Option<Symbol>,
/// The "semantic" representation of the literal lowered from the original tokens. /// The "semantic" representation of the literal lowered from the original tokens.
/// Strings are unescaped, hexadecimal forms are eliminated, etc. /// Strings are unescaped, hexadecimal forms are eliminated, etc.
pub kind: LitKind, pub kind: LitKind,
@ -3103,7 +3105,7 @@ mod size_asserts {
static_assert_size!(ItemKind, 112); static_assert_size!(ItemKind, 112);
static_assert_size!(LitKind, 24); static_assert_size!(LitKind, 24);
static_assert_size!(Local, 72); static_assert_size!(Local, 72);
static_assert_size!(MetaItemLit, 48); static_assert_size!(MetaItemLit, 40);
static_assert_size!(Param, 40); static_assert_size!(Param, 40);
static_assert_size!(Pat, 88); static_assert_size!(Pat, 88);
static_assert_size!(Path, 24); static_assert_size!(Path, 24);

View file

@ -328,7 +328,9 @@ pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> Meta
} }
pub fn mk_name_value_item(ident: Ident, kind: LitKind, lit_span: Span) -> MetaItem { pub fn mk_name_value_item(ident: Ident, kind: LitKind, lit_span: Span) -> MetaItem {
let lit = MetaItemLit { token_lit: kind.synthesize_token_lit(), kind, span: lit_span }; let token_lit = kind.synthesize_token_lit();
let lit =
MetaItemLit { symbol: token_lit.symbol, suffix: token_lit.suffix, kind, span: lit_span };
let span = ident.span.to(lit_span); let span = ident.span.to(lit_span);
MetaItem { path: Path::from_ident(ident), kind: MetaItemKind::NameValue(lit), span } MetaItem { path: Path::from_ident(ident), kind: MetaItemKind::NameValue(lit), span }
} }

View file

@ -202,9 +202,32 @@ impl LitKind {
} }
impl MetaItemLit { impl MetaItemLit {
/// Converts token literal into a meta item literal. /// Converts a token literal into a meta item literal.
pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result<MetaItemLit, LitError> { pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result<MetaItemLit, LitError> {
Ok(MetaItemLit { token_lit, kind: LitKind::from_token_lit(token_lit)?, span }) Ok(MetaItemLit {
symbol: token_lit.symbol,
suffix: token_lit.suffix,
kind: LitKind::from_token_lit(token_lit)?,
span,
})
}
/// Cheaply converts a meta item literal into a token literal.
pub fn as_token_lit(&self) -> token::Lit {
let kind = match self.kind {
LitKind::Bool(_) => token::Bool,
LitKind::Str(_, ast::StrStyle::Cooked) => token::Str,
LitKind::Str(_, ast::StrStyle::Raw(n)) => token::StrRaw(n),
LitKind::ByteStr(_, ast::StrStyle::Cooked) => token::ByteStr,
LitKind::ByteStr(_, ast::StrStyle::Raw(n)) => token::ByteStrRaw(n),
LitKind::Byte(_) => token::Byte,
LitKind::Char(_) => token::Char,
LitKind::Int(..) => token::Integer,
LitKind::Float(..) => token::Float,
LitKind::Err => token::Err,
};
token::Lit::new(kind, self.symbol, self.suffix)
} }
/// Converts an arbitrary token into meta item literal. /// Converts an arbitrary token into meta item literal.

View file

@ -954,7 +954,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
lit lit
} else { } else {
MetaItemLit { MetaItemLit {
token_lit: token::Lit::new(token::LitKind::Err, kw::Empty, None), symbol: kw::Empty,
suffix: None,
kind: LitKind::Err, kind: LitKind::Err,
span: DUMMY_SP, span: DUMMY_SP,
} }

View file

@ -376,7 +376,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
} }
fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) { fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) {
self.print_token_literal(lit.token_lit, lit.span) self.print_token_literal(lit.as_token_lit(), lit.span)
} }
fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) { fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) {

View file

@ -1,7 +1,7 @@
use crate::cfg_eval::cfg_eval; use crate::cfg_eval::cfg_eval;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::{token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
use rustc_errors::{struct_span_err, Applicability}; use rustc_errors::{struct_span_err, Applicability};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
use rustc_feature::AttributeTemplate; use rustc_feature::AttributeTemplate;
@ -130,9 +130,11 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
} }
fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) { fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) {
let help_msg = match lit.token_lit.kind { let help_msg = match lit.kind {
token::Str if rustc_lexer::is_ident(lit.token_lit.symbol.as_str()) => { ast::LitKind::Str(_, ast::StrStyle::Cooked)
format!("try using `#[derive({})]`", lit.token_lit.symbol) if rustc_lexer::is_ident(lit.symbol.as_str()) =>
{
format!("try using `#[derive({})]`", lit.symbol)
} }
_ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(), _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(),
}; };

View file

@ -1551,7 +1551,7 @@ impl<'a> Parser<'a> {
}) })
}); });
consume_colon = false; consume_colon = false;
Ok(self.mk_expr(lo, ExprKind::Lit(lit.token_lit))) Ok(self.mk_expr(lo, ExprKind::Lit(lit.as_token_lit())))
} else if !ate_colon } else if !ate_colon
&& (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt)) && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
{ {
@ -1654,7 +1654,8 @@ impl<'a> Parser<'a> {
} }
let name = lifetime.without_first_quote().name; let name = lifetime.without_first_quote().name;
ast::MetaItemLit { ast::MetaItemLit {
token_lit: token::Lit::new(token::LitKind::Char, name, None), symbol: name,
suffix: None,
kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')), kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')),
span: lifetime.span, span: lifetime.span,
} }
@ -1773,8 +1774,8 @@ impl<'a> Parser<'a> {
Some(lit) => match lit.kind { Some(lit) => match lit.kind {
ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit { ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit {
style, style,
symbol: lit.token_lit.symbol, symbol: lit.symbol,
suffix: lit.token_lit.suffix, suffix: lit.suffix,
span: lit.span, span: lit.span,
symbol_unescaped, symbol_unescaped,
}), }),
@ -1817,7 +1818,7 @@ impl<'a> Parser<'a> {
pub(super) fn parse_token_lit(&mut self) -> PResult<'a, (token::Lit, Span)> { pub(super) fn parse_token_lit(&mut self) -> PResult<'a, (token::Lit, Span)> {
self.parse_opt_token_lit() self.parse_opt_token_lit()
.ok_or(()) .ok_or(())
.or_else(|()| self.handle_missing_lit().map(|lit| (lit.token_lit, lit.span))) .or_else(|()| self.handle_missing_lit().map(|lit| (lit.as_token_lit(), lit.span)))
} }
pub(super) fn parse_meta_item_lit(&mut self) -> PResult<'a, MetaItemLit> { pub(super) fn parse_meta_item_lit(&mut self) -> PResult<'a, MetaItemLit> {

View file

@ -420,7 +420,7 @@ impl<'a> Parser<'a> {
err.span_label(self_.token.span, format!("expected {}", expected)); err.span_label(self_.token.span, format!("expected {}", expected));
err err
}); });
PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit.token_lit))) PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit.as_token_lit())))
} else { } else {
// Try to parse everything else as literal with optional minus // Try to parse everything else as literal with optional minus
match self.parse_literal_maybe_minus() { match self.parse_literal_maybe_minus() {

View file

@ -260,7 +260,9 @@ impl Rewrite for ast::NestedMetaItem {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
match self { match self {
ast::NestedMetaItem::MetaItem(ref meta_item) => meta_item.rewrite(context, shape), ast::NestedMetaItem::MetaItem(ref meta_item) => meta_item.rewrite(context, shape),
ast::NestedMetaItem::Lit(ref l) => rewrite_literal(context, l.token_lit, l.span, shape), ast::NestedMetaItem::Lit(ref l) => {
rewrite_literal(context, l.as_token_lit(), l.span, shape)
}
} }
} }
} }
@ -308,18 +310,18 @@ impl Rewrite for ast::MetaItem {
}), }),
)? )?
} }
ast::MetaItemKind::NameValue(ref literal) => { ast::MetaItemKind::NameValue(ref lit) => {
let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?; let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?;
// 3 = ` = ` // 3 = ` = `
let lit_shape = shape.shrink_left(path.len() + 3)?; let lit_shape = shape.shrink_left(path.len() + 3)?;
// `rewrite_literal` returns `None` when `literal` exceeds max // `rewrite_literal` returns `None` when `lit` exceeds max
// width. Since a literal is basically unformattable unless it // width. Since a literal is basically unformattable unless it
// is a string literal (and only if `format_strings` is set), // is a string literal (and only if `format_strings` is set),
// we might be better off ignoring the fact that the attribute // we might be better off ignoring the fact that the attribute
// is longer than the max width and continue on formatting. // is longer than the max width and continue on formatting.
// See #2479 for example. // See #2479 for example.
let value = rewrite_literal(context, literal.token_lit, literal.span, lit_shape) let value = rewrite_literal(context, lit.as_token_lit(), lit.span, lit_shape)
.unwrap_or_else(|| context.snippet(literal.span).to_owned()); .unwrap_or_else(|| context.snippet(lit.span).to_owned());
format!("{} = {}", path, value) format!("{} = {}", path, value)
} }
}) })