Use token::Lit
in ast::ExprKind::Lit
.
Instead of `ast::Lit`. Literal lowering now happens at two different times. Expression literals are lowered when HIR is crated. Attribute literals are lowered during parsing. This commit changes the language very slightly. Some programs that used to not compile now will compile. This is because some invalid literals that are removed by `cfg` or attribute macros will no longer trigger errors. See this comment for more details: https://github.com/rust-lang/rust/pull/102944#issuecomment-1277476773
This commit is contained in:
parent
01760265cb
commit
358a603f11
45 changed files with 701 additions and 581 deletions
|
@ -172,7 +172,11 @@ pub fn parse_asm_args<'a>(
|
|||
// If it can't possibly expand to a string, provide diagnostics here to include other
|
||||
// things it could have been.
|
||||
match template.kind {
|
||||
ast::ExprKind::Lit(ast::Lit { kind: ast::LitKind::Str(..), .. }) => {}
|
||||
ast::ExprKind::Lit(token_lit)
|
||||
if matches!(
|
||||
token_lit.kind,
|
||||
token::LitKind::Str | token::LitKind::StrRaw(_)
|
||||
) => {}
|
||||
ast::ExprKind::MacCall(..) => {}
|
||||
_ => {
|
||||
let errstr = if is_global_asm {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use rustc_ast as ast;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_expand::base::{self, DummyResult};
|
||||
use rustc_session::errors::report_lit_error;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
||||
use std::string::String;
|
||||
|
@ -18,28 +19,28 @@ pub fn expand_concat(
|
|||
let mut has_errors = false;
|
||||
for e in es {
|
||||
match e.kind {
|
||||
ast::ExprKind::Lit(ref lit) => match lit.kind {
|
||||
ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _) => {
|
||||
ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
|
||||
Ok(ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _)) => {
|
||||
accumulator.push_str(s.as_str());
|
||||
}
|
||||
ast::LitKind::Char(c) => {
|
||||
Ok(ast::LitKind::Char(c)) => {
|
||||
accumulator.push(c);
|
||||
}
|
||||
ast::LitKind::Int(
|
||||
i,
|
||||
ast::LitIntType::Unsigned(_)
|
||||
| ast::LitIntType::Signed(_)
|
||||
| ast::LitIntType::Unsuffixed,
|
||||
) => {
|
||||
Ok(ast::LitKind::Int(i, _)) => {
|
||||
accumulator.push_str(&i.to_string());
|
||||
}
|
||||
ast::LitKind::Bool(b) => {
|
||||
Ok(ast::LitKind::Bool(b)) => {
|
||||
accumulator.push_str(&b.to_string());
|
||||
}
|
||||
ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..) => {
|
||||
Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => {
|
||||
cx.span_err(e.span, "cannot concatenate a byte string literal");
|
||||
has_errors = true;
|
||||
}
|
||||
ast::LitKind::Err => {
|
||||
Ok(ast::LitKind::Err) => {
|
||||
has_errors = true;
|
||||
}
|
||||
Err(err) => {
|
||||
report_lit_error(&cx.sess.parse_sess, err, token_lit, e.span);
|
||||
has_errors = true;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -2,18 +2,21 @@ use rustc_ast as ast;
|
|||
use rustc_ast::{ptr::P, tokenstream::TokenStream};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_expand::base::{self, DummyResult};
|
||||
use rustc_span::Span;
|
||||
|
||||
/// Emits errors for literal expressions that are invalid inside and outside of an array.
|
||||
fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_nested: bool) {
|
||||
let ast::ExprKind::Lit(lit) = &expr.kind else {
|
||||
unreachable!();
|
||||
};
|
||||
match lit.kind {
|
||||
ast::LitKind::Char(_) => {
|
||||
let mut err = cx.struct_span_err(expr.span, "cannot concatenate character literals");
|
||||
if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
|
||||
fn invalid_type_err(
|
||||
cx: &mut base::ExtCtxt<'_>,
|
||||
token_lit: ast::token::Lit,
|
||||
span: Span,
|
||||
is_nested: bool,
|
||||
) {
|
||||
match ast::LitKind::from_token_lit(token_lit) {
|
||||
Ok(ast::LitKind::Char(_)) => {
|
||||
let mut err = cx.struct_span_err(span, "cannot concatenate character literals");
|
||||
if let Ok(snippet) = cx.sess.source_map().span_to_snippet(span) {
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
span,
|
||||
"try using a byte character",
|
||||
format!("b{}", snippet),
|
||||
Applicability::MachineApplicable,
|
||||
|
@ -21,13 +24,13 @@ fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_ne
|
|||
.emit();
|
||||
}
|
||||
}
|
||||
ast::LitKind::Str(_, _) => {
|
||||
let mut err = cx.struct_span_err(expr.span, "cannot concatenate string literals");
|
||||
Ok(ast::LitKind::Str(_, _)) => {
|
||||
let mut err = cx.struct_span_err(span, "cannot concatenate string literals");
|
||||
// suggestion would be invalid if we are nested
|
||||
if !is_nested {
|
||||
if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
|
||||
if let Ok(snippet) = cx.sess.source_map().span_to_snippet(span) {
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
span,
|
||||
"try using a byte string",
|
||||
format!("b{}", snippet),
|
||||
Applicability::MachineApplicable,
|
||||
|
@ -36,18 +39,18 @@ fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_ne
|
|||
}
|
||||
err.emit();
|
||||
}
|
||||
ast::LitKind::Float(_, _) => {
|
||||
cx.span_err(expr.span, "cannot concatenate float literals");
|
||||
Ok(ast::LitKind::Float(_, _)) => {
|
||||
cx.span_err(span, "cannot concatenate float literals");
|
||||
}
|
||||
ast::LitKind::Bool(_) => {
|
||||
cx.span_err(expr.span, "cannot concatenate boolean literals");
|
||||
Ok(ast::LitKind::Bool(_)) => {
|
||||
cx.span_err(span, "cannot concatenate boolean literals");
|
||||
}
|
||||
ast::LitKind::Err => {}
|
||||
ast::LitKind::Int(_, _) if !is_nested => {
|
||||
let mut err = cx.struct_span_err(expr.span, "cannot concatenate numeric literals");
|
||||
if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
|
||||
Ok(ast::LitKind::Err) => {}
|
||||
Ok(ast::LitKind::Int(_, _)) if !is_nested => {
|
||||
let mut err = cx.struct_span_err(span, "cannot concatenate numeric literals");
|
||||
if let Ok(snippet) = cx.sess.source_map().span_to_snippet(span) {
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
span,
|
||||
"try wrapping the number in an array",
|
||||
format!("[{}]", snippet),
|
||||
Applicability::MachineApplicable,
|
||||
|
@ -55,15 +58,15 @@ fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_ne
|
|||
}
|
||||
err.emit();
|
||||
}
|
||||
ast::LitKind::Int(
|
||||
Ok(ast::LitKind::Int(
|
||||
val,
|
||||
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
|
||||
) => {
|
||||
)) => {
|
||||
assert!(val > u8::MAX.into()); // must be an error
|
||||
cx.span_err(expr.span, "numeric literal is out of bounds");
|
||||
cx.span_err(span, "numeric literal is out of bounds");
|
||||
}
|
||||
ast::LitKind::Int(_, _) => {
|
||||
cx.span_err(expr.span, "numeric literal is not a `u8`");
|
||||
Ok(ast::LitKind::Int(_, _)) => {
|
||||
cx.span_err(span, "numeric literal is not a `u8`");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
@ -83,14 +86,14 @@ fn handle_array_element(
|
|||
*has_errors = true;
|
||||
None
|
||||
}
|
||||
ast::ExprKind::Lit(ref lit) => match lit.kind {
|
||||
ast::LitKind::Int(
|
||||
ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
|
||||
Ok(ast::LitKind::Int(
|
||||
val,
|
||||
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
|
||||
) if val <= u8::MAX.into() => Some(val as u8),
|
||||
)) if val <= u8::MAX.into() => Some(val as u8),
|
||||
|
||||
ast::LitKind::Byte(val) => Some(val),
|
||||
ast::LitKind::ByteStr(_) => {
|
||||
Ok(ast::LitKind::Byte(val)) => Some(val),
|
||||
Ok(ast::LitKind::ByteStr(_)) => {
|
||||
if !*has_errors {
|
||||
cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
|
||||
.note("byte strings are treated as arrays of bytes")
|
||||
|
@ -102,7 +105,7 @@ fn handle_array_element(
|
|||
}
|
||||
_ => {
|
||||
if !*has_errors {
|
||||
invalid_type_err(cx, expr, true);
|
||||
invalid_type_err(cx, token_lit, expr.span, true);
|
||||
}
|
||||
*has_errors = true;
|
||||
None
|
||||
|
@ -148,9 +151,9 @@ pub fn expand_concat_bytes(
|
|||
}
|
||||
}
|
||||
ast::ExprKind::Repeat(ref expr, ref count) => {
|
||||
if let ast::ExprKind::Lit(ast::Lit {
|
||||
kind: ast::LitKind::Int(count_val, _), ..
|
||||
}) = count.value.kind
|
||||
if let ast::ExprKind::Lit(token_lit) = count.value.kind
|
||||
&& let Ok(ast::LitKind::Int(count_val, _)) =
|
||||
ast::LitKind::from_token_lit(token_lit)
|
||||
{
|
||||
if let Some(elem) =
|
||||
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
|
||||
|
@ -163,16 +166,16 @@ pub fn expand_concat_bytes(
|
|||
cx.span_err(count.value.span, "repeat count is not a positive number");
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Lit(ref lit) => match lit.kind {
|
||||
ast::LitKind::Byte(val) => {
|
||||
ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
|
||||
Ok(ast::LitKind::Byte(val)) => {
|
||||
accumulator.push(val);
|
||||
}
|
||||
ast::LitKind::ByteStr(ref bytes) => {
|
||||
Ok(ast::LitKind::ByteStr(ref bytes)) => {
|
||||
accumulator.extend_from_slice(&bytes);
|
||||
}
|
||||
_ => {
|
||||
if !has_errors {
|
||||
invalid_type_err(cx, &e, false);
|
||||
invalid_type_err(cx, token_lit, e.span, false);
|
||||
}
|
||||
has_errors = true;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue