Skip to content

Commit

Permalink
Auto merge of rust-lang#10573 - Alexendoo:print-literal-file-macro, r…
Browse files Browse the repository at this point in the history
…=Jarcho

Ignore `file!()` macro in `print_literal`, `write_literal`

changelog: [`print_literal`], [`write_literal`]: Ignore the `file!()` macro

`file!()` expands to a string literal with its span set to that of the `file!()` callsite, but isn't marked as coming from an expansion. To fix this we make sure we actually find a string/char literal instead of assuming it's one and slicing

It would also ignore any other macros that result in the same situation, but that shouldn't be common as `proc_macro::Span::call_site()` returns a span that is marked as from expansion

Fixes rust-lang#10544
  • Loading branch information
bors committed Mar 30, 2023
2 parents 799732c + 17f8045 commit d43714a
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 5 deletions.
14 changes: 10 additions & 4 deletions clippy_lints/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,12 +463,18 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
&& let Some(value_string) = snippet_opt(cx, arg.expr.span)
{
let (replacement, replace_raw) = match lit.kind {
LitKind::Str | LitKind::StrRaw(_) => extract_str_literal(&value_string),
LitKind::Str | LitKind::StrRaw(_) => match extract_str_literal(&value_string) {
Some(extracted) => extracted,
None => return,
},
LitKind::Char => (
match lit.symbol.as_str() {
"\"" => "\\\"",
"\\'" => "'",
_ => &value_string[1..value_string.len() - 1],
_ => match value_string.strip_prefix('\'').and_then(|s| s.strip_suffix('\'')) {
Some(stripped) => stripped,
None => return,
},
}
.to_string(),
false,
Expand Down Expand Up @@ -533,13 +539,13 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
/// `r#"a"#` -> (`a`, true)
///
/// `"b"` -> (`b`, false)
fn extract_str_literal(literal: &str) -> (String, bool) {
fn extract_str_literal(literal: &str) -> Option<(String, bool)> {
let (literal, raw) = match literal.strip_prefix('r') {
Some(stripped) => (stripped.trim_matches('#'), true),
None => (literal, false),
};

(literal[1..literal.len() - 1].to_string(), raw)
Some((literal.strip_prefix('"')?.strip_suffix('"')?.to_string(), raw))
}

enum UnescapeErr {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/auxiliary/proc_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn group_with_span(delimiter: Delimiter, stream: TokenStream, span: Span) -> Gro
/// Token used to escape the following token from the macro's span rules.
const ESCAPE_CHAR: char = '$';

/// Takes a single token followed by a sequence tokens. Returns the sequence of tokens with their
/// Takes a single token followed by a sequence of tokens. Returns the sequence of tokens with their
/// span set to that of the first token. Tokens may be escaped with either `#ident` or `#(tokens)`.
#[proc_macro]
pub fn with_span(input: TokenStream) -> TokenStream {
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/print_literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,8 @@ fn main() {
// named args shouldn't change anything either
println!("{foo} {bar}", foo = "hello", bar = "world");
println!("{bar} {foo}", foo = "hello", bar = "world");

// The string literal from `file!()` has a callsite span that isn't marked as coming from an
// expansion
println!("file: {}", file!());
}

0 comments on commit d43714a

Please sign in to comment.