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

[Proposal] Remove CheckReturnValue on subscribe() overloads #6304

Closed

Conversation

ZacSweers
Copy link
Contributor

@ZacSweers ZacSweers commented Nov 12, 2018

Proposal PR for my followup comment in #4878 (comment)

Will close if the discussion raised there still settles on keeping them, just wanted to show a PoC of what the change scope would look like for reference.

Copy link
Collaborator

@vanniktech vanniktech left a comment

Choose a reason for hiding this comment

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

I'd keep the annotation and in the rare cases suppress the warning. This annotation saved me more times than it harmed me.

@ZacSweers
Copy link
Contributor Author

Maybe you, but see the thread for plenty more cases where it's not useful :). Let's keep the discussion consolidated there

@akarnokd
Copy link
Member

This was discussed before. The no arg subscribe doesn't have it as being fire and forget, the rest do.

@ZacSweers
Copy link
Contributor Author

That's not true actually

Observable#subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete, Consumer<? super Disposable> onSubscribe)

also requires it despite accepting an onSubscribe Consumer, and presumably that shouldn't require it by that logic either since a handling consumer is passed in. I understand it was discussed before, but I feel I've offered a good set of examples in the linked issue that highlight where the original reasoning has not accounted for.

@akarnokd
Copy link
Member

akarnokd commented Nov 12, 2018

also requires it despite accepting an onSubscribe Consumer

It is to be removed in 3.x: #5622

Also the issue here is a general conflict between one's individual coding style and the hard coded coding style of a library. So you either ignore warnings individually as Jake suggested or create a separate subscribe method/converter in your project where you can ignore it once.

@ZacSweers
Copy link
Contributor Author

or create a separate subscribe method/converter in your project where you can ignore it once.

This seems like a really harsh stance to take :/. Any specific thoughts on the examples I raised?

@vanniktech
Copy link
Collaborator

Talked with Zac offline and I understand his points now. We both have different valid ways of using RxJava and the annotation is a constraint that should not be enforced per se.

I'd be willing to give up the annotation if we have proper open source toolings like Zac suggested that simulate the old behavior.

@ZacSweers
Copy link
Contributor Author

And I'd be happy to contribute implementations (in existing or new projects) for error-prone and lint as a part of this :)

@akarnokd
Copy link
Member

This should have been part of some tooling all along, but then the lack of warnings out-of-box received by newcommers and beginners would have resulted in a lot of support requests. By the way, if tooling is created for this, it could have both the feature to add as well as remove via configuration for the entire project.

@artem-zinnatullin
Copy link
Contributor

my 2 cents: RxJava uses its own annotation for this, which means that it should be possible to disable it project (module) -wide without clashing with @CheckReturnValues enforced by other libraries.

Thus, I'd rather keep it as is in RxJava (because there is value in it) and focus on tooling support for disabling such specific annotations.

@vanniktech
Copy link
Collaborator

I think for Android Lint this might actually already be doable. For each issue there can be a regex defined. Might be enough to pass in the fully qualified name of the annotation.

@ZacSweers
Copy link
Contributor Author

A custom annotation for this would work, but we'd probably have to deprecate the existing one vs. remove it since it's part of the public API right?

@vanniktech have a link/sample? I didn't know that was an option!

@akarnokd when you say

it could have both the feature to add as well as remove via configuration for the entire project.

Could you elaborate a bit? I'm not sure I followed

@akarnokd
Copy link
Member

I meant like a config file:

@CheckReturnValue
+ io.reactivex.Flowable.subscribe()
- io.reactivex.Flowable.subscribe(io.reactivex.function.Consumer<? super T>)

Some tooling would check this file and apply the annotation virtually to the given method signature or ignore it.

@vanniktech
Copy link
Collaborator

Something like that might work (haven't tried it out myself):

<?xml version="1.0" encoding="UTF-8"?>
<lint>
  <issue id="CheckResult">
    <ignore regexp="io.reactivex.annotations.CheckReturnValue"/>
  </issue>
</lint>

@ZacSweers
Copy link
Contributor Author

Let me see if ErrorProne's check allows for this. Unfortunately neither case covers the actual IDE tooling marking these (they don't read lint xml configurations and the intelliJ inspection doesn't support customization as far as I know)

@vanniktech
Copy link
Collaborator

they don't read lint xml configurations and the intelliJ inspection doesn't support customization as far as I know

I'm sure this can be fixed. Just like custom lint checks got fixed with 3.3

@ZacSweers
Copy link
Contributor Author

Maybe. That was a bug and this would be a FR :). lint xml files are entirely a CLI implementation, and not part of the main lint API that the CLI and IDE plugins both implement

@ZacSweers
Copy link
Contributor Author

Followup on error-prone - confirmed there's no way to configure this right now. I don't think focusing on disabling in other tooling is the right way to go about this, as it's much easier to enable custom tooling than it is to disable non-configurable existing tooling.

@artem-zinnatullin
Copy link
Contributor

One (me) could argue that changing a default behavior and requiring everyone who relies on it to reconfigure their tooling is also not great and hardly considerable as much easier :)

@ZacSweers
Copy link
Contributor Author

ZacSweers commented Nov 16, 2018 via email

@vanniktech
Copy link
Collaborator

lint xml files are entirely a CLI implementation, and not part of the main lint API that the CLI and IDE plugins both implement

IntelliJ could read the lintConfig file from android { lintOptions { .. } }. Not seeing a problem with that

@ZacSweers
Copy link
Contributor Author

The problem is that's a significant feature request for functionality that doesn't exist today right?

@vanniktech
Copy link
Collaborator

Maybe. Maybe not. It's worth asking for nonetheless ;) - https://issuetracker.google.com/issues/119660763

@ZacSweers
Copy link
Contributor Author

Even then, that still marries it to gradle android projects right?

@vanniktech
Copy link
Collaborator

Probably yeah. Unless they find some universal way which would also work with other build systems. Feel free to suggest that in the issue since I'm only using Gradle.

@ZacSweers
Copy link
Contributor Author

Yeah I think that's a good thing to file in general, but as a separate async thing. Mind if we continue with using a renamed annotation for rx?

@vanniktech
Copy link
Collaborator

Yeah I'm in for having both (proper tooling support) and new tooling to flag this.

You want to rename it so standard tools don't know the name and hence don't flag it, right? Custom checks like you proposed would read it then.

@ZacSweers
Copy link
Contributor Author

Yeah rename, though we'd have to add a separate new one (and deprecate the existing one?) since it's part of the public API up to this point. Also - what should we call it? PossiblyCheckReturnValue? RxCheckReturnValue?

@vanniktech
Copy link
Collaborator

I guess yeah but then in the end tools still need a way to exclude the current annotation since we can't remove it, right?

@ZacSweers
Copy link
Contributor Author

Oh no I meant you can't delete the class. You can still remove it from the methods. I was as a actually thinking it's fine in it's other uses, and maybe just make a custom 2nd one for like CheckDisposableReturnValue

@vanniktech
Copy link
Collaborator

Sounds like a good tradeoff.

@ZacSweers ZacSweers force-pushed the z/remoteCheckReturnValueAnnotations branch from aa3f961 to ced572d Compare November 20, 2018 07:16
@codecov
Copy link

codecov bot commented Nov 20, 2018

Codecov Report

Merging #6304 into 2.x will decrease coverage by 0.04%.
The diff coverage is n/a.

Impacted file tree graph

@@             Coverage Diff              @@
##                2.x    #6304      +/-   ##
============================================
- Coverage     98.26%   98.22%   -0.05%     
+ Complexity     6284     6283       -1     
============================================
  Files           672      672              
  Lines         44992    44992              
  Branches       6223     6223              
============================================
- Hits          44212    44193      -19     
- Misses          244      255      +11     
- Partials        536      544       +8
Impacted Files Coverage Δ Complexity Δ
src/main/java/io/reactivex/Flowable.java 100% <ø> (ø) 567 <0> (ø) ⬇️
src/main/java/io/reactivex/Maybe.java 100% <ø> (ø) 172 <0> (ø) ⬇️
src/main/java/io/reactivex/Completable.java 100% <ø> (ø) 120 <0> (ø) ⬇️
src/main/java/io/reactivex/Observable.java 100% <ø> (ø) 542 <0> (ø) ⬇️
src/main/java/io/reactivex/Single.java 100% <ø> (ø) 148 <0> (ø) ⬇️
...rnal/operators/flowable/FlowableFlatMapSingle.java 92.93% <0%> (-3.81%) 2% <0%> (ø)
...ternal/operators/observable/ObservablePublish.java 94.69% <0%> (-3.54%) 11% <0%> (ø)
...ava/io/reactivex/processors/BehaviorProcessor.java 96.86% <0%> (-2.25%) 60% <0%> (ø)
.../io/reactivex/disposables/CompositeDisposable.java 98.14% <0%> (-1.86%) 39% <0%> (-1%)
...ternal/operators/flowable/FlowableSubscribeOn.java 96.61% <0%> (-1.7%) 2% <0%> (ø)
... and 29 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ac3b5b1...ced572d. Read the comment docs.

@ZacSweers
Copy link
Contributor Author

Rebased and switched over to a OptionalCheckReturnValue. Let me know if that works?

Copy link
Collaborator

@vanniktech vanniktech left a comment

Choose a reason for hiding this comment

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

It would. I'd like to see the tooling in place before we merge this though.

@ZacSweers
Copy link
Contributor Author

I'll create a project for that now 👍

@vanniktech
Copy link
Collaborator

You might have the possibility to reuse the existing Detector by creating your own and registering the new annotation and from there forward everything to the CheckResultDetector. That way you wouldn't need to duplicate all of the work.

I've also filed https://issuetracker.google.com/issues/119763072 - dunno if that's something they are willing to do though.

@ZacSweers
Copy link
Contributor Author

I've created a project with working checkers for both here: https://github.com/hzsweers/rxjava2-optionalcheckreturnvalue-checkers

Going to try to get review from @vanniktech and a couple others separately, but they're mostly straightforward adaptation of existing checkers just for this new annotation

@vanniktech
Copy link
Collaborator

Lint implementation looks good!

@JakeWharton
Copy link
Contributor

Still opposed to this. Makes the common case worse for the benefit of the uncommon case.

@ZacSweers
Copy link
Contributor Author

ZacSweers commented Nov 23, 2018

Counterexample: RxLifecycle is nigh-ubiquitous in Android apps and negatively affected by this (since lifecycle handling is handled via upstream takeUntil), would that still be considered an uncommon case?

@JakeWharton
Copy link
Contributor

JakeWharton commented Nov 23, 2018 via email

@ZacSweers
Copy link
Contributor Author

Maybe! Unfortunately neither of us can prove that one way or the other. What about any of the other cases I mentioned in #4878 (comment)? Especially considering RxJava is synchronous by default, it seems to me like there's quite a few "uncommon" cases. Maybe not enough to be "common", but it gets to a larger point of when static analysis tools should be imposed.

To me, hard checks like this should only be imposed in black-and-white situations, like a factory or cases where it's otherwise pointless to call that method without capturing the result. This seems far from black-and-white. On top of that, it's a check that's not configurable in any built-in error-prone/lint tooling (it's even hardcoded into lint today) that would otherwise enforce it.

I think I have an alternative idea, but I'd like to get thoughts on the above first

@ZacSweers ZacSweers closed this Dec 3, 2018
@ZacSweers ZacSweers deleted the z/remoteCheckReturnValueAnnotations branch December 3, 2018 03:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants