I believe we should update a contribution doc on this, since now it’s confusing 
 - you run “./gradlew :your:task:check” and it’s fine but then it fails on CI 
because of some missed Nullable checks.

Also, I noticed that “checkNotNull(yourVar)” or "checkState(yourVar != null)” 
won’t help, it will still complain. Only explicit “if (yourVar != null)” works. 
Is it correct or do I miss something?

> On 24 Mar 2021, at 01:24, Kyle Weaver <kcwea...@google.com> wrote:
> 
> I moved the checker framework from opt-out to opt-in [1]. You can opt in by 
> passing "-PenableCheckerFramework=true" to the Gradle invocation. The checker 
> still runs on all Jenkins CI builds.
> 
> [1] https://github.com/apache/beam/pull/14301 
> <https://github.com/apache/beam/pull/14301>
> On Wed, Mar 17, 2021 at 8:50 AM Kenneth Knowles <k...@apache.org 
> <mailto:k...@apache.org>> wrote:
> 
> 
> On Wed, Mar 17, 2021 at 2:49 AM Jan Lukavský <je...@seznam.cz 
> <mailto:je...@seznam.cz>> wrote:
> If there is no way to configure which annotations should be generated, then 
> I'd be +1 for removing the checker to separated CI and adding an opt-in flag 
> for the check when run locally.
> 
> Yes. If this answer is correct, then we are out of luck: 
> https://stackoverflow.com/questions/57929137/disable-nonnull-annotation-on-implement-methods
>  
> <https://stackoverflow.com/questions/57929137/disable-nonnull-annotation-on-implement-methods>
> 
> A good followup to moving it to a separate CI job would be to attach a full 
> type checking run to the `:check` gradle task. This should be the best place 
> to attach all of our extended checks like spotbugs, spotless, checkstyle, 
> checkerframework. I rarely run `:check` myself (I think it is currently 
> broken in some ways) but it may be good to start.
> 
> BTW the slowdown we need to solve is local builds, not CI runs. When it was 
> added the slowdown was almost completely prevented by caching. And now that 
> we disable it for test classes (where for some reason it was extra slow) I 
> wonder if it will speed up the main CI runs at all. So I would say the first 
> thing to do is to just disable it by default but enable it in the Jenkins job 
> builders.
> 
> Kenn 
> 
> We need to solve the issue for dev@ as well, as the undesirable annotations 
> are already digging their way to the code base:
> 
> git/apache/beam$ git grep UnknownKeyFor
> 
> Another strange thing is that it seems, that we are pulling the 
> checkerframework as a runtime dependency (at least for some submodules). When 
> I run `mvn dependency:tree` on one of my projects that uses maven I see
> 
> [INFO] +- com.google.guava:guava:jar:30.1-jre:provided
> [INFO] |  +- com.google.guava:failureaccess:jar:1.0.1:provided
> [INFO] |  +- 
> com.google.guava:listenablefuture:jar:9999.0-empty-to-avoid-conflict-with-guava:provided
> [INFO] |  +- org.checkerframework:checker-qual:jar:3.5.0:provided
> 
> which is fine, but when I add beam-sdks-java-extensions-euphoria it changes to
> 
> [INFO] +- 
> org.apache.beam:beam-sdks-java-extensions-euphoria:jar:2.28.0:compile
> [INFO] |  \- org.checkerframework:checker-qual:jar:3.7.0:compile
> 
> I'm not a gradle guru, so I cannot tell how this happens, there seems to be 
> nothing special about euphoria in the gradle.
> 
>  Jan
> 
> On 3/16/21 7:12 PM, Kenneth Knowles wrote:
>> I've asked on checkerframework users mailing list if they or any users have 
>> recommendations for the IntelliJ integration issue.
>> 
>> It is worth noting that the default annotations inserted into the bytecode 
>> do add value: the @NonNull type annotations are default for checkerframework 
>> but not default for spotbugs. So having the default inserted enables 
>> downstream users to have betters spotbugs heuristic analysis. Further, the 
>> defaults can be adjusted by users so freezing them at the values we use them 
>> at is valuable in general across all tools.
>> 
>> I think it makes sense to sacrifice these minor value-adds to keep things 
>> simple-looking for IntelliJ users.
>> 
>> Kenn
>> 
>> On Tue, Mar 16, 2021 at 10:05 AM Kenneth Knowles <k...@apache.org 
>> <mailto:k...@apache.org>> wrote:
>> Seems it is an FAQ with no solution: 
>> https://checkerframework.org/manual/#faq-classfile-annotations 
>> <https://checkerframework.org/manual/#faq-classfile-annotations>
>> On Tue, Mar 16, 2021 at 10:01 AM Kenneth Knowles <k...@apache.org 
>> <mailto:k...@apache.org>> wrote:
>> Adding -PskipCheckerframework when releasing will solve it for users, but 
>> not for dev@.
>> 
>> Making it off by default and a separate CI check that turns it on would 
>> solve it overall but has the downsides mentioned before.
>> 
>> It would be very nice to simply have a flag to not insert default 
>> annotations.
>> 
>> Kenn
>> 
>> On Tue, Mar 16, 2021 at 9:37 AM Jan Lukavský <je...@seznam.cz 
>> <mailto:je...@seznam.cz>> wrote:
>> I believe it is not a problem of Idea. At least I didn't notice behavior 
>> like that with Guava, although Guava uses the framework as well. Maybe there 
>> is a way to tune which annotations should be generated? Or Guava handles 
>> that somehow differently?
>> 
>> On 3/16/21 5:22 PM, Reuven Lax wrote:
>>> I've also been annoyed at IntelliJ autogenenerating all these annotations. 
>>> I believe Kenn said that this was not the intention - maybe there's an 
>>> IntelliJ setting that would stop this from happening?
>>> 
>>> On Tue, Mar 16, 2021 at 2:14 AM Jan Lukavský <je...@seznam.cz 
>>> <mailto:je...@seznam.cz>> wrote:
>>> I don't know the details of the checkerframework, but there seems a 
>>> contradiction between what code is (currently) generated and what we 
>>> therefore release and what actually the checkerframework states [1]:
>>> 
>>> @UnknownKeyFor:
>>> 
>>> Used internally by the type system; should never be written by a 
>>> programmer. 
>>> 
>>> If this annotation is generated for overwritten methods, then I'd say, that 
>>> it means we place a great burden to our users - either not using 
>>> autogenerated methods, or erase all the generated annotations afterwards. 
>>> Either way, that is not "polite" from Beam.
>>> 
>>> What we should judge is not only a formal purity of code, but what stands 
>>> on the other side is how usable APIs we provide. We should not head for 
>>> 100% pure code and sacrificing use comfort. Every check that leaks to user 
>>> code is at a price and we should not ignore that. No free lunch.
>>> 
>>> From my point of view:
>>> 
>>>  a) if a check does not modify the bytecode, it is fine and we can use it - 
>>> we are absolutely free to use any tooling we agree on, if our users cannot 
>>> be affected anyhow
>>> 
>>>  b) if a tool needs to be leaked to user, it should be as small leakage as 
>>> possible
>>> 
>>>  c) if a check significantly affects compile performance, it should be 
>>> possible to opt-out
>>> 
>>> I think that our current setup violates all these three points.
>>> 
>>> Moving the check to different CI is a possibility (a)), it would then 
>>> require opt-in flag to be able to run the check locally. It would also stop 
>>> the leakage (if we would release code without this check).
>>> 
>>> If we want to keep some annotations for user's benefit (which might be 
>>> fine), it should be really limited to the bare minimum (e.g. only @Nullable 
>>> for method arguments and return values, possibly more, I don't know if and 
>>> how we can configure that). Definitely not @UnknownKeyFor, that is simply 
>>> internal to the checker. We should then have opt-out flag for local 
>>> development before committing changes.
>>> 
>>>  Jan
>>> 
>>> [1] 
>>> https://checkerframework.org/api/org/checkerframework/checker/nullness/qual/UnknownKeyFor.html
>>>  
>>> <https://checkerframework.org/api/org/checkerframework/checker/nullness/qual/UnknownKeyFor.html>
>>> On 3/16/21 8:33 AM, Reuven Lax wrote:
>>>> 
>>>> 
>>>> On Mon, Mar 15, 2021 at 11:42 PM Reuven Lax <re...@google.com 
>>>> <mailto:re...@google.com>> wrote:
>>>> 
>>>> 
>>>> On Mon, Mar 15, 2021 at 9:12 PM Kenneth Knowles <k...@apache.org 
>>>> <mailto:k...@apache.org>> wrote:
>>>> I will be blunt about my opinions about the general issue:
>>>> 
>>>> - NullPointerExceptions (and similar) are a solved problem.
>>>>    * They have been since 2003 at the latest [1] (this is when the types 
>>>> were hacked into Java - the foundation dates back to the 70s or earlier)
>>>> 
>>>> Huh - Fahndrich tried to hire me once to work on a project called 
>>>> Singularity. Small world. Also note that Sanjay Ghemawat is listed in the 
>>>> citations!
>>>> 
>>>> Umm, I was confusing names. Fahndrich is actually a former coworker at 
>>>> Google :)
>>>>  
>>>>  
>>>>    * Checkerframework is a _pluggable_ system where that nullness type 
>>>> system is a "hello, world" level demo, since 2008 at the latest [2].
>>>>    * Our users should know this and judge us accordingly.
>>>> 
>>>> - Checkerframework should be thought of and described as type checking, 
>>>> because it is. It is not heuristic nor approximate.
>>>> - If your code was unclear about whether something could be null, it was 
>>>> probably unclear to a person reading it also, and very likely to have 
>>>> actual bugs.
>>>> - APIs that accept a lot of nullable parameters are, generally speaking, 
>>>> bad APIs. They are hard to use correctly, less readable, and very likely 
>>>> to cause actual bugs. You are forcing your users to deal with accidental 
>>>> complexity you left behind.
>>>>   * Corollary to the above two points: Almost all the time, the changes to 
>>>> clearify nullness make your code better, more readable, easier for users 
>>>> or editors.
>>>> - It is true that there is a learning curve to programming in this way.
>>>> 
>>>> I agree with the above in a closed system. However as mentioned, some of 
>>>> the APIs we use suffer from this.
>>>> 
>>>> In a previous life, I saw up close an effort to add such analysis to a 
>>>> large codebase. Two separate tools called Prefix and Prefast were used 
>>>> (the difference between the two is actually quite interesting, but not 
>>>> relevant here). However in order to make this analysis useful, there was a 
>>>> massive effort to properly annotate the entire codebase, including all 
>>>> libraries used. This isn't a perfect example - this was a C++ codebase 
>>>> which is much harder to analyze, and these tools identified far more than 
>>>> simply nullness errors (resource leaks, array indices, proper string null 
>>>> termination, exception behavior, etc.). However the closer we can get to 
>>>> properly annotating the transitive closure of our dependencies, the better 
>>>> this framework will work.
>>>> 
>>>>  
>>>> - There are certainly common patterns in Java that do not work very well, 
>>>> and suppression is sometimes the best option.
>>>>    * Example: JUnit's @Setup and @Test conventions do not work very well 
>>>> and it is not worth the effort to make them work. This is actually because 
>>>> if it were "normal code" it would be bad code. There are complex 
>>>> inter-method dependencies enforced only by convention. This matters: 
>>>> sometimes a JUnit test class is called from another class, used as "normal 
>>>> code". This does go wrong in practice. Plain old JUnit test cases 
>>>> frequently go wrong as well.
>>>> 
>>>> And here is my opinion when it comes to Beam:
>>>> 
>>>> - "Community over code" is not an excuse for negligent practices that 
>>>> cause easily avoidable risk to our users. I will be very disappointed if 
>>>> we choose that.
>>>> - I think having tooling that helps newcomers write better code by default 
>>>> is better for the community too. Just like having automatic formatting is 
>>>> better. Less to haggle about in review, etc.
>>>> - A simple search reveals about 170 bugs that we know of [4].
>>>> - So far in almost every module I have fixed I discovered actual new null 
>>>> errors. Many examples at [5].
>>>> - It is extremely easy to suppress the type checking. Almost all of our 
>>>> classes have it suppressed already (I did this work, to allow existing 
>>>> errors while protecting new code).
>>>> - Including the annotations in the shipped jars is an important feature. 
>>>> Without this, users cannot write null-safe code themselves.
>>>>    * Reuven highlighted this: when methods are not annotated, we have to 
>>>> use/implement workarounds. Actually Guava does use checkerframework 
>>>> annotations [6] and the problem is that it requires its *input* to already 
>>>> be non-null so actually you cannot even use it to convert nullable values 
>>>> to non-nullable values.
>>>>    * Beam has its own [7] that is annotated, actually for yet another 
>>>> reason: when Guava's checkNotNull fails, it throws NPE when it should 
>>>> throw IllegalArgumentException. Guava's checkNotNull should not be used 
>>>> for input validation!
>>>> - It is unfortunate that IntelliJ inserts a bunch of annotations in user 
>>>> code. I wonder if there is something we can do about that. At the Java 
>>>> level, if they are not on the classpath they should be ignored and not 
>>>> affect users. Coincidentally, the JDK has had NullPointerExceptions in 
>>>> this area :-)  [8].
>>>> 
>>>> I understand the pain of longer compile times slowing people down. That is 
>>>> actually a problem to be solved which does not require lowering our 
>>>> standards of quality. How about we try moving it to a separate CI job and 
>>>> see how it goes?
>>>> 
>>>>  
>>>> In my experience stories like Reuven's are much more frustrating in a 
>>>> separate CI job because you find out quite late that your code has flaws. 
>>>> Like when spotless fails, but much more work to fix, and would have been 
>>>> prevented long ago if it were integrated into the compile.
>>>> 
>>>> I agree with this. I prefer to be able to detect on my computer that there 
>>>> are failures, and not have to wait for submission. The complaint was that 
>>>> some people are experiencing trouble on their local machine however, so it 
>>>> seems reasonable to add an opt-out flag (though I would prefer opt out to 
>>>> opt in).
>>>>  
>>>> 
>>>> Kenn
>>>> 
>>>> [1] 
>>>> https://web.eecs.umich.edu/~bchandra/courses/papers/Fahndrich_NonNull.pdf 
>>>> <https://web.eecs.umich.edu/~bchandra/courses/papers/Fahndrich_NonNull.pdf>
>>>> [2] 
>>>> https://homes.cs.washington.edu/~mernst/pubs/pluggable-checkers-issta2008.pdf
>>>>  
>>>> <https://homes.cs.washington.edu/~mernst/pubs/pluggable-checkers-issta2008.pdf>
>>>> [3] 
>>>> https://github.com/google/guava/blob/fe3fda0ca54076a2268d060725e9a6e26f867a5e/pom.xml#L275
>>>>  
>>>> <https://github.com/google/guava/blob/fe3fda0ca54076a2268d060725e9a6e26f867a5e/pom.xml#L275>
>>>> [4] 
>>>> https://issues.apache.org/jira/issues/?jql=project%20%3D%20BEAM%20AND%20(summary%20~%20%22NPE%22%20OR%20summary%20~%20%22NullPointerException%22%20OR%20description%20~%20%22NPE%22%20OR%20description%20~%20%22NullPointerException%22%20OR%20comment%20~%20%22NPE%22%20OR%20comment%20~%20%22NullPointerException%22)
>>>>  
>>>> <https://issues.apache.org/jira/issues/?jql=project%20%3D%20BEAM%20AND%20(summary%20~%20%22NPE%22%20OR%20summary%20~%20%22NullPointerException%22%20OR%20description%20~%20%22NPE%22%20OR%20description%20~%20%22NullPointerException%22%20OR%20comment%20~%20%22NPE%22%20OR%20comment%20~%20%22NullPointerException%22)>
>>>> [5] https://github.com/apache/beam/pull/12284 
>>>> <https://github.com/apache/beam/pull/12284> and 
>>>> https://github.com/apache/beam/pull/12162 
>>>> <https://github.com/apache/beam/pull/12162> and 
>>>> [6] 
>>>> https://github.com/google/guava/blob/fe3fda0ca54076a2268d060725e9a6e26f867a5e/guava/src/com/google/common/base/Preconditions.java#L878
>>>>  
>>>> <https://github.com/google/guava/blob/fe3fda0ca54076a2268d060725e9a6e26f867a5e/guava/src/com/google/common/base/Preconditions.java#L878>
>>>> [7] 
>>>> https://github.com/apache/beam/blob/master/sdks/java/core/src/main/java/org/apache/beam/sdk/util/Preconditions.java
>>>>  
>>>> <https://github.com/apache/beam/blob/master/sdks/java/core/src/main/java/org/apache/beam/sdk/util/Preconditions.java>
>>>> [8] https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8152174 
>>>> <https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8152174>
>>>> 
>>>> 
>>>> On Mon, Mar 15, 2021 at 2:12 PM Reuven Lax <re...@google.com 
>>>> <mailto:re...@google.com>> wrote:
>>>> I have some deeper concerns with the null checks. The fact that many 
>>>> libraries we use (including guava) don't always annotate their methods 
>>>> forces a lot of workarounds. As a very simple example, the return value 
>>>> from Preconditions.checkNotNull clearly can never be null, yet the 
>>>> nullability checks don't know this. This and other similar cases require 
>>>> constantly adding extra unnecessary null checks in the code just to make 
>>>> the checker happy. There have been other cases where I haven't been able 
>>>> to figure out a way to make the checker happy (often these seem to involve 
>>>> using lambdas), and after 10-15 minutes of investigation have given up and 
>>>> disabled the check.
>>>> 
>>>> Now you might say that it's worth the extra pain and ugliness of writing 
>>>> "useless" code to ensure that we have null-safe code. However I think this 
>>>> ignores a sociological aspect of software development. I have a higher 
>>>> tolerance than many for this sort of pain, and I'm willing to spend some 
>>>> time figuring out how to rewrite my code such that it makes the checker 
>>>> happy (even though often it forced me to write much more awkward code). 
>>>> However even I have often found myself giving up and just disabling the 
>>>> check. Many others will have less tolerance than me, and will simply 
>>>> disable the checks. At that point we'll have a codebase littered with 
>>>> @SuppressWarnings("nullness"), which doesn't really get us where we want 
>>>> to be. I've seen similar struggles in other codebases, and generally 
>>>> having a static checker with too many false positives often ends up being 
>>>> worse than having no checker.
>>>> 
>>>> On Mon, Mar 15, 2021 at 10:37 AM Ismaël Mejía <ieme...@gmail.com 
>>>> <mailto:ieme...@gmail.com>> wrote:
>>>> +1
>>>> 
>>>> Even if I like the strictness for Null checking, I also think that
>>>> this is adding too much extra time for builds (that I noticed locally
>>>> when enabled) and also I agree with Jan that the annotations are
>>>> really an undesired side effect. For reference when you try to auto
>>>> complete some method signatures on IntelliJ on downstream projects
>>>> with C-A-v it generates some extra Checkers annotations like @NonNull
>>>> and others even if the user isn't using them which is not desirable.
>>>> 
>>>> 
>>>> 
>>>> On Mon, Mar 15, 2021 at 6:04 PM Kyle Weaver <kcwea...@google.com 
>>>> <mailto:kcwea...@google.com>> wrote:
>>>> >>
>>>> >> Big +1 for moving this to separate CI job. I really don't like what 
>>>> >> annotations are currently added to the code we ship. Tools like Idea 
>>>> >> add these annotations to code they generate when overriding classes and 
>>>> >> that's very annoying. Users should not be exposed to internal tools 
>>>> >> like nullability checking.
>>>> >
>>>> >
>>>> > I was only planning on moving this to a separate CI job. The job would 
>>>> > still be release blocking, so the same annotations would still be 
>>>> > required.
>>>> >
>>>> > I'm not sure which annotations you are concerned about. There are two 
>>>> > annotations involved with nullness checking, @SuppressWarnings and 
>>>> > @Nullable. @SuppressWarnings has retention policy SOURCE, so it 
>>>> > shouldn't be exposed to users at all. @Nullable is not just for internal 
>>>> > tooling, it also provides useful information about our APIs to users. 
>>>> > The user should not have to guess whether a method argument etc. can be 
>>>> > null or not, and for better or worse, these annotations are the standard 
>>>> > way of expressing that in Java.

Reply via email to