From 2af47facc3fd7eda3fb4e52f0589bb6f48eff15c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 7 Jun 2019 12:53:33 +0300 Subject: [PATCH] syntax: Treat error literals in more principled way --- src/librustc/hir/intravisit.rs | 3 +-- src/librustc/ich/impls_syntax.rs | 4 ++-- src/librustc_mir/hair/constant.rs | 10 +--------- src/libsyntax/ast.rs | 6 +++--- src/libsyntax/mut_visit.rs | 3 +-- src/libsyntax/parse/literal.rs | 6 +++++- src/libsyntax/print/pprust.rs | 8 ++++---- src/libsyntax/visit.rs | 3 +-- src/libsyntax_ext/concat.rs | 4 +++- src/test/ui/extenv/issue-55897.rs | 5 +++++ src/test/ui/extenv/issue-55897.stderr | 8 +++++++- 11 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 1c66f8bdf81bd..f4f9d6261de48 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -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) => { visitor.visit_expr(subexpression) } - ExprKind::Lit(_) => {} ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { visitor.visit_expr(subexpression); 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) => { visitor.visit_expr(subexpression); } - ExprKind::Err => {} + ExprKind::Lit(_) | ExprKind::Err => {} } } diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index abe4196abd19c..e0c01277801d4 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -170,14 +170,14 @@ impl_stable_hash_for!(struct ::syntax::ast::Lit { impl_stable_hash_for!(enum ::syntax::ast::LitKind { Str(value, style), - Err(value), ByteStr(value), Byte(value), Char(value), Int(value, lit_int_type), Float(value, float_ty), FloatUnsuffixed(value), - Bool(value) + Bool(value), + Err(value) }); impl_stable_hash_for_spanned!(::syntax::ast::LitKind); diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs index a5be55d16d488..b5604f4cb0f8e 100644 --- a/src/librustc_mir/hair/constant.rs +++ b/src/librustc_mir/hair/constant.rs @@ -34,15 +34,6 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>( let allocation = tcx.intern_const_alloc(allocation); 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) => { let id = tcx.allocate_bytes(data); 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::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), + LitKind::Err(_) => unreachable!(), }; Ok(tcx.mk_const(ty::Const { val: lit, ty })) } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 598232f9f8f22..02fbcb14fa599 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1368,7 +1368,7 @@ pub enum LitKind { FloatUnsuffixed(Symbol), /// A boolean literal. 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), } @@ -1406,10 +1406,10 @@ impl LitKind { | LitKind::ByteStr(..) | LitKind::Byte(..) | LitKind::Char(..) - | LitKind::Err(..) | LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::FloatUnsuffixed(..) - | LitKind::Bool(..) => true, + | LitKind::Bool(..) + | LitKind::Err(..) => true, // suffixed variants LitKind::Int(_, LitIntType::Signed(..)) | LitKind::Int(_, LitIntType::Unsigned(..)) diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index d2a614c4a54ac..2889f8edfc64c 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1101,7 +1101,6 @@ pub fn noop_visit_expr(Expr { node, id, span, attrs }: &mut Expr, vis.visit_expr(rhs); } ExprKind::Unary(_unop, ohs) => vis.visit_expr(ohs), - ExprKind::Lit(_lit) => {} ExprKind::Cast(expr, ty) => { vis.visit_expr(expr); vis.visit_ty(ty); @@ -1225,7 +1224,7 @@ pub fn noop_visit_expr(Expr { node, id, span, attrs }: &mut Expr, } ExprKind::Try(expr) => vis.visit_expr(expr), ExprKind::TryBlock(body) => vis.visit_block(body), - ExprKind::Err => {} + ExprKind::Lit(_) | ExprKind::Err => {} } vis.visit_id(id); vis.visit_span(span); diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index 7d5356ffe4d8d..467ad6ccfbe88 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -311,7 +311,11 @@ impl<'a> Parser<'a> { let (lit, span) = (token.expect_lit(), token.span); self.bump(); 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!()) } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 07acfb5dc86c3..d922e1896cc9c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -168,9 +168,6 @@ pub fn literal_to_string(lit: token::Lit) -> String { let mut out = match kind { token::Byte => format!("b'{}'", symbol), token::Char => format!("'{}'", symbol), - token::Bool | - token::Float | - token::Integer => symbol.to_string(), token::Str => format!("\"{}\"", symbol), token::StrRaw(n) => format!("r{delim}\"{string}\"{delim}", 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}", delim="#".repeat(n as usize), string=symbol), - token::Err => format!("'{}'", symbol), + token::Integer | + token::Float | + token::Bool | + token::Err => symbol.to_string(), }; if let Some(suffix) = suffix { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4e6a8274a478c..24b0c37247191 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -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) => { visitor.visit_expr(subexpression) } - ExprKind::Lit(_) => {} ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { visitor.visit_expr(subexpression); 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) => { visitor.visit_block(body) } - ExprKind::Err => {} + ExprKind::Lit(_) | ExprKind::Err => {} } visitor.visit_expr_post(expression) diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index 230b00c0f8f55..68d5178372eba 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -22,7 +22,6 @@ pub fn expand_syntax_ext( match e.node { ast::ExprKind::Lit(ref lit) => match lit.node { ast::LitKind::Str(ref s, _) - | ast::LitKind::Err(ref s) | ast::LitKind::Float(ref s, _) | ast::LitKind::FloatUnsuffixed(ref s) => { accumulator.push_str(&s.as_str()); @@ -41,6 +40,9 @@ pub fn expand_syntax_ext( ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..) => { cx.span_err(e.span, "cannot concatenate a byte string literal"); } + ast::LitKind::Err(_) => { + has_errors = true; + } }, ast::ExprKind::Err => { has_errors = true; diff --git a/src/test/ui/extenv/issue-55897.rs b/src/test/ui/extenv/issue-55897.rs index bd151c8a4e4e7..c3975f6b9255e 100644 --- a/src/test/ui/extenv/issue-55897.rs +++ b/src/test/ui/extenv/issue-55897.rs @@ -12,4 +12,9 @@ mod nonexistent_env { //~^ 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() {} diff --git a/src/test/ui/extenv/issue-55897.stderr b/src/test/ui/extenv/issue-55897.stderr index 9f6570ab2a0f3..9d68131beabd7 100644 --- a/src/test/ui/extenv/issue-55897.stderr +++ b/src/test/ui/extenv/issue-55897.stderr @@ -4,6 +4,12 @@ error: environment variable `NON_EXISTENT` not defined 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` --> $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 -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0432`.