Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unnecessary_debug_formatting lint #13893

Merged
merged 1 commit into from
Feb 26, 2025

Conversation

smoelius
Copy link
Contributor

Fixes #12674, i.e., adds a lint to flag Paths printed with {:?}.

Nits are welcome.

changelog: Add unnecessary_debug_formatting lint

@rustbot
Copy link
Collaborator

rustbot commented Dec 29, 2024

r? @blyxyas

rustbot has assigned @blyxyas.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Dec 29, 2024
@smoelius
Copy link
Contributor Author

cc: @kornelski

@smoelius smoelius force-pushed the unnecessary-debug-formatting branch from 8a7ccf4 to 4e1cad1 Compare December 29, 2024 11:44
@smoelius
Copy link
Contributor Author

@blyxyas Sorry for the CI failures and the force push. But I think the lint should be good now.

Copy link
Member

@blyxyas blyxyas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great first patch!

#[clippy::version = "1.85.0"]
pub UNNECESSARY_DEBUG_FORMATTING,
restriction,
"`Debug` formatting applied to an `OsStr` or `Path`"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"`Debug` formatting applied to an `OsStr` or `Path`"
"`Debug` formatting applied to an `OsStr` or `Path` when `.display()` is available."

/// ```
#[clippy::version = "1.85.0"]
pub UNNECESSARY_DEBUG_FORMATTING,
restriction,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this would fit better into pedantic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered this. But I was concerned there could be legitimate reasons to print a path with debug formatting, and that having to allow them could get annoying.

I'll change it if you feel strongly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be better in pedantic.

This isn't a subjective restriction, but future-proofing for a feature that can disable Debug entirely, and a warning that Rust never promised any stable syntax of the Debug format. I've seen a couple of libraries assume the Debug format is a correct serialization of paths into Rust string syntax, which it is not, and it breaks on non-UTF-8.

So it is pedantically warning about edge cases that may affect all programs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I'll change it.

@@ -439,6 +478,24 @@ impl FormatArgsExpr<'_, '_> {
}
}

fn check_unnecessary_debug_formatting(&self, name: Symbol, value: &Expr<'_>) {
let cx = self.cx;
if !value.span.from_expansion()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also check for procedural macros? Usually new lints want to make sure we aren't linting in those cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Frankly, I'm not sure, though I don't think it would hurt.

You mention "new lints" but are there larger guidelines for when is_from_proc_macro should be used?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, everywhere. There are not many lints that we want to lint in procedural macros. Proc macros are outside of the user's control and could produce any arbitrary output based on any arbitrary input.

For example, a while back we had an issue that a clap procedural macro produced let _ = _, Clippy warned about that and the user was confused because there was nothing they could do apart from reporting it to either Clap or Clippy. I'm not sure if there's a case that we want to explicitly lint in procedural macros.

// Even if `ty` is not in `self.ty_feature_map`, check whether `ty` implements `Deref` with with a
// `Target` that is in `self.ty_feature_map`.
if let Some(deref_trait_id) = self.cx.tcx.lang_items().deref_trait()
&& let Some(target_ty) = self.cx.get_associated_type(ty, deref_trait_id, "Target")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to check that ty implements Deref before calling this function (this would save us a lot of work, as there are not a lot of types that implement Deref after a .peel_refs().)

Comment on lines 33 to 40
println!("{:?}", path);
println!("{:?}", path_buf);

let _: String = format!("{:?}", path);
let _: String = format!("{:?}", path_buf);

let deref_path = DerefPath { path };
println!("{:?}", &*deref_path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
println!("{:?}", path);
println!("{:?}", path_buf);
let _: String = format!("{:?}", path);
let _: String = format!("{:?}", path_buf);
let deref_path = DerefPath { path };
println!("{:?}", &*deref_path);
println!("{:?}", path); //~ unnecessary_debug_formatting
println!("{:?}", path_buf); //~ unnecessary_debug_formatting
let _: String = format!("{:?}", path); //~ unnecessary_debug_formatting
let _: String = format!("{:?}", path_buf); //~ unnecessary_debug_formatting
let deref_path = DerefPath { path };
println!("{:?}", &*deref_path); //~ unnecessary_debug_formatting

Comment on lines 15 to 19
println!("{:?}", os_str);
println!("{:?}", os_string);

let _: String = format!("{:?}", os_str);
let _: String = format!("{:?}", os_string);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
println!("{:?}", os_str);
println!("{:?}", os_string);
let _: String = format!("{:?}", os_str);
let _: String = format!("{:?}", os_string);
println!("{:?}", os_str); //~ unnecessary_debug_formatting
println!("{:?}", os_string); //~ unnecessary_debug_formatting
let _: String = format!("{:?}", os_str); //~ unnecessary_debug_formatting
let _: String = format!("{:?}", os_string); //~ unnecessary_debug_formatting

@smoelius
Copy link
Contributor Author

@blyxyas I think I have addressed all of your comments thus far.


// positive tests
println!("{:?}", path); //~ unnecessary_debug_formatting
println!("{:?}", path_buf); //~ unnecessary_debug_formatting
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add an inline format test as well?

    println!("{path_buf:?}"); //~ unnecessary_debug_formatting

(ditto for OsStr)

@blyxyas
Copy link
Member

blyxyas commented Feb 5, 2025

Here's the FCP: https://rust-lang.zulipchat.com/#narrow/channel/257328-clippy/topic/FCP.3A.20unnecessary_debug_formatting

Alexendoo says: It should definitely note that there is a difference in the output.

I agree, we should probably mention that there may be a difference between outputs. (Although in version 1.85 there is not)

@Alexendoo
Copy link
Member

I agree, we should probably mention that there may be a difference between outputs. (Although in version 1.85 there is not)

I don't think anything changed in 1.85, Debug escapes various characters including ' which is not uncommon in paths, it also adds double quotes where .display() does not

While Debug's format is not stable it is documented as escaping the path in .display(), plus it's unlikely the wrapping "" would be removed

@smoelius
Copy link
Contributor Author

smoelius commented Feb 5, 2025

I'm proposing to add this text to the description:

Note that switching from Debug formatting to Display formatting will change how the OsStr or Path is shown. Escaped characters will no longer be escaped, and enclosing quotes ("...") will be removed.

Does this sound okay?

Where would you add this, under "Why is this bad?"?

EDIT: Added.

@Alexendoo
Copy link
Member

I was thinking to add a diagnostic note

For the Why is this bad? angle you could phrase it from the perspective of not being able copy/paste a path correctly or click it in an integrated terminal if the characters are escaped

@smoelius
Copy link
Contributor Author

smoelius commented Feb 6, 2025

I was thinking to add a diagnostic note

For the Why is this bad? angle you could phrase it from the perspective of not being able copy/paste a path correctly or click it in an integrated terminal if the characters are escaped

I'll make both changes.

@smoelius
Copy link
Contributor Author

smoelius commented Feb 7, 2025

@Alexendoo Please tell me if what I pushed is not what you had in mind.

Copy link
Member

@blyxyas blyxyas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay, I was waiting for Alex's input on the change but taking a look at it I think it's very agreeable.
LGTM, thanks! ❤️ Could you change the version to reflect the new current version and squash all commits?

@smoelius smoelius force-pushed the unnecessary-debug-formatting branch from d5bdce7 to d467273 Compare February 26, 2025 01:16
@smoelius
Copy link
Contributor Author

Sorry for the delay, I was waiting for Alex's input on the change but taking a look at it I think it's very agreeable. LGTM, thanks! ❤️ Could you change the version to reflect the new current version and squash all commits?

No worries at all. Please let me know if there's a Clippy version I missed. And thank you for the review. 🙏

/// let path = Path::new("…");
/// println!("The path is {}", path.display());
/// ```
#[clippy::version = "1.86.0"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decide the rust version for new Clippy lints by viewing the output of rustc -Vv in master 👀
This should be 1.87.0 🐱

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. Sorry.

@Alexendoo
Copy link
Member

Ah sorry, I thought I had replied to this thread

Yeah, LGTM

Address review comments

Fix adjacent code

Required now that the lint is pedantic

Add inline formatting tests

Add note re formatting changes

Address `unnecessary_map_or` warnings

Address additional review comments

Typo

Update Clippy version
@smoelius smoelius force-pushed the unnecessary-debug-formatting branch from d467273 to 6af901c Compare February 26, 2025 14:26
Copy link
Member

@blyxyas blyxyas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks! ❤️

@blyxyas blyxyas added this pull request to the merge queue Feb 26, 2025
Merged via the queue into rust-lang:master with commit b583568 Feb 26, 2025
11 checks passed
@smoelius smoelius deleted the unnecessary-debug-formatting branch February 26, 2025 18:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Paths printed with {:?} instead of .display()
6 participants