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

discarded_futures lint discussion #59887

Open
FMorschel opened this issue Jan 11, 2025 · 4 comments
Open

discarded_futures lint discussion #59887

FMorschel opened this issue Jan 11, 2025 · 4 comments
Labels
area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. type-question A question about expected behavior or functionality

Comments

@FMorschel
Copy link
Contributor

After some discussion over at #59877, #59331 and #58747, I've seen many users expecting discarded_futures to work similarly to unawaited_futures but inside synchronous code.

That is, inside synchronous code, if the Future is assigned to something that explicitly asks for a Future, do nothing, if not, trigger.

That would solve all of these duplicates that expect the lint not to warn when using it on FutureBuilder from Flutter for example:

Making the behaviour match unawaited_futures would also probably fix: #59204.

I've opened https://dart-review.googlesource.com/c/sdk/+/403901 and I've made some changes to address this assignability issue, but @lrhn commented on the CL:

There is no change to the description, documentation or specification of this lint, but a significant change to its behavior.
(As much as a specification exists.)

Among my many beefs with this lint is that its name, description and behavior seem to be three different things. I can't tell if this change makes that better or worse.

The name is "discarded_futures". It's description (the line above and the text at https://dart.dev/tools/linter-rules/discarded_futures) is very clear that it really means "don't call async functions in non-async code".

The implementation seems to refer to the unawaited function in some places, which is not mentioned in the description, and isn't relevant to the specified behavior, so the implementation is either a third thing, or maybe it matches the title better than the description does. (But not well. The unawaited_futures lint doesn't mention the unawaited function it the code. It doesn't have to.)

I'm all for changing the specification and behavior of this lint, because "don't call async functions in non-async code" is a rule I break all the time (I know how to use Future.then). It's not a good lint as specified.

This change seems to try to move it closer to the behavior of unawaited_futures, which is about not leaving a Future unawaited by accident.
That lint understands, I think, that passing a Future as an argument to a parameter of type Future or FutureOr is a way of handling that future.

If this lint was to be changed, I'd probably want to change it to the exact same behavior as unawaited_futures, just in a non-async function (and therefore without the ability to use await). That is, don't throw away a future, which means boils down to to not use an expression with type Future (maybe also FutureOr) in a context that isn't typed as Future or FutureOr. It being a future is lost whether the context is Object or void.

Then unawaited(someFuture) just works because someFuture is in a Future<void> context, and unawaited(someFuture) has type void.

All this special-casing of when it's OK to have a future feels like overkill.
It's OK to have a future in a place where a future is expected, anything else won't know to treat > it as a future.

I'm opening this issue to track this discussion and hopefully to make that change.

// CC @lrhn @pq

@FMorschel FMorschel added the area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. label Jan 11, 2025
@FMorschel
Copy link
Contributor Author

Just to keep things in one place. The current CL fixes all of the above issues. I'll read through https://gist.github.com/lrhn/0316c1c6c5102dc900d635d08ec31188 and see if there is any missing test here.

I'll also address to the linter/analyzer team the following question:

With the current changes, if the Future is assigned to an explicit Future, we won't trigger the lint. If it is a variable assignment and the variable is unused, I'd expect the unused_local_variable to trigger. I'd expect that to be enough to tell the user this is still not handled. Do you agree? Should we do something (with this lint) in this case still?

@bwilkerson bwilkerson added the type-question A question about expected behavior or functionality label Jan 21, 2025
@FMorschel
Copy link
Contributor Author

One more issue that is a duplicate from the list above #59949.

@FMorschel
Copy link
Contributor Author

To note:

  • This being done this way (as described above) will have some conflicts with omit_local_variable_types and related lints when it asks for an explicit Future cast.

  • One new issue came up recently ([linter][discarded_futures] false positive #59949) asking for special casing for variable assignments, saying any assignment should be considered handling. I'm unsure I agree or disagree.

I'd appreciate some inputs here @pq.

@pq
Copy link
Member

pq commented Jan 23, 2025

My quick 2 cents:

This being done this way (as described above) will have some conflicts with omit_local_variable_types and related lints when it asks for an explicit Future cast.

My gut says if this route is considered valuable we could explore updating omit_local_variable_types to not flag these cases iff discard_futures is enabled. That's a little unfortunate but I think OK.

One new issue came up recently (#59949) asking for special casing for variable assignments, saying any assignment should be considered handling. I'm unsure I agree or disagree.

I'm not sure either. I'd be curious, in practice, if this happens a lot. The downside to a blanket special-case is that we may miss flagging unintended behavior. I wonder if a more principled approach might be something along the lines of function-side opt outs as discussed for unawaited_futures in #58348.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. type-question A question about expected behavior or functionality
Projects
None yet
Development

No branches or pull requests

3 participants