Skip to content

WIP: New lint: needless_path_new #14895

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

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

Conversation

ada4a
Copy link
Contributor

@ada4a ada4a commented May 25, 2025

fs::read_to_string(Path::new("foo.txt")) -> fs::read_to_string("foo.txt")

The commit history of this might be a bit messy -- it took me some time to figure this lint out. I cleaned it up a bit, but it's still not perfect

Fixes #14668

changelog: [needless_path_new]: new lint

WIP because:

  • it was suggested on Zulip to look into using trait obligations for impl AsRef<Path>. Later comments seem to not quite agree? As I said on Zulip, I don't know what these obligations are all about, so let me know if you think I should look into them (I'd appreciate some help as well)
  • I know that all the descriptions for this lint are pretty verbose -- I think its purpose is just hard to describe succintly. That would've been easier originally, since I thought the lint would apply only to strings enclosed in Path::new, but that was pretty easy to expand to "any impl AsRef<Path>", so I did that.

@rustbot
Copy link
Collaborator

rustbot commented May 25, 2025

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 May 25, 2025
Comment on lines +76 to +77
name: &str,
fn_kind: &str,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

these two arguments are what makes the CI fail currently, since they are unused. I got them when copy-pasting from mut_reference, and I haven't removed them (yet) because I thought I could use them to give a better warning message. Something like:

format!("the {fn_kind} {name} accepts `AsRef<Path>`, \
and {x} implements that trait, so wrapping it in `Path::new` is unnecessary")

If you think it makes sense to have the message, I'd add it in -- otherwise I'd just remove these arguments

ada4a added 3 commits May 26, 2025 01:50
it was recommended on Zulip to keep the check, so do that and give the
motivation for having it
apparently a common thing to do? definitely reduces verbosity

fn check_arguments<'tcx>(
cx: &LateContext<'tcx>,
arguments: &mut dyn Iterator<Item = &'tcx Expr<'tcx>>,
Copy link
Contributor Author

@ada4a ada4a May 26, 2025

Choose a reason for hiding this comment

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

I have this function signature from mut_reference -- should I maybe replace the dyn with impl here?

@samueltardieu
Copy link
Contributor

samueltardieu commented May 27, 2025

I think you need to check that you can use a AsRef<Path>, otherwise you might suggest removing Path::new() while you really need a &Path.

Don't forget to look at the lintcheck logs for your PR. You'll see the first hit is probably wrong, as it requires building a Option<&Path>, not a Option<dyn AsRef<Path>>.

@ada4a
Copy link
Contributor Author

ada4a commented May 27, 2025

Don't forget to look at the lintcheck logs for your PR.

oh, didn't know about that! thank you, that's very helpful

I think you need to check that you can use a AsRef<Path>, otherwise you might suggest removing Path::new() while you really need a &Path.

You'll see the first hit [in lintcheck] is probably wrong, as it requires building a Option<&Path>, not a Option<dyn AsRef<Path>>.

I thought I already covered that with the following line:

&& implements_asref_path(*parameter)

I even have a test case for exactly this!

// no warning
fn takes_path(_: &Path) {}
takes_path(Path::new("foo"));

But now that I think about it, the check above doesn't actually work?... It just checks that whatever type parameter has itself implements AsRef<Path>, and that is the case for Path. I wonder why the test even works in that case... Maybe something to do with Path vs &Path?

I guess what I need to check instead is that parameter is impl AsRef<Path>. is_type_diagnostic_item seems to be closest to what I want, but it wouldn't include the impl part? Btw that makes me wonder if I should check for dyn AsRef<Path> as well

@ada4a
Copy link
Contributor Author

ada4a commented May 27, 2025

But the weirdest thing is that Some(..) is not even a fucntion/method call?... The lint is supposed to only check expressions that are ExprKind::Call or ExprKind::MethodCall -- but maybe the former actually includes anything of the form foo(bar)?...

EDIT: indeed it does. but I guess this is not actually the root cause of the problem, so we could keep it? Maybe the function/method restriction should not even be necessary, maybe we should just check that the place the expression is in requires an impl AsRef<Path>, be that place a parameter in a function call, or e.g. a RHS of an assignment, like

let _: Option<impl AsRef<Path>>: Some(Path::new("foo.txt"));

(assuming impl Trait in this position would be valid, but this is just an example)

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.

New lint: needless Path::new
4 participants