[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-compiler-dev
Subject:    @SafeVarargs vs @SuppressWarnings("varargs")
From:       Anthony Vanelverdinghe <dev () anthonyv ! be>
Date:       2020-05-01 17:39:06
Message-ID: 2140cb38-e6fd-141b-75f6-3d7af84e2a57 () anthonyv ! be
[Download RAW message or body]

Hi

Please consider the following class:

     import java.util.*;
     import java.util.function.Predicate;

     class Foo {

         @SafeVarargs // suppresses (1) but not (2)
         @SuppressWarnings("varargs") // suppresses (2) but not (1)
         static <T> void bar(T o, Predicate<T>... predicates) {
             // (1) warning: [unchecked] Possible heap pollution from 
parameterized vararg type Predicate<T>
             for(Predicate<T> predicate : predicates) {
                 predicate.test(o);
             }

             // (2) warning: [varargs] Varargs method could cause heap 
pollution from non-reifiable varargs parameter predicates
             Arrays.stream(predicates).forEachOrdered(predicate -> 
predicate.test(o));
         }

         // copied from 
https://docs.oracle.com/en/java/javase/14/docs/specs/man/javac.html#examples-of-using--xlint-keys
         public static <T> void addToList(List<T> listArg, T... elements) {
             for (T x : elements) {
                 listArg.add(x);
             }
         }

         static void baz() {
             addToList(List.of(""), "foo");
         }

     }

As you can see, the method `bar` does the same thing twice, but in 
different ways: the first time it uses an enhanced for statement, the 
second time it uses Arrays::stream.
Using a for-loop results in a warning of type "unchecked", which can be 
suppressed with @SafeVarargs.
Using Arrays::stream results in a warning of type "varargs", which can 
be suppressed with @SuppressWarnings("varargs").

The method `addToList` was copied from the documentation for the 
"varargs" Xlint type [1], which states that its compilation will create 
the warning: "warning: [varargs] Possible heap pollution from 
parameterized vararg type T".
However, comparing with the `bar` method, this is the Xlint type of the 
second warning, combined with the message of the first warning, which 
seems suspicious. And indeed, compiling it gives me an "unchecked" 
warning, not a "varargs" warning.
Moreover, the documentation first says: "Warns about unsafe **use** of 
variable arguments (varargs) methods", but then after the example says: 
"The compiler generates the following warning for the **definition** of 
the method".

 From the documentation I thought that the "varargs" type is indeed 
about uses of varargs methods which haven't been annotated with 
`@SafeVarargs`. But this is contradicted by the invocation of 
`addToList` in the method `baz`, which doesn't result in an Xlint 
warning at all.

To summarize, I believe:
* there are 2 issues with javac here:
     1) both warnings in the `bar` method should be the same, namely: 
"warning: [unchecked] Possible heap pollution from parameterized vararg 
type Predicate<T>" and only `@SafeVarargs` should be needed to be able 
to compile the method without any warnings
     2) there's no warning in `baz`, even though I think it should give 
a warning of type "varargs"
* and the current documentation for the "varargs" Xlint type is wrong

Is the above correct? If so, I'll file bug reports for these. If not, 
I'm confused, so I'd appreciate any clarifications.

Kind regards,
Anthony

[1] 
https://docs.oracle.com/en/java/javase/14/docs/specs/man/javac.html#examples-of-using--xlint-keys

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic