syntax: Treat error literals in more principled way

This commit is contained in:
Vadim Petrochenkov 2019-06-07 12:53:33 +03:00
parent c1c60d292e
commit 2af47facc3
11 changed files with 33 additions and 27 deletions

View File

@ -1020,7 +1020,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
ExprKind::AddrOf(_, ref subexpression) | ExprKind::Unary(_, ref subexpression) => { ExprKind::AddrOf(_, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
visitor.visit_expr(subexpression) visitor.visit_expr(subexpression)
} }
ExprKind::Lit(_) => {}
ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
visitor.visit_expr(subexpression); visitor.visit_expr(subexpression);
visitor.visit_ty(typ) visitor.visit_ty(typ)
@ -1093,7 +1092,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
ExprKind::Yield(ref subexpression) => { ExprKind::Yield(ref subexpression) => {
visitor.visit_expr(subexpression); visitor.visit_expr(subexpression);
} }
ExprKind::Err => {} ExprKind::Lit(_) | ExprKind::Err => {}
} }
} }

View File

@ -170,14 +170,14 @@ impl_stable_hash_for!(struct ::syntax::ast::Lit {
impl_stable_hash_for!(enum ::syntax::ast::LitKind { impl_stable_hash_for!(enum ::syntax::ast::LitKind {
Str(value, style), Str(value, style),
Err(value),
ByteStr(value), ByteStr(value),
Byte(value), Byte(value),
Char(value), Char(value),
Int(value, lit_int_type), Int(value, lit_int_type),
Float(value, float_ty), Float(value, float_ty),
FloatUnsuffixed(value), FloatUnsuffixed(value),
Bool(value) Bool(value),
Err(value)
}); });
impl_stable_hash_for_spanned!(::syntax::ast::LitKind); impl_stable_hash_for_spanned!(::syntax::ast::LitKind);

View File

@ -34,15 +34,6 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
let allocation = tcx.intern_const_alloc(allocation); let allocation = tcx.intern_const_alloc(allocation);
ConstValue::Slice { data: allocation, start: 0, end: s.len() } ConstValue::Slice { data: allocation, start: 0, end: s.len() }
}, },
LitKind::Err(ref s) => {
let s = s.as_str();
let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes());
let allocation = tcx.intern_const_alloc(allocation);
return Ok(tcx.mk_const(ty::Const {
val: ConstValue::Slice{ data: allocation, start: 0, end: s.len() },
ty: tcx.types.err,
}));
},
LitKind::ByteStr(ref data) => { LitKind::ByteStr(ref data) => {
let id = tcx.allocate_bytes(data); let id = tcx.allocate_bytes(data);
ConstValue::Scalar(Scalar::Ptr(id.into())) ConstValue::Scalar(Scalar::Ptr(id.into()))
@ -66,6 +57,7 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
} }
LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)), LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)),
LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
LitKind::Err(_) => unreachable!(),
}; };
Ok(tcx.mk_const(ty::Const { val: lit, ty })) Ok(tcx.mk_const(ty::Const { val: lit, ty }))
} }

View File

@ -1368,7 +1368,7 @@ pub enum LitKind {
FloatUnsuffixed(Symbol), FloatUnsuffixed(Symbol),
/// A boolean literal. /// A boolean literal.
Bool(bool), Bool(bool),
/// A recovered character literal that contains mutliple `char`s, most likely a typo. /// Placeholder for a literal that wasn't well-formed in some way.
Err(Symbol), Err(Symbol),
} }
@ -1406,10 +1406,10 @@ impl LitKind {
| LitKind::ByteStr(..) | LitKind::ByteStr(..)
| LitKind::Byte(..) | LitKind::Byte(..)
| LitKind::Char(..) | LitKind::Char(..)
| LitKind::Err(..)
| LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Int(_, LitIntType::Unsuffixed)
| LitKind::FloatUnsuffixed(..) | LitKind::FloatUnsuffixed(..)
| LitKind::Bool(..) => true, | LitKind::Bool(..)
| LitKind::Err(..) => true,
// suffixed variants // suffixed variants
LitKind::Int(_, LitIntType::Signed(..)) LitKind::Int(_, LitIntType::Signed(..))
| LitKind::Int(_, LitIntType::Unsigned(..)) | LitKind::Int(_, LitIntType::Unsigned(..))

View File

@ -1101,7 +1101,6 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { node, id, span, attrs }: &mut Expr,
vis.visit_expr(rhs); vis.visit_expr(rhs);
} }
ExprKind::Unary(_unop, ohs) => vis.visit_expr(ohs), ExprKind::Unary(_unop, ohs) => vis.visit_expr(ohs),
ExprKind::Lit(_lit) => {}
ExprKind::Cast(expr, ty) => { ExprKind::Cast(expr, ty) => {
vis.visit_expr(expr); vis.visit_expr(expr);
vis.visit_ty(ty); vis.visit_ty(ty);
@ -1225,7 +1224,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { node, id, span, attrs }: &mut Expr,
} }
ExprKind::Try(expr) => vis.visit_expr(expr), ExprKind::Try(expr) => vis.visit_expr(expr),
ExprKind::TryBlock(body) => vis.visit_block(body), ExprKind::TryBlock(body) => vis.visit_block(body),
ExprKind::Err => {} ExprKind::Lit(_) | ExprKind::Err => {}
} }
vis.visit_id(id); vis.visit_id(id);
vis.visit_span(span); vis.visit_span(span);

View File

@ -311,7 +311,11 @@ impl<'a> Parser<'a> {
let (lit, span) = (token.expect_lit(), token.span); let (lit, span) = (token.expect_lit(), token.span);
self.bump(); self.bump();
err.report(&self.sess.span_diagnostic, lit, span); err.report(&self.sess.span_diagnostic, lit, span);
let lit = token::Lit::new(token::Err, lit.symbol, lit.suffix); // Pack possible quotes and prefixes from the original literal into
// the error literal's symbol so they can be pretty-printed faithfully.
let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
let symbol = Symbol::intern(&pprust::literal_to_string(suffixless_lit));
let lit = token::Lit::new(token::Err, symbol, lit.suffix);
Lit::from_lit_token(lit, span).map_err(|_| unreachable!()) Lit::from_lit_token(lit, span).map_err(|_| unreachable!())
} }
} }

View File

@ -168,9 +168,6 @@ pub fn literal_to_string(lit: token::Lit) -> String {
let mut out = match kind { let mut out = match kind {
token::Byte => format!("b'{}'", symbol), token::Byte => format!("b'{}'", symbol),
token::Char => format!("'{}'", symbol), token::Char => format!("'{}'", symbol),
token::Bool |
token::Float |
token::Integer => symbol.to_string(),
token::Str => format!("\"{}\"", symbol), token::Str => format!("\"{}\"", symbol),
token::StrRaw(n) => format!("r{delim}\"{string}\"{delim}", token::StrRaw(n) => format!("r{delim}\"{string}\"{delim}",
delim="#".repeat(n as usize), delim="#".repeat(n as usize),
@ -179,7 +176,10 @@ pub fn literal_to_string(lit: token::Lit) -> String {
token::ByteStrRaw(n) => format!("br{delim}\"{string}\"{delim}", token::ByteStrRaw(n) => format!("br{delim}\"{string}\"{delim}",
delim="#".repeat(n as usize), delim="#".repeat(n as usize),
string=symbol), string=symbol),
token::Err => format!("'{}'", symbol), token::Integer |
token::Float |
token::Bool |
token::Err => symbol.to_string(),
}; };
if let Some(suffix) = suffix { if let Some(suffix) = suffix {

View File

@ -714,7 +714,6 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
ExprKind::AddrOf(_, ref subexpression) | ExprKind::Unary(_, ref subexpression) => { ExprKind::AddrOf(_, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
visitor.visit_expr(subexpression) visitor.visit_expr(subexpression)
} }
ExprKind::Lit(_) => {}
ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
visitor.visit_expr(subexpression); visitor.visit_expr(subexpression);
visitor.visit_ty(typ) visitor.visit_ty(typ)
@ -826,7 +825,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
ExprKind::TryBlock(ref body) => { ExprKind::TryBlock(ref body) => {
visitor.visit_block(body) visitor.visit_block(body)
} }
ExprKind::Err => {} ExprKind::Lit(_) | ExprKind::Err => {}
} }
visitor.visit_expr_post(expression) visitor.visit_expr_post(expression)

View File

@ -22,7 +22,6 @@ pub fn expand_syntax_ext(
match e.node { match e.node {
ast::ExprKind::Lit(ref lit) => match lit.node { ast::ExprKind::Lit(ref lit) => match lit.node {
ast::LitKind::Str(ref s, _) ast::LitKind::Str(ref s, _)
| ast::LitKind::Err(ref s)
| ast::LitKind::Float(ref s, _) | ast::LitKind::Float(ref s, _)
| ast::LitKind::FloatUnsuffixed(ref s) => { | ast::LitKind::FloatUnsuffixed(ref s) => {
accumulator.push_str(&s.as_str()); accumulator.push_str(&s.as_str());
@ -41,6 +40,9 @@ pub fn expand_syntax_ext(
ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..) => { ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..) => {
cx.span_err(e.span, "cannot concatenate a byte string literal"); cx.span_err(e.span, "cannot concatenate a byte string literal");
} }
ast::LitKind::Err(_) => {
has_errors = true;
}
}, },
ast::ExprKind::Err => { ast::ExprKind::Err => {
has_errors = true; has_errors = true;

View File

@ -12,4 +12,9 @@ mod nonexistent_env {
//~^ ERROR environment variable `NON_EXISTENT` not defined //~^ ERROR environment variable `NON_EXISTENT` not defined
} }
mod erroneous_literal {
include!(concat!("NON_EXISTENT"suffix, "/data.rs"));
//~^ ERROR suffixes on a string literal are invalid
}
fn main() {} fn main() {}

View File

@ -4,6 +4,12 @@ error: environment variable `NON_EXISTENT` not defined
LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
error: suffixes on a string literal are invalid
--> $DIR/issue-55897.rs:16:22
|
LL | include!(concat!("NON_EXISTENT"suffix, "/data.rs"));
| ^^^^^^^^^^^^^^^^^^^^ invalid suffix `suffix`
error[E0432]: unresolved import `prelude` error[E0432]: unresolved import `prelude`
--> $DIR/issue-55897.rs:1:5 --> $DIR/issue-55897.rs:1:5
| |
@ -21,6 +27,6 @@ LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
| |
= note: import resolution is stuck, try simplifying macro imports = note: import resolution is stuck, try simplifying macro imports
error: aborting due to 3 previous errors error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0432`. For more information about this error, try `rustc --explain E0432`.