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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

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

Required now that the lint is pedantic
@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)

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()
5 participants