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

On Wed, Mar 17, 2021 at 8:50 AM Kenneth Knowles <k...@apache.org> wrote:

>
>
> On Wed, Mar 17, 2021 at 2:49 AM Jan Lukavský <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
>
> 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> wrote:
>>
>>> Seems it is an FAQ with no solution:
>>> https://checkerframework.org/manual/#faq-classfile-annotations
>>>
>>> On Tue, Mar 16, 2021 at 10:01 AM Kenneth Knowles <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> 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> 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
>>>>>> On 3/16/21 8:33 AM, Reuven Lax wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Mon, Mar 15, 2021 at 11:42 PM Reuven Lax <re...@google.com> wrote:
>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Mon, Mar 15, 2021 at 9:12 PM Kenneth Knowles <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
>>>>>>>> [2]
>>>>>>>> https://homes.cs.washington.edu/~mernst/pubs/pluggable-checkers-issta2008.pdf
>>>>>>>> [3]
>>>>>>>> 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)
>>>>>>>> [5] https://github.com/apache/beam/pull/12284 and
>>>>>>>> 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
>>>>>>>> [7]
>>>>>>>> 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
>>>>>>>>
>>>>>>>>
>>>>>>>> On Mon, Mar 15, 2021 at 2:12 PM Reuven Lax <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>
>>>>>>>>> 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>
>>>>>>>>>> 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