From c16f710daa0d56c0a741c57a9d7d669d15b90f7c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 22 Aug 2022 14:52:51 +1000 Subject: [PATCH] Remove `token::Lit` from `ast::Lit`. `token::Lit` contains a `kind` field that indicates what kind of literal it is. `ast::Lit` currently wraps a `token::Lit` but also has its own `kind` field. Which means that `ast::Lit` encodes the literal kind in two different ways. This commit changes `ast::Lit` 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 requires extending `ast::LitKind::ByteStr` to include a `StrStyle` to properly distinguish between cooked and raw byte string literals at the `ast::Lit` level. --- compiler/rustc_ast/src/ast.rs | 59 ++++++++++++++----- compiler/rustc_ast/src/util/literal.rs | 46 ++++++++++----- compiler/rustc_ast_lowering/src/lib.rs | 6 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- .../rustc_builtin_macros/src/concat_bytes.rs | 4 +- compiler/rustc_builtin_macros/src/derive.rs | 10 ++-- compiler/rustc_expand/src/base.rs | 2 +- compiler/rustc_expand/src/build.rs | 2 +- .../rustc_expand/src/proc_macro_server.rs | 19 ++---- .../src/hidden_unicode_codepoints.rs | 6 +- .../src/build/expr/as_constant.rs | 4 +- compiler/rustc_mir_build/src/thir/constant.rs | 4 +- compiler/rustc_parse/src/parser/expr.rs | 4 +- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 2 +- compiler/rustc_typeck/src/check/pat.rs | 2 +- .../src/invalid_utf8_in_unchecked.rs | 2 +- .../clippy_lints/src/large_include_file.rs | 2 +- .../src/matches/match_same_arms.rs | 2 +- .../clippy/clippy_lints/src/octal_escapes.rs | 17 +++--- .../clippy/clippy_lints/src/utils/author.rs | 2 +- src/tools/clippy/clippy_lints/src/write.rs | 27 ++++----- .../clippy_utils/src/check_proc_macro.rs | 4 +- src/tools/clippy/clippy_utils/src/consts.rs | 2 +- src/tools/rustfmt/src/expr.rs | 10 ++-- 24 files changed, 137 insertions(+), 103 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f25fdc942b085..666c582308bb4 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -23,7 +23,7 @@ pub use GenericArgs::*; pub use UnsafeSource::*; use crate::ptr::P; -use crate::token::{self, CommentKind, Delimiter}; +use crate::token::{CommentKind, Delimiter}; use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -1719,15 +1719,49 @@ pub enum StrStyle { /// An AST literal. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct Lit { - /// The original literal token as written in source code. - pub token_lit: token::Lit, + /// The original literal as written in the source code. + pub symbol: Symbol, + /// The original suffix as written in the source code. + pub suffix: Option, /// 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, } +impl fmt::Display for Lit { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Lit { kind, symbol, suffix, .. } = self; + match kind { + LitKind::Byte(_) => write!(f, "b'{}'", symbol)?, + LitKind::Char(_) => write!(f, "'{}'", symbol)?, + LitKind::Str(_, StrStyle::Cooked) => write!(f, "\"{}\"", symbol)?, + LitKind::Str(_, StrStyle::Raw(n)) => write!( + f, + "r{delim}\"{string}\"{delim}", + delim = "#".repeat(*n as usize), + string = symbol + )?, + LitKind::ByteStr(_, StrStyle::Cooked) => write!(f, "b\"{}\"", symbol)?, + LitKind::ByteStr(_, StrStyle::Raw(n)) => write!( + f, + "br{delim}\"{string}\"{delim}", + delim = "#".repeat(*n as usize), + string = symbol + )?, + LitKind::Int(..) | LitKind::Float(..) | LitKind::Bool(..) | LitKind::Err => { + write!(f, "{}", symbol)? + } + } + + if let Some(suffix) = suffix { + write!(f, "{}", suffix)?; + } + + Ok(()) + } +} + /// Same as `Lit`, but restricted to string literals. #[derive(Clone, Copy, Encodable, Decodable, Debug)] pub struct StrLit { @@ -1737,18 +1771,14 @@ pub struct StrLit { pub suffix: Option, pub span: Span, /// The unescaped "semantic" representation of the literal lowered from the original token. - /// FIXME: Remove this and only create the semantic representation during lowering to HIR. pub symbol_unescaped: Symbol, } impl StrLit { pub fn as_lit(&self) -> Lit { - let token_kind = match self.style { - StrStyle::Cooked => token::Str, - StrStyle::Raw(n) => token::StrRaw(n), - }; Lit { - token_lit: token::Lit::new(token_kind, self.symbol, self.suffix), + symbol: self.symbol, + suffix: self.suffix, span: self.span, kind: LitKind::Str(self.symbol_unescaped, self.style), } @@ -1785,8 +1815,9 @@ pub enum LitKind { /// A string literal (`"foo"`). The symbol is unescaped, and so may differ /// from the original token's symbol. Str(Symbol, StrStyle), - /// A byte string (`b"foo"`). - ByteStr(Lrc<[u8]>), + /// A byte string (`b"foo"`). Not stored as a symbol because it might be + /// non-utf8, and symbols only allow utf8 strings. + ByteStr(Lrc<[u8]>, StrStyle), /// A byte char (`b'f'`). Byte(u8), /// A character literal (`'a'`). @@ -1810,7 +1841,7 @@ impl LitKind { /// Returns `true` if this literal is byte literal string. pub fn is_bytestr(&self) -> bool { - matches!(self, LitKind::ByteStr(_)) + matches!(self, LitKind::ByteStr(..)) } /// Returns `true` if this is a numeric literal. @@ -3084,7 +3115,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, 40); static_assert_size!(LitKind, 24); static_assert_size!(Local, 72); static_assert_size!(Param, 40); diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 6a1578498e689..73f2b9cb5fd22 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -1,13 +1,11 @@ //! Code related to parsing literals. -use crate::ast::{self, Lit, LitKind}; +use crate::ast::{self, Lit, LitKind, StrStyle}; 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 { @@ -120,9 +118,9 @@ impl LitKind { } }); error?; - LitKind::ByteStr(buf.into()) + LitKind::ByteStr(buf.into(), StrStyle::Cooked) } - token::ByteStrRaw(_) => { + token::ByteStrRaw(n) => { let s = symbol.as_str(); let bytes = if s.contains('\r') { let mut buf = Vec::with_capacity(s.len()); @@ -143,7 +141,7 @@ impl LitKind { symbol.to_string().into_bytes() }; - LitKind::ByteStr(bytes.into()) + LitKind::ByteStr(bytes.into(), StrStyle::Raw(n)) } token::Err => LitKind::Err, }) @@ -162,15 +160,19 @@ impl LitKind { (token::Str, symbol, None) } LitKind::Str(symbol, ast::StrStyle::Raw(n)) => (token::StrRaw(n), symbol, None), - LitKind::ByteStr(ref bytes) => { + LitKind::ByteStr(ref bytes, ast::StrStyle::Cooked) => { let string = bytes .iter() - .cloned() + .copied() .flat_map(ascii::escape_default) .map(Into::::into) .collect::(); (token::ByteStr, Symbol::intern(&string), None) } + LitKind::ByteStr(ref bytes, ast::StrStyle::Raw(n)) => { + let string = bytes.iter().copied().map(Into::::into).collect::(); + (token::ByteStrRaw(n), Symbol::intern(&string), None) + } LitKind::Byte(byte) => { let string: String = ascii::escape_default(byte).map(Into::::into).collect(); (token::Byte, Symbol::intern(&string), None) @@ -210,7 +212,12 @@ impl LitKind { impl Lit { /// Converts literal token into an AST literal. pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result { - Ok(Lit { token_lit, kind: LitKind::from_token_lit(token_lit)?, span }) + Ok(Lit { + symbol: token_lit.symbol, + suffix: token_lit.suffix, + kind: LitKind::from_token_lit(token_lit)?, + span, + }) } /// Converts arbitrary token into an AST literal. @@ -240,16 +247,27 @@ impl Lit { /// 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 } + let token_lit = kind.to_token_lit(); + Lit { symbol: token_lit.symbol, suffix: token_lit.suffix, kind, span } } /// Losslessly convert an AST literal into a token. pub fn to_token(&self) -> Token { - let kind = match self.token_lit.kind { - token::Bool => token::Ident(self.token_lit.symbol, false), - _ => token::Literal(self.token_lit), + let symbol = self.symbol; + let suffix = self.suffix; + let kind = match self.kind { + LitKind::Bool(_) => return Token::new(token::Ident(symbol, false), self.span), + LitKind::Str(_, StrStyle::Cooked) => token::LitKind::Str, + LitKind::Str(_, StrStyle::Raw(n)) => token::LitKind::StrRaw(n), + LitKind::ByteStr(_, StrStyle::Cooked) => token::LitKind::ByteStr, + LitKind::ByteStr(_, StrStyle::Raw(n)) => token::LitKind::ByteStrRaw(n), + LitKind::Byte(_) => token::LitKind::Byte, + LitKind::Char(_) => token::LitKind::Char, + LitKind::Int(..) => token::LitKind::Integer, + LitKind::Float(..) => token::LitKind::Float, + LitKind::Err => token::LitKind::Err, }; - Token::new(kind, self.span) + Token::new(token::Literal(token::Lit { kind, symbol, suffix }), self.span) } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3a94c7a91b23f..72719742aaeca 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -925,11 +925,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lit = if let ExprKind::Lit(lit) = &expr.kind { lit.clone() } else { - Lit { - token_lit: token::Lit::new(token::LitKind::Err, kw::Empty, None), - kind: LitKind::Err, - span: DUMMY_SP, - } + Lit { symbol: kw::Empty, suffix: None, kind: LitKind::Err, span: DUMMY_SP } }; MacArgs::Eq(eq_span, MacArgsEq::Hir(lit)) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index ed5e7dace4bc4..84f88c0a07c51 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -372,7 +372,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere fn print_literal(&mut self, lit: &ast::Lit) { self.maybe_print_comment(lit.span.lo()); - self.word(lit.token_lit.to_string()) + self.word(lit.to_string()) } fn print_string(&mut self, st: &str, style: ast::StrStyle) { diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index 66e86bf218267..5a5838236d50c 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -90,7 +90,7 @@ fn handle_array_element( ) if val <= u8::MAX.into() => Some(val as u8), ast::LitKind::Byte(val) => Some(val), - ast::LitKind::ByteStr(_) => { + 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") @@ -157,7 +157,7 @@ pub fn expand_concat_bytes( ast::LitKind::Byte(val) => { accumulator.push(val); } - ast::LitKind::ByteStr(ref bytes) => { + ast::LitKind::ByteStr(ref bytes, _) => { accumulator.extend_from_slice(&bytes); } _ => { diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 467ac34ded942..8d880f8b2f831 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,7 +1,7 @@ use crate::cfg_eval::cfg_eval; use rustc_ast as ast; -use rustc_ast::{attr, token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; +use rustc_ast::{attr, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; use rustc_errors::{struct_span_err, Applicability}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; use rustc_feature::AttributeTemplate; @@ -126,9 +126,11 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { } fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) { - let help_msg = match lit.token_lit.kind { - token::Str if rustc_lexer::is_ident(lit.token_lit.symbol.as_str()) => { - format!("try using `#[derive({})]`", lit.token_lit.symbol) + let help_msg = match lit.kind { + ast::LitKind::Str(_, ast::StrStyle::Cooked) + if rustc_lexer::is_ident(lit.symbol.as_str()) => + { + format!("try using `#[derive({})]`", lit.symbol) } _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(), }; diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 2bb522caa2d41..ab4f6efa21a3f 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1217,7 +1217,7 @@ pub fn expr_to_spanned_string<'a>( Err(match expr.kind { ast::ExprKind::Lit(ref l) => match l.kind { ast::LitKind::Str(s, style) => return Ok((s, style, expr.span)), - ast::LitKind::ByteStr(_) => { + ast::LitKind::ByteStr(..) => { let mut err = cx.struct_span_err(l.span, err_msg); err.span_suggestion( expr.span.shrink_to_lo(), diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index cf2c023c2f89f..d9620258b4fc2 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -358,7 +358,7 @@ impl<'a> ExtCtxt<'a> { } pub fn expr_byte_str(&self, sp: Span, bytes: Vec) -> P { - self.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(bytes))) + self.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(bytes), ast::StrStyle::Cooked)) } /// `[expr1, expr2, ...]` diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 59a7b668a83ce..6cb991ce733a7 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -499,26 +499,19 @@ impl server::TokenStream for Rustc<'_, '_> { // We don't use `TokenStream::from_ast` as the tokenstream currently cannot // be recovered in the general case. match &expr.kind { - ast::ExprKind::Lit(l) if l.token_lit.kind == token::Bool => { - Ok(tokenstream::TokenStream::token_alone( - token::Ident(l.token_lit.symbol, false), - l.span, - )) - } ast::ExprKind::Lit(l) => { - Ok(tokenstream::TokenStream::token_alone(token::Literal(l.token_lit), l.span)) + let token = l.to_token(); + Ok(tokenstream::TokenStream::token_alone(token.kind, token.span)) } ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind { - ast::ExprKind::Lit(l) => match l.token_lit { - token::Lit { kind: token::Integer | token::Float, .. } => { + ast::ExprKind::Lit(l) => match l.kind { + ast::LitKind::Int(..) | ast::LitKind::Float(..) => { + let token = l.to_token(); Ok(Self::TokenStream::from_iter([ // FIXME: The span of the `-` token is lost when // parsing, so we cannot faithfully recover it here. tokenstream::TokenTree::token_alone(token::BinOp(token::Minus), e.span), - tokenstream::TokenTree::token_alone( - token::Literal(l.token_lit), - l.span, - ), + tokenstream::TokenTree::token_alone(token.kind, token.span), ])) } _ => Err(()), diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs index 8f22221324a6e..ed252ce41b8e4 100644 --- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs +++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs @@ -120,8 +120,8 @@ impl EarlyLintPass for HiddenUnicodeCodepoints { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { // byte strings are already handled well enough by `EscapeError::NonAsciiCharInByteString` let (text, span, padding) = match &expr.kind { - ast::ExprKind::Lit(ast::Lit { token_lit, kind, span }) => { - let text = token_lit.symbol; + ast::ExprKind::Lit(ast::Lit { symbol, kind, span, .. }) => { + let text = symbol; if !contains_text_flow_control_chars(text.as_str()) { return; } @@ -136,6 +136,6 @@ impl EarlyLintPass for HiddenUnicodeCodepoints { } _ => return, }; - self.lint_text_direction_codepoint(cx, text, *span, padding, true, "literal"); + self.lint_text_direction_codepoint(cx, *text, *span, padding, true, "literal"); } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 3549b47478cbd..613fd3157e4a1 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -122,14 +122,14 @@ pub(crate) fn lit_to_mir_constant<'tcx>( let allocation = tcx.intern_const_alloc(allocation); ConstValue::Slice { data: allocation, start: 0, end: s.len() } } - (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) + (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(_)) => { let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]); let allocation = tcx.intern_const_alloc(allocation); ConstValue::Slice { data: allocation, start: 0, end: data.len() } } - (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { + (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { let id = tcx.allocate_bytes(data); ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx)) } diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index f626571b5b2c5..b1b69356b88fb 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -24,13 +24,13 @@ pub(crate) fn lit_to_const<'tcx>( let str_bytes = s.as_str().as_bytes(); ty::ValTree::from_raw_bytes(tcx, str_bytes) } - (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) + (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(_)) => { let bytes = data as &[u8]; ty::ValTree::from_raw_bytes(tcx, bytes) } - (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { + (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { let bytes = data as &[u8]; ty::ValTree::from_raw_bytes(tcx, bytes) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 7addf519872f0..fb963ba3b5521 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1723,8 +1723,8 @@ impl<'a> Parser<'a> { Some(lit) => match lit.kind { ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit { style, - symbol: lit.token_lit.symbol, - suffix: lit.token_lit.suffix, + symbol: lit.symbol, + suffix: lit.suffix, span: lit.span, symbol_unescaped, }), diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 311fcaadaa98b..631edee6052d6 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -1150,7 +1150,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match lit.node { ast::LitKind::Str(..) => tcx.mk_static_str(), - ast::LitKind::ByteStr(ref v) => { + ast::LitKind::ByteStr(ref v, _) => { tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64)) } ast::LitKind::Byte(_) => tcx.types.u8, diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 9096fc442d493..fcd940badf662 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -388,7 +388,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Byte string patterns behave the same way as array patterns // They can denote both statically and dynamically-sized byte arrays. let mut pat_ty = ty; - if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(_), .. }) = lt.kind { + if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind { let expected = self.structurally_resolved_type(span, expected); if let ty::Ref(_, inner_ty, _) = expected.kind() && matches!(inner_ty.kind(), ty::Slice(_)) diff --git a/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs b/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs index e0a607f9a95b6..6a4861747d267 100644 --- a/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs +++ b/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs @@ -33,7 +33,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidUtf8InUnchecked { if let Some([arg]) = match_function_call(cx, expr, &paths::STR_FROM_UTF8_UNCHECKED) { match &arg.kind { ExprKind::Lit(Spanned { node: lit, .. }) => { - if let LitKind::ByteStr(bytes) = &lit + if let LitKind::ByteStr(bytes, _) = &lit && std::str::from_utf8(bytes).is_err() { lint(cx, expr.span); diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs index 84dd61a1e4b0d..424c0d9e79828 100644 --- a/src/tools/clippy/clippy_lints/src/large_include_file.rs +++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs @@ -60,7 +60,7 @@ impl LateLintPass<'_> for LargeIncludeFile { then { let len = match &lit.node { // include_bytes - LitKind::ByteStr(bstr) => bstr.len(), + LitKind::ByteStr(bstr, _) => bstr.len(), // include_str LitKind::Str(sym, _) => sym.as_str().len(), _ => return, diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index e32ef9933afe5..f11ac25d106ad 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -285,7 +285,7 @@ impl<'a> NormalizedPat<'a> { // TODO: Handle negative integers. They're currently treated as a wild match. ExprKind::Lit(lit) => match lit.node { LitKind::Str(sym, _) => Self::LitStr(sym), - LitKind::ByteStr(ref bytes) => Self::LitBytes(bytes), + LitKind::ByteStr(ref bytes, _) => Self::LitBytes(bytes), LitKind::Byte(val) => Self::LitInt(val.into()), LitKind::Char(val) => Self::LitInt(val.into()), LitKind::Int(val, _) => Self::LitInt(val), diff --git a/src/tools/clippy/clippy_lints/src/octal_escapes.rs b/src/tools/clippy/clippy_lints/src/octal_escapes.rs index bffbf20b4d289..1648a443a076a 100644 --- a/src/tools/clippy/clippy_lints/src/octal_escapes.rs +++ b/src/tools/clippy/clippy_lints/src/octal_escapes.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; -use rustc_ast::ast::{Expr, ExprKind}; -use rustc_ast::token::{Lit, LitKind}; +use rustc_ast::ast::{Expr, ExprKind, LitKind, StrStyle}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; use std::fmt::Write; declare_clippy_lint! { @@ -57,17 +56,17 @@ impl EarlyLintPass for OctalEscapes { } if let ExprKind::Lit(lit) = &expr.kind { - if matches!(lit.token_lit.kind, LitKind::Str) { - check_lit(cx, &lit.token_lit, lit.span, true); - } else if matches!(lit.token_lit.kind, LitKind::ByteStr) { - check_lit(cx, &lit.token_lit, lit.span, false); + if matches!(lit.kind, LitKind::Str(_, StrStyle::Cooked)) { + check_lit(cx, lit.symbol, lit.span, true); + } else if matches!(lit.kind, LitKind::ByteStr(_, StrStyle::Cooked)) { + check_lit(cx, lit.symbol, lit.span, false); } } } } -fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) { - let contents = lit.symbol.as_str(); +fn check_lit(cx: &EarlyContext<'_>, symbol: Symbol, span: Span, is_string: bool) { + let contents = symbol.as_str(); let mut iter = contents.char_indices().peekable(); let mut found = vec![]; diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 1489c96d9e9b0..88bacc1deead7 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -295,7 +295,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { }; kind!("Float(_, {float_ty})"); }, - LitKind::ByteStr(ref vec) => { + LitKind::ByteStr(ref vec, _) => { bind!(self, vec); kind!("ByteStr(ref {vec})"); out!("if let [{:?}] = **{vec};", vec.value); diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index 347165d9704a1..a155c724e1e2c 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -4,9 +4,9 @@ use std::ops::{Deref, Range}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; -use rustc_ast::ast::{Expr, ExprKind, Impl, Item, ItemKind, MacCall, Path, StrLit, StrStyle}; +use rustc_ast::ast::{Expr, ExprKind, Impl, Item, ItemKind, LitKind, MacCall, Path, StrLit, StrStyle}; use rustc_ast::ptr::P; -use rustc_ast::token::{self, LitKind}; +use rustc_ast::token::{self}; use rustc_ast::tokenstream::TokenStream; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_lexer::unescape::{self, EscapeError}; @@ -683,21 +683,16 @@ impl Write { }, }; - let replacement: String = match lit.token_lit.kind { - LitKind::StrRaw(_) | LitKind::ByteStrRaw(_) if matches!(fmtstr.style, StrStyle::Raw(_)) => { - lit.token_lit.symbol.as_str().replace('{', "{{").replace('}', "}}") + let replacement: String = match lit.kind { + LitKind::Str(_, style) | LitKind::ByteStr(_, style) if fmtstr.style == style => { + lit.symbol.as_str().replace('{', "{{").replace('}', "}}") }, - LitKind::Str | LitKind::ByteStr if matches!(fmtstr.style, StrStyle::Cooked) => { - lit.token_lit.symbol.as_str().replace('{', "{{").replace('}', "}}") - }, - LitKind::StrRaw(_) - | LitKind::Str - | LitKind::ByteStrRaw(_) - | LitKind::ByteStr - | LitKind::Integer - | LitKind::Float + LitKind::Str(..) + | LitKind::ByteStr(..) + | LitKind::Int(..) + | LitKind::Float(..) | LitKind::Err => continue, - LitKind::Byte | LitKind::Char => match lit.token_lit.symbol.as_str() { + LitKind::Byte(_) | LitKind::Char(_) => match lit.symbol.as_str() { "\"" if matches!(fmtstr.style, StrStyle::Cooked) => "\\\"", "\"" if matches!(fmtstr.style, StrStyle::Raw(0)) => continue, "\\\\" if matches!(fmtstr.style, StrStyle::Raw(_)) => "\\", @@ -708,7 +703,7 @@ impl Write { x => x, } .into(), - LitKind::Bool => lit.token_lit.symbol.as_str().deref().into(), + LitKind::Bool(_) => lit.symbol.as_str().deref().into(), }; if !fmt_spans.is_empty() { diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index e8d2d579f097e..bb4f1ad8fde55 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -69,7 +69,9 @@ fn lit_search_pat(lit: &LitKind) -> (Pat, Pat) { LitKind::Str(_, StrStyle::Cooked) => (Pat::Str("\""), Pat::Str("\"")), LitKind::Str(_, StrStyle::Raw(0)) => (Pat::Str("r"), Pat::Str("\"")), LitKind::Str(_, StrStyle::Raw(_)) => (Pat::Str("r#"), Pat::Str("#")), - LitKind::ByteStr(_) => (Pat::Str("b\""), Pat::Str("\"")), + LitKind::ByteStr(_, StrStyle::Cooked) => (Pat::Str("b\""), Pat::Str("\"")), + LitKind::ByteStr(_, StrStyle::Raw(0)) => (Pat::Str("br\""), Pat::Str("\"")), + LitKind::ByteStr(_, StrStyle::Raw(_)) => (Pat::Str("br#\""), Pat::Str("#")), LitKind::Byte(_) => (Pat::Str("b'"), Pat::Str("'")), LitKind::Char(_) => (Pat::Str("'"), Pat::Str("'")), LitKind::Int(_, LitIntType::Signed(IntTy::Isize)) => (Pat::Num, Pat::Str("isize")), diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index e053708edd507..1c7c31585d235 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -179,7 +179,7 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option>) -> Constant { match *lit { LitKind::Str(ref is, _) => Constant::Str(is.to_string()), LitKind::Byte(b) => Constant::Int(u128::from(b)), - LitKind::ByteStr(ref s) => Constant::Binary(Lrc::clone(s)), + LitKind::ByteStr(ref s, _) => Constant::Binary(Lrc::clone(s)), LitKind::Char(c) => Constant::Char(c), LitKind::Int(n, _) => Constant::Int(n), LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty { diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 3105882e2d308..5952618b7de97 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::cmp::min; use itertools::Itertools; -use rustc_ast::token::{Delimiter, LitKind}; +use rustc_ast::token::Delimiter; use rustc_ast::{ast, ptr}; use rustc_span::{BytePos, Span}; @@ -79,7 +79,7 @@ pub(crate) fn format_expr( if let Some(expr_rw) = rewrite_literal(context, l, shape) { Some(expr_rw) } else { - if let LitKind::StrRaw(_) = l.token_lit.kind { + if let ast::LitKind::Str(_, ast::StrStyle::Raw(_)) = l.kind { Some(context.snippet(l.span).trim().into()) } else { None @@ -1226,7 +1226,7 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) -> fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -> Option { let span = lit.span; - let symbol = lit.token_lit.symbol.as_str(); + let symbol = lit.symbol.as_str(); if let Some(symbol_stripped) = symbol.strip_prefix("0x") { let hex_lit = match context.config.hex_literal_case() { @@ -1239,9 +1239,7 @@ fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) - format!( "0x{}{}", hex_lit, - lit.token_lit - .suffix - .map_or(String::new(), |s| s.to_string()) + lit.suffix.map_or(String::new(), |s| s.to_string()) ), context.config.max_width(), shape,