Does it make sense to add a Jenkins precommit suite that runs null checking exclusively?
On Fri, Mar 12, 2021 at 11:57 AM Kyle Weaver <kcwea...@google.com> wrote: > I don't mind fixing my code or suppressing nullness errors, but the cost > of the null check itself is hurting my productivity. In the best case, null > checks add about ten minutes to the build time for large modules > like :sdks:java:core. In the worst case, they cause my build to fail > altogether, because the framework logs a warning that "Memory constraints > are impeding performance," which is interpreted by -Wall as an error. It > might not be a problem on big machines with a lot of memory, but on my > Macbook, and on the Github Actions executors it is a real problem. > https://issues.apache.org/jira/browse/BEAM-11837 > > Since nullness checks seem to work fine for now on Jenkins, I propose > making them opt-in rather than opt-out, and only run them on Jenkins by > default. > > On Tue, Mar 2, 2021 at 12:13 PM Kyle Weaver <kcwea...@google.com> wrote: > >> Can you try adding the generated classes to generatedClassPatterns in the >> JavaNatureConfiguration? >> >> >> https://github.com/apache/beam/blob/03b883b415d27244ddabb17a0fb5bab147b86f89/buildSrc/src/main/groovy/org/apache/beam/gradle/BeamModulePlugin.groovy#L92 >> >> >> On Tue, Mar 2, 2021 at 12:05 AM Reuven Lax <re...@google.com> wrote: >> >>> I'm running into a problem with this check. I added a protocol-buffer >>> file to a module (google-cloud-platform) that previously did have any >>> protobuf files in it. The generated files contain lines that violate this >>> null checker, so they won't compile. I can't annotate the files, because >>> they are codegen files. I tried adding the package to spotbugs-filter.xml, >>> but that didn't help. >>> >>> Any suggestions? >>> >>> Reuven >>> >>> On Fri, Jan 22, 2021 at 10:38 AM Brian Hulette <bhule...@google.com> >>> wrote: >>> >>>> >>>> >>>> On Fri, Jan 22, 2021 at 1:18 AM Jan Lukavský <je...@seznam.cz> wrote: >>>> >>>>> Hi, >>>>> >>>>> I'll give my two cents here. >>>>> >>>>> I'm not 100% sure that the 1-5% of bugs are as severe as other types >>>>> of bugs. Yes, throwing NPEs at user is not very polite. On the other hand, >>>>> many of these actually boil down to user errors. Then we might ask what a >>>>> correct solution would be. If we manage to figure out what the actual >>>>> problem is and tell user what specifically is missing or going wrong, that >>>>> would be just awesome. On the other hand, if a tool used for avoiding >>>>> "unexpected" NPEs forces us to code >>>>> >>>>> Object value = Objects.requireNonNull(myNullableObject); // or >>>>> similar using Preconditions >>>>> value.doStuff(); >>>>> >>>>> instead of just >>>>> >>>>> myNullableObject.doStuff() >>>>> >>>>> what we actually did, is a) made a framework happy, and b) changed a >>>>> line at which NPE is thrown by 1 (and yes, internally prevented JVM from >>>>> thrown SIGSEGV at itself, but that is deeply technical thing). Nothing >>>>> changed semantically, from user perspective. >>>>> >>>> I'd argue there's value in asking Beam developers to make that change. >>>> It makes us acknowledge that there's a possibility myNullableObject is >>>> null. If myNullableObject being null is something relevant to the user we >>>> would likely want to wrap it in some other exception or provide a more >>>> useful message than just NPE(!!). >>>> >>>>> >>>>> Now, given that the framework significantly rises compile time (due to >>>>> all the checks), causes many "bugs" being reported by static code analysis >>>>> tools (because the framework adds @Nonnull default annotations everywhere, >>>>> even when Beam's code actually counts with nullability of a field), and >>>>> given how much we currently suppress these checks ($ git grep BEAM-10402 | >>>>> wc -l -> 1981), I'd say this deserves a deeper discussion. >>>>> >>>> The reason there are so many suppressions is that fixing all the errors >>>> is a monumental task. Rather than addressing them all, Kenn >>>> programmatically added suppressions for classes that failed the checks ( >>>> https://github.com/apache/beam/pull/13261). This allowed us to start >>>> running the checker on the code that passes it while the errors are fixed. >>>> >>>>> Jan >>>>> >>>>> >>>>> On 1/20/21 10:48 PM, Kenneth Knowles wrote: >>>>> >>>>> Yes, completely sound nullability checking has been added to the >>>>> project via checkerframework, based on a large number of NPE bugs (1-5% >>>>> depending on how you search, but many other bugs likely attributable to >>>>> nullness-based design errors) which are extra embarrassing because NPEs >>>>> have were essentially solved, even in practice for Java, well before Beam >>>>> existed. >>>>> >>>>> Checker framework is a pluggable type system analysis with some amount >>>>> of control flow sensitivity. Every value has a type that is either >>>>> nullable >>>>> or not, and certain control structures (like checking for null) can alter >>>>> the type inside a scope. The best way to think about it is to consider >>>>> every value in the program as either nullable or not, much like you think >>>>> of every value as either a string or not, and to view method calls as >>>>> inherently stateful/nondetermistic. This can be challenging in esoteric >>>>> cases, but usually makes the overall code health better anyhow. >>>>> >>>>> Your example illustrates how problematic the design of the Java >>>>> language is: the analysis cannot assume that `getDescription` is a pure >>>>> function, and neither should you. Even if it is aware of >>>>> boolean-short-circuit it would not be sound to accept this code. There is >>>>> an annotation for this in the cases where it is true (like proto-generate >>>>> getters): >>>>> https://checkerframework.org/api/org/checkerframework/dataflow/qual/Pure.html >>>>> >>>>> The refactor for cases like this is trivial so there isn't a lot of >>>>> value to thinking too hard about it. >>>>> >>>>> if (statusCode.equals(Code.INVALID_ARGUMENT) >>>>> @Nullable String desc = statusCode.toStatus().getDescription(); >>>>> if (desc != null && desc.contains("finalized")) { >>>>> return false; >>>>> } >>>>> } >>>>> >>>>> To a casual eye, this may look like a noop change. To the analysis it >>>>> makes all the difference. And IMO this difference is real. Humans may >>>>> assume it is a noop and humans would be wrong. So many times when you >>>>> think/expect/hope that `getXYZ()` is a trivial getter method you later >>>>> learn that it was tweaked for some odd reason. I believe this code change >>>>> makes the code better. Suppressing these errors should be exceptionally >>>>> rare, and never in normal code. It is far better to improve your code than >>>>> to suppress the issue. >>>>> >>>>> It would be very cool for the proto compiler to annotate enough that >>>>> new-and-improved type checkers could make things more convenient. >>>>> >>>>> Kenn >>>>> >>>>> On Mon, Jan 11, 2021 at 8:53 PM Reuven Lax <re...@google.com> wrote: >>>>> >>>>>> I can use that trick. However I'm surprised that the check appears to >>>>>> be so simplistic. >>>>>> >>>>>> For example, the following code triggers the check on >>>>>> getDescription().contains(), since getDescription returns a Nullable >>>>>> string. However even a simplistic analysis should realize that >>>>>> getDescription() was checked for null first! I have a dozen or so cases >>>>>> like this, and I question how useful such a simplistic check it will be. >>>>>> >>>>>> if (statusCode.equals(Code.INVALID_ARGUMENT) && >>>>>> statusCode.toStatus().getDescription() != null && >>>>>> statusCode.toStatus().getDescription().contains("finalized")) { return >>>>>> false; >>>>>> } >>>>>> >>>>>> >>>>>> On Mon, Jan 11, 2021 at 8:32 PM Boyuan Zhang <boyu...@google.com> >>>>>> wrote: >>>>>> >>>>>>> Yeah it seems like the checker is enabled: >>>>>>> https://issues.apache.org/jira/browse/BEAM-10402. I used >>>>>>> @SuppressWarnings({"nullness" )}) to suppress the error when I think >>>>>>> it's >>>>>>> not really a concern. >>>>>>> >>>>>>> On Mon, Jan 11, 2021 at 8:28 PM Reuven Lax <re...@google.com> wrote: >>>>>>> >>>>>>>> Has extra Nullable checking been enabled in the Beam project? I >>>>>>>> have a PR that was on hold for several months, and I'm struggling now >>>>>>>> with >>>>>>>> compile failing to complaints about assigning something that is >>>>>>>> nullable to >>>>>>>> something that is not nullable. Even when the immediate control flow >>>>>>>> makes >>>>>>>> it absolutely impossible for the variable to be null. >>>>>>>> >>>>>>>> Has something changed here? >>>>>>>> >>>>>>>> Reuven >>>>>>>> >>>>>>>