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

redundant_closure fix FP on coerced closure #8431

Merged
merged 1 commit into from
Apr 27, 2022
Merged

Conversation

dswij
Copy link
Member

@dswij dswij commented Feb 14, 2022

Closes #8416,
Closes #7812
Closes #8091

Seems like this is fixed in #817 and regressed.

Ignore coerced closure false positives, but this will lead to some false negatives on resolvable generics. IMO, this is still an overall improvement

changelog: [redundant_closure] ignores coerced closure

@rust-highfive
Copy link

r? @flip1995

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Feb 14, 2022
|
LL | let e = Some(1u8).map(|a| divergent(a));
| ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `divergent`

Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like a false negative because map allows a function with any return type but the bug in the example expects a function that returns nothing (or unit). It seems like it should be possible to detect the difference. Maybe there is an expr type adjustment to coerce ! to () on the closure or the function call within the closure. Or maybe you can detect this scenario by comparing call_ty and closure_ty (one of them has -> () and the other has -> !?).

Copy link
Member Author

@dswij dswij Feb 15, 2022

Choose a reason for hiding this comment

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

Ah, I definitely misunderstood the bug in the example. I will take a further look. Thanks!

Copy link
Member Author

@dswij dswij Feb 28, 2022

Choose a reason for hiding this comment

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

Seems like checking for coerced closure is not enough. In the case above, it seems like the closure is coerced to () before being passed on to map (not sure why this is the case, though). AFAIU, in the example above, map accepts divergent nonetheless, probably because of generics. For non-generics, this is not the case and type check wouldn't resolve (hence the problem with issue #8416 and similar, see playground).

Ignoring coerced closures is not hard, but it does produce false negatives such as the case above. Although I'd say that this is still an improvement over all the false positives.

A full solution would be to check if type-check is resolvable for the call/method-call taking Fn(..) -> T without the coerced closure, but I'm not sure that this is trivial to do.

@flip1995 flip1995 added S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Feb 17, 2022
@dswij dswij force-pushed the 8416 branch 3 times, most recently from 929c5f3 to 4f5e96e Compare February 28, 2022 08:04
@dswij dswij changed the title redundant_closure fix FP on Never type redundant_closure fix FP on coerced closure Mar 1, 2022
@flip1995 flip1995 added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties and removed S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels Mar 1, 2022
@bors
Copy link
Collaborator

bors commented Apr 14, 2022

☔ The latest upstream changes (presumably #8676) made this pull request unmergeable. Please resolve the merge conflicts.

@dswij
Copy link
Member Author

dswij commented Apr 15, 2022

Hey @flip1995, I'd love to fix the merge conflicts, but this PR has not seen any activities for some time now.
Is there anything I can do to help this move forward?

@xFrednet
Copy link
Member

We currently sadly have a long reviewing queue and only a few reviewers. That's why stale PRs are sadly not always picked up. That being said, I'll take over the review, my queue is still manageable (If I ignore some university and works stuff xD).

The linked issue contains two references to duplicate issues. Could you add tests and check that they are also fixed? If so, you can add them to the Closed: list in your issue 🙃

r? @xFrednet

@rust-highfive rust-highfive assigned xFrednet and unassigned flip1995 Apr 15, 2022
@@ -145,6 +146,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
);

if_chain!(
if !is_adjusted(cx, &body.value);
Copy link
Member

@xFrednet xFrednet Apr 15, 2022

Choose a reason for hiding this comment

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

I think that is_adjusted is a bit too restrictive. The example cases all are related to the never type. Therefore, I would only suppress the lint if the wrapped function returns the never type, in all other cases it seems like the normal adjustment has worked its magic.

Have you tried the following two options?

  1. Check the return type of the body expression of the closure. The expression might still return the never type if it gets adjusted, but I'm not sure about that.
  2. Otherwise we might have to resolve the referenced function and check what that returns.

Copy link
Member Author

Choose a reason for hiding this comment

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

The example cases all are related to the never type.

The problem is not never type, but it's when the wrapped function can only be resolved by typechecks by adjusting it to return () type.

Check the return type of the body expression of the closure. The expression might still return the never type if it gets adjusted, but I'm not sure about that.

It gets adjusted to () type.

Otherwise we might have to resolve the referenced function and check what that returns.

Yes, the only way that I see for a complete solution is to check if the function typecheck can be resolved to accept the original return type of the closure. I'm not sure this is trivial to do.

Copy link
Member

Choose a reason for hiding this comment

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

The example cases all are related to the never type.

The problem is not never type, but it's when the wrapped function can only be resolved by typechecks by adjusting it to return () type.

Looks like I also misunderstood the issue at first. The type adjustment to () sounds like a quirk of the type checking system.

In that case, I think that your fix is the correct one. It will have some FNs but those are better than FPs IMO. 🙃

@dswij
Copy link
Member Author

dswij commented Apr 17, 2022

We currently sadly have a long reviewing queue and only a few reviewers

Hope the team can get enough bandwidth soon 🙂

@xFrednet
Copy link
Member

xFrednet commented Apr 17, 2022

We currently sadly have a long reviewing queue and only a few reviewers

Hope the team can get enough bandwidth soon slightly_smiling_face

Btw and slightly off topic, I've pinged you on Zulip. Not sure, if that's your preferred method of communication.

I'll put the next review on my todo list 🙃

@xFrednet
Copy link
Member

xFrednet commented Apr 21, 2022

I've looked through our open issues, and believe that this also fixes: #7812 and #8091

Edit: I've already added them to the lint description to r+, before I saw the conflicts :)

@xFrednet
Copy link
Member

xFrednet commented Apr 21, 2022

FYI, for anyone reading this in the future. This fix introduces some false negatives, but we believe that the trade of is worth it. Avoiding these false negatives would take several complicated checks, which also speaks for this solution.

@dswij Thank you for this change and your patience. It's highly appreciated!

Could you rebase one last time? Then you can use bors with r=xFrednet 🙃

@bors delegate+

@xFrednet

This comment was marked as off-topic.

@bors
Copy link
Collaborator

bors commented Apr 21, 2022

✌️ @dswij can now approve this pull request

@giraffate
Copy link
Contributor

@dswij Can you resolve the conflicts?

@dswij
Copy link
Member Author

dswij commented Apr 27, 2022

@bors r=xFrednet

@bors
Copy link
Collaborator

bors commented Apr 27, 2022

📌 Commit 33bf9e9 has been approved by xFrednet

@bors
Copy link
Collaborator

bors commented Apr 27, 2022

⌛ Testing commit 33bf9e9 with merge d5c62fd...

@bors
Copy link
Collaborator

bors commented Apr 27, 2022

☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test
Approved by: xFrednet
Pushing d5c62fd to master...

@bors bors merged commit d5c62fd into rust-lang:master Apr 27, 2022
@dswij dswij deleted the 8416 branch April 27, 2022 11:50
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
7 participants