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

fix [infinite_loop] suggestions on async funtion/closure #12421

Closed
wants to merge 3 commits into from

Conversation

J-ZhengLi
Copy link
Member

fixes: #12338


changelog: fix [infinite_loop] suggestions on async funtion/closure

@rustbot
Copy link
Collaborator

rustbot commented Mar 5, 2024

r? @Jarcho

rustbot has assigned @Jarcho.
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 Mar 5, 2024
@J-ZhengLi
Copy link
Member Author

I have split the changes into 2 commits, the second one is not related to the issue, but it's something I realized when fixing it, it basically treats the explicite () return as a DefaultReturn and offers suggestion as well. If it turns out not needed (because there's a lint [unused_init] exist to fix that), I can just modify the second commit easily.

@J-ZhengLi
Copy link
Member Author

Hmmmm, a fairly familiar looking PR waiting to be triaged...

Hey @Jarcho, do you have time to review this pile of spaghetti code 😆? You can assign someone else to do it if you don't wanna do it yourself, and I totally understand that~

Comment on lines 156 to 174
struct BindingVisitor<'tcx> {
res: Option<Ty<'tcx>>,
}
impl<'tcx> Visitor<'tcx> for BindingVisitor<'tcx> {
fn visit_assoc_type_binding(&mut self, type_binding: &'tcx hir::TypeBinding<'tcx>) {
if self.res.is_some() {
return;
}
if let hir::TypeBindingKind::Equality {
term: hir::Term::Ty(ty),
} = type_binding.kind
{
self.res = Some(*ty);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Visitors can return ControlFlow by setting type ResultTy = ControlFlow<T>

Copy link
Member Author

Choose a reason for hiding this comment

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

I tried use this for the other visitor here as well, but sadly it doesn't work, I'm assuming it's somehow "conflicting" with those walk_expr calls?

Copy link
Contributor

Choose a reason for hiding this comment

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

It would work there. walk_expr has the same return type as visit_expr. If you really want to clean that part up you can get rid the label and loop depth tracking. Destination::target_id will always hold the HirId of the loop expression or block it's targeting.

Copy link
Member Author

Choose a reason for hiding this comment

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

after trying out your suggestion, I think the depth tracking is somehow needed in this case below right?

'outer: loop {
    loop {
        if cond {
            break 'outer;
        }
    }
}

'outer loop can be identified as finite when visitor sees the break with a matching target_id. However during the second iteration, the original logic assumes the break 'outer was breaking the current loop because the "depth" was 0.

if self.loop_depth == 0 || has_same_label() {
    self.is_finite = true;
}

Without the depth tracking I can't think of any better way to eliminate this FP, so I'm guessing it should be safe to assume that way?

Copy link
Contributor

Choose a reason for hiding this comment

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

A small change to the example causes the current version to not work:

'outer: loop {
    loop {
        if cond {
            loop {
                break 'outer;
            }
        }
    }
}

The correct implementation would track the HirId of every loop and targeted block contained in the checked loop.


If you want to fix this feel free, otherwise leave the current code.


// Since `item_id` is from a `TyKind::OpaqueDef`,
// the `Item` related to it should always be `OpaqueTy`.
assert!(matches!(opaque_ty_item.kind, ItemKind::OpaqueTy(_)));
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason this assert is here? An ICE isn't exactly a great outcome if it's wrong.

Copy link
Member Author

@J-ZhengLi J-ZhengLi Jun 11, 2024

Choose a reason for hiding this comment

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

hmmm, right, I guess I was being overly confident 😂. Should've be more careful with it, I'll change it~

Comment on lines 201 to 202
let Self::Return(ty) = self else { return false };
matches!(ty.kind, TyKind::Never)
Copy link
Contributor

Choose a reason for hiding this comment

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

Could be matches!(self, Self::Return(ty) if ty.is_never()).

Copy link
Member Author

Choose a reason for hiding this comment

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

ah, that's an hir::Ty, so there's no is_never calls, but I got what you mean, thanks

@J-ZhengLi J-ZhengLi force-pushed the issue12338 branch 2 times, most recently from 88ea1b7 to fc78fde Compare June 26, 2024 01:59
@Jarcho
Copy link
Contributor

Jarcho commented Jul 14, 2024

If you want to clean up the other visitor feel free. Otherwise I'll merge it as is.

@J-ZhengLi
Copy link
Member Author

J-ZhengLi commented Jul 15, 2024

thanks for your time reviewing this~

If you want to clean up the other visitor feel free. Otherwise I'll merge it as is.

I'll try cleaning that up, but I'll be kinda busy for the up coming month so if I didn't post any progress by tomorrow, could you merge it as is? 😄

@J-ZhengLi J-ZhengLi force-pushed the issue12338 branch 2 times, most recently from 3867e00 to fc78fde Compare July 15, 2024 17:04
@bors
Copy link
Contributor

bors commented Sep 22, 2024

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

@AlexSherbinin
Copy link

Any changes on fixing this?

@J-ZhengLi
Copy link
Member Author

Any changes on fixing this?

apologies for the long wait, seems like I got stuck on trying to fix this comment #12421 (comment) which doesn't seems to be related to your issue, then I forgot about this pr's existence ...

I'm splitting this PR now, sorry~

@J-ZhengLi
Copy link
Member Author

closing for now in favor of #13608.

@J-ZhengLi J-ZhengLi closed this Oct 26, 2024
bors added a commit that referenced this pull request Nov 1, 2024
[`infinite_loops`]: fix incorrect suggestions on async functions/closures

closes: #12338

I intend to fix this in #12421 but got distracted by some other problems in the same lint, delaying the process of closing the actual issue. So here's a separated PR that only focus on the issue and nothing else.

---

changelog: [`infinite_loops`]: fix suggestion error on async functions/closures
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.

Incorrect infinite loop detection in async functions
6 participants