-
Bug
-
Resolution: Not an Issue
-
P3
-
8
-
x86_64
-
linux
FULL PRODUCT VERSION :
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b127)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b69, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux jtek 3.10.25-gentoo #6 SMP Sun Jan 5 14:08:51 PST 2014 x86_64 Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz GenuineIntel GNU/Linux
A DESCRIPTION OF THE PROBLEM :
I hit this bug while trying to get Gradle building under JDK8.
I've created a simple reproduction of the issue here: https://bitbucket.org/marshallpierce/java8-varargs-generics-capture
The README of that repo describes the issue, so I'll copy & paste it here for completeness.
`GenericContainerWithVarargs<T>` has `add(T)` and `add(T...)`. This sample code (`WithVarargs`) that invokes `add(new Object())` compiles under Java 7, but doesn't under Java 8 M8 b127:
```
GenericContainerWithVarargs<?> container = new GenericContainerWithVarargs<>();
container.add(new Object());
```
`GenericContainerWithoutVarargs` has only `add(T)`. This other sample code (`NoVarargs`) that also invokes `add(new Object())` doesn't compile under either version:
```
GenericContainerWithoutVarargs<?> container = new GenericContainerWithoutVarargs<>();
container.add(new Object());
```
To reproduce this, try the following under both JDK 7 and JDK 8. There are two separate modules so that compile failures in one don't affect the other.
```
./gradlew clean :with-varargs:build
./gradlew clean :without-varargs:build
```
Under JDK 7, `with-varargs` compiles (with an unchecked warning) but `without-varargs` does not:
```
/.../without-varargs/src/main/java/withoutvarargs/GenericVarargs.java:6: error: method add in class GenericContainerWithoutVarargs<T> cannot be applied to given types;
container.add(new Object());
^
required: CAP#1
found: Object
reason: actual argument Object cannot be converted to CAP#1 by method invocation conversion
where T is a type-variable:
T extends Object declared in class GenericContainerWithoutVarargs
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 error
```
Under JDK 8 M8 b127, neither builds.
`with-varargs`:
```
/.../with-varargs/src/main/java/withvarargs/GenericContainerWithVarargs.java:9: warning: [unchecked] Possible heap pollution from parameterized vararg type T
void add(T... objects) {
^
where T is a type-variable:
T extends Object declared in class GenericContainerWithVarargs
/.../with-varargs/src/main/java/withvarargs/GenericVarargs.java:6: error: no suitable method found for add(Object)
container.add(new Object());
^
method GenericContainerWithVarargs.add(CAP#1) is not applicable
(argument mismatch; Object cannot be converted to CAP#1)
method GenericContainerWithVarargs.add(CAP#1...) is not applicable
(varargs mismatch; Object cannot be converted to CAP#1)
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 error
1 warning
```
`without-varargs`:
```
/.../without-varargs/src/main/java/withoutvarargs/GenericVarargs.java:6: error: method add in class GenericContainerWithoutVarargs<T> cannot be applied to given types;
container.add(new Object());
^
required: CAP#1
found: Object
reason: argument mismatch; Object cannot be converted to CAP#1
where T is a type-variable:
T extends Object declared in class GenericContainerWithoutVarargs
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 error
```
This is a simplified version of this code in Gradle's [DefaultModelRegistry](https://github.com/gradle/gradle/blob/75785398f19b634494316b0eb8f2427ab6adbc1a/subprojects/core/src/main/groovy/org/gradle/model/internal/DefaultModelRegistry.java#L210) that has an analogous failure:
```
private Inputs toInputs(Iterable<ModelPath> inputPaths) {
ImmutableList.Builder<?> builder = ImmutableList.builder();
for (ModelPath inputPath : inputPaths) {
builder.add(getClosedModel(inputPath));
}
return new DefaultInputs(builder.build());
}
```
The Guava ImmutableList.Builder that it's using basically has the `with-varargs` case: both `add(E e)` and `add(E... es)` are provided, so it compiled under Java 7 and now doesn't.
REGRESSION. Last worked in version 7u51
ADDITIONAL REGRESSION INFORMATION:
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b127)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b69, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Clone the sample repo https://bitbucket.org/marshallpierce/java8-varargs-generics-capture
2. Under java 7, run:
./gradlew clean :with-varargs:build
See that it compiles.
3. Under java 8, run the same command and see that it fails.
4. For contrast, note that doing the same for :without-varargs fails for both versions.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The JDK8 compiler should behave like the JDK7 one.
Unless the JDK7 one was wrong all along? In which case it'd be great if the JDK7 compiler also failed (perhaps in a subsequent JDK7 update).
ACTUAL -
The JDK8 compiler rejects code that the JDK7 compiler accepted.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
There's already a minimal test case at https://bitbucket.org/marshallpierce/java8-varargs-generics-capture but here are the classes contained there.
class GenericContainerWithVarargs<T> {
void add(T obj) {
}
void add(T... objects) {
}
}
class WithVarargs {
private void foo() {
GenericContainerWithVarargs<?> container = new GenericContainerWithVarargs<>();
container.add(new Object());
}
}
class GenericContainerWithoutVarargs<T> {
void add(T obj) {
}
}
class NoVarargs {
private void foo() {
GenericContainerWithoutVarargs<?> container = new GenericContainerWithoutVarargs<>();
container.add(new Object());
}
}
---------- END SOURCE ----------
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b127)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b69, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux jtek 3.10.25-gentoo #6 SMP Sun Jan 5 14:08:51 PST 2014 x86_64 Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz GenuineIntel GNU/Linux
A DESCRIPTION OF THE PROBLEM :
I hit this bug while trying to get Gradle building under JDK8.
I've created a simple reproduction of the issue here: https://bitbucket.org/marshallpierce/java8-varargs-generics-capture
The README of that repo describes the issue, so I'll copy & paste it here for completeness.
`GenericContainerWithVarargs<T>` has `add(T)` and `add(T...)`. This sample code (`WithVarargs`) that invokes `add(new Object())` compiles under Java 7, but doesn't under Java 8 M8 b127:
```
GenericContainerWithVarargs<?> container = new GenericContainerWithVarargs<>();
container.add(new Object());
```
`GenericContainerWithoutVarargs` has only `add(T)`. This other sample code (`NoVarargs`) that also invokes `add(new Object())` doesn't compile under either version:
```
GenericContainerWithoutVarargs<?> container = new GenericContainerWithoutVarargs<>();
container.add(new Object());
```
To reproduce this, try the following under both JDK 7 and JDK 8. There are two separate modules so that compile failures in one don't affect the other.
```
./gradlew clean :with-varargs:build
./gradlew clean :without-varargs:build
```
Under JDK 7, `with-varargs` compiles (with an unchecked warning) but `without-varargs` does not:
```
/.../without-varargs/src/main/java/withoutvarargs/GenericVarargs.java:6: error: method add in class GenericContainerWithoutVarargs<T> cannot be applied to given types;
container.add(new Object());
^
required: CAP#1
found: Object
reason: actual argument Object cannot be converted to CAP#1 by method invocation conversion
where T is a type-variable:
T extends Object declared in class GenericContainerWithoutVarargs
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 error
```
Under JDK 8 M8 b127, neither builds.
`with-varargs`:
```
/.../with-varargs/src/main/java/withvarargs/GenericContainerWithVarargs.java:9: warning: [unchecked] Possible heap pollution from parameterized vararg type T
void add(T... objects) {
^
where T is a type-variable:
T extends Object declared in class GenericContainerWithVarargs
/.../with-varargs/src/main/java/withvarargs/GenericVarargs.java:6: error: no suitable method found for add(Object)
container.add(new Object());
^
method GenericContainerWithVarargs.add(CAP#1) is not applicable
(argument mismatch; Object cannot be converted to CAP#1)
method GenericContainerWithVarargs.add(CAP#1...) is not applicable
(varargs mismatch; Object cannot be converted to CAP#1)
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 error
1 warning
```
`without-varargs`:
```
/.../without-varargs/src/main/java/withoutvarargs/GenericVarargs.java:6: error: method add in class GenericContainerWithoutVarargs<T> cannot be applied to given types;
container.add(new Object());
^
required: CAP#1
found: Object
reason: argument mismatch; Object cannot be converted to CAP#1
where T is a type-variable:
T extends Object declared in class GenericContainerWithoutVarargs
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 error
```
This is a simplified version of this code in Gradle's [DefaultModelRegistry](https://github.com/gradle/gradle/blob/75785398f19b634494316b0eb8f2427ab6adbc1a/subprojects/core/src/main/groovy/org/gradle/model/internal/DefaultModelRegistry.java#L210) that has an analogous failure:
```
private Inputs toInputs(Iterable<ModelPath> inputPaths) {
ImmutableList.Builder<?> builder = ImmutableList.builder();
for (ModelPath inputPath : inputPaths) {
builder.add(getClosedModel(inputPath));
}
return new DefaultInputs(builder.build());
}
```
The Guava ImmutableList.Builder that it's using basically has the `with-varargs` case: both `add(E e)` and `add(E... es)` are provided, so it compiled under Java 7 and now doesn't.
REGRESSION. Last worked in version 7u51
ADDITIONAL REGRESSION INFORMATION:
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b127)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b69, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Clone the sample repo https://bitbucket.org/marshallpierce/java8-varargs-generics-capture
2. Under java 7, run:
./gradlew clean :with-varargs:build
See that it compiles.
3. Under java 8, run the same command and see that it fails.
4. For contrast, note that doing the same for :without-varargs fails for both versions.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The JDK8 compiler should behave like the JDK7 one.
Unless the JDK7 one was wrong all along? In which case it'd be great if the JDK7 compiler also failed (perhaps in a subsequent JDK7 update).
ACTUAL -
The JDK8 compiler rejects code that the JDK7 compiler accepted.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
There's already a minimal test case at https://bitbucket.org/marshallpierce/java8-varargs-generics-capture but here are the classes contained there.
class GenericContainerWithVarargs<T> {
void add(T obj) {
}
void add(T... objects) {
}
}
class WithVarargs {
private void foo() {
GenericContainerWithVarargs<?> container = new GenericContainerWithVarargs<>();
container.add(new Object());
}
}
class GenericContainerWithoutVarargs<T> {
void add(T obj) {
}
}
class NoVarargs {
private void foo() {
GenericContainerWithoutVarargs<?> container = new GenericContainerWithoutVarargs<>();
container.add(new Object());
}
}
---------- END SOURCE ----------