Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove ast::Lit::kind #101885

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 2 additions & 21 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1691,10 +1691,6 @@ pub enum StrStyle {
pub struct Lit {
/// The original literal token as written in source code.
pub token_lit: token::Lit,
/// The "semantic" representation of the literal lowered from the original tokens.
/// Strings are unescaped, hexadecimal forms are eliminated, etc.
/// FIXME: Remove this and only create the semantic representation during lowering to HIR.
pub kind: LitKind,
pub span: Span,
}

Expand All @@ -1717,11 +1713,7 @@ impl StrLit {
StrStyle::Cooked => token::Str,
StrStyle::Raw(n) => token::StrRaw(n),
};
Lit {
token_lit: token::Lit::new(token_kind, self.symbol, self.suffix),
span: self.span,
kind: LitKind::Str(self.symbol_unescaped, self.style),
}
Lit { token_lit: token::Lit::new(token_kind, self.symbol, self.suffix), span: self.span }
}
}

Expand Down Expand Up @@ -1778,22 +1770,11 @@ impl LitKind {
matches!(self, LitKind::Str(..))
}

/// Returns `true` if this literal is byte literal string.
pub fn is_bytestr(&self) -> bool {
matches!(self, LitKind::ByteStr(_))
}

/// Returns `true` if this is a numeric literal.
pub fn is_numeric(&self) -> bool {
matches!(self, LitKind::Int(..) | LitKind::Float(..))
}

/// Returns `true` if this literal has no suffix.
/// Note: this will return true for literals with prefixes such as raw strings and byte strings.
pub fn is_unsuffixed(&self) -> bool {
!self.is_suffixed()
}

/// Returns `true` if this literal has a suffix.
pub fn is_suffixed(&self) -> bool {
match *self {
Expand Down Expand Up @@ -3056,7 +3037,7 @@ mod size_asserts {
static_assert_size!(Impl, 200);
static_assert_size!(Item, 184);
static_assert_size!(ItemKind, 112);
static_assert_size!(Lit, 48);
static_assert_size!(Lit, 20);
static_assert_size!(LitKind, 24);
static_assert_size!(Local, 72);
static_assert_size!(Param, 40);
Expand Down
12 changes: 5 additions & 7 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> Meta
}

pub fn mk_name_value_item(ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem {
let lit = Lit::from_lit_kind(lit_kind, lit_span);
let lit = Lit { token_lit: lit_kind.to_token_lit(), span: lit_span };
let span = ident.span.to(lit_span);
MetaItem { path: Path::from_ident(ident), span, kind: MetaItemKind::NameValue(lit) }
}
Expand Down Expand Up @@ -519,8 +519,8 @@ impl MetaItem {
impl MetaItemKind {
pub fn value_str(&self) -> Option<Symbol> {
match self {
MetaItemKind::NameValue(ref v) => match v.kind {
LitKind::Str(ref s, _) => Some(*s),
MetaItemKind::NameValue(ref v) => match LitKind::from_token_lit(v.token_lit) {
Ok(LitKind::Str(ref s, _)) => Some(*s),
_ => None,
},
_ => None,
Expand Down Expand Up @@ -605,7 +605,7 @@ impl MetaItemKind {
MetaItemKind::name_value_from_tokens(&mut inner_tokens.into_trees())
}
Some(TokenTree::Token(token, _)) => {
Lit::from_token(&token).ok().map(MetaItemKind::NameValue)
Lit::from_token(&token).map(MetaItemKind::NameValue)
}
_ => None,
}
Expand Down Expand Up @@ -667,9 +667,7 @@ impl NestedMetaItem {
I: Iterator<Item = TokenTree>,
{
match tokens.peek() {
Some(TokenTree::Token(token, _))
if let Ok(lit) = Lit::from_token(token) =>
{
Some(TokenTree::Token(token, _)) if let Some(lit) = Lit::from_token(token) => {
tokens.next();
return Some(NestedMetaItem::Literal(lit));
}
Expand Down
22 changes: 22 additions & 0 deletions compiler/rustc_ast/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,28 @@ pub struct Lit {
pub suffix: Option<Symbol>,
}

impl Lit {
pub fn is_bool_true(&self) -> bool {
matches!(self.kind, LitKind::Bool) && self.symbol == kw::True
}

/// Returns `true` if this literal is a string.
pub fn is_str(&self) -> bool {
matches!(self.kind, LitKind::Str | LitKind::StrRaw(_))
}

/// Returns `true` if this literal is byte literal string.
pub fn is_bytestr(&self) -> bool {
matches!(self.kind, LitKind::ByteStr | LitKind::ByteStrRaw(_))
}

/// Returns `true` if this literal has no suffix.
/// Note: this will return true for literals with prefixes such as raw strings and byte strings.
pub fn is_unsuffixed(&self) -> bool {
self.suffix.is_none()
}
}

impl fmt::Display for Lit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Lit { kind, symbol, suffix } = *self;
Expand Down
37 changes: 14 additions & 23 deletions compiler/rustc_ast/src/util/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ use crate::token::{self, Token};
use rustc_lexer::unescape::{unescape_byte, unescape_char};
use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;

use std::ascii;

pub enum LitError {
NotLiteral,
LexerError,
InvalidSuffix,
InvalidIntSuffix,
Expand Down Expand Up @@ -149,7 +147,7 @@ impl LitKind {
})
}

/// Attempts to recover a token from semantic literal.
/// Creates a token literal from a semantic literal kind.
/// This function is used when the original token doesn't exist (e.g. the literal is created
/// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
pub fn to_token_lit(&self) -> token::Lit {
Expand Down Expand Up @@ -203,39 +201,30 @@ impl LitKind {
}

impl Lit {
/// Converts literal token into an AST literal.
pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result<Lit, LitError> {
Ok(Lit { token_lit, kind: LitKind::from_token_lit(token_lit)?, span })
}

/// Converts arbitrary token into an AST literal.
/// Converts an arbitrary token into an AST literal. Returns `None` if the
/// token is not a literal. The literal may be invalid in some fashion
/// (e.g. invalid suffix, too-large int, etc.); this will be caught during
/// lowering to HIR.
///
/// Keep this in sync with `Token::can_begin_literal_or_bool` excluding unary negation.
pub fn from_token(token: &Token) -> Result<Lit, LitError> {
let lit = match token.uninterpolate().kind {
pub fn from_token(token: &Token) -> Option<Lit> {
let token_lit = match token.uninterpolate().kind {
token::Ident(name, false) if name.is_bool_lit() => {
token::Lit::new(token::Bool, name, None)
}
token::Literal(lit) => lit,
token::Literal(token_lit) => token_lit,
token::Interpolated(ref nt) => {
if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt
&& let ast::ExprKind::Lit(lit) = &expr.kind
{
return Ok(lit.clone());
return Some(lit.clone());
}
return Err(LitError::NotLiteral);
return None;
}
_ => return Err(LitError::NotLiteral),
_ => return None,
};

Lit::from_token_lit(lit, token.span)
}

/// Attempts to recover an AST literal from semantic literal.
/// This function is used when the original token doesn't exist (e.g. the literal is created
/// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
pub fn from_lit_kind(kind: LitKind, span: Span) -> Lit {
Lit { token_lit: kind.to_token_lit(), kind, span }
Some(Lit { token_lit, span: token.span })
}

/// Losslessly convert an AST literal into a token.
Expand Down Expand Up @@ -281,11 +270,13 @@ fn filtered_float_lit(
})
}

#[inline]
fn float_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitError> {
debug!("float_lit: {:?}, {:?}", symbol, suffix);
filtered_float_lit(strip_underscores(symbol), suffix, 10)
}

#[inline]
fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitError> {
debug!("integer_lit: {:?}, {:?}", symbol, suffix);
let symbol = strip_underscores(symbol);
Expand Down
55 changes: 55 additions & 0 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,61 @@ use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic, Diagnost
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
use rustc_span::{symbol::Ident, Span, Symbol};

#[derive(SessionDiagnostic)]
#[diag(parser::invalid_int_literal_width)]
#[help]
pub(crate) struct InvalidIntLiteralWidth {
#[primary_span]
pub span: Span,
pub width: String,
}

#[derive(SessionDiagnostic)]
#[diag(parser::invalid_num_literal_base_prefix)]
#[note]
pub(crate) struct InvalidNumLiteralBasePrefix {
#[primary_span]
#[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
pub span: Span,
pub fixed: String,
}

#[derive(SessionDiagnostic)]
#[diag(parser::invalid_num_literal_suffix)]
#[help]
pub(crate) struct InvalidNumLiteralSuffix {
#[primary_span]
#[label]
pub span: Span,
pub suffix: String,
}

#[derive(SessionDiagnostic)]
#[diag(parser::invalid_float_literal_width)]
#[help]
pub(crate) struct InvalidFloatLiteralWidth {
#[primary_span]
pub span: Span,
pub width: String,
}

#[derive(SessionDiagnostic)]
#[diag(parser::invalid_float_literal_suffix)]
#[help]
pub(crate) struct InvalidFloatLiteralSuffix {
#[primary_span]
#[label]
pub span: Span,
pub suffix: String,
}

#[derive(SessionDiagnostic)]
#[diag(parser::int_literal_too_large)]
pub(crate) struct IntLiteralTooLarge {
#[primary_span]
pub span: Span,
}

#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::generic_type_with_parentheses, code = "E0214")]
pub struct GenericTypeWithParentheses {
Expand Down
Loading