JDK-8219318 (???): inferred type does not conform to upper bound(s) when collecting to a HashMap
B. Blaser
bsrbnd at gmail.com
Thu Dec 19 15:23:23 UTC 2019
On Wed, 18 Dec 2019 at 16:46, Maurizio Cimadamore
<maurizio.cimadamore at oracle.com> wrote:
>
> On 18/12/2019 15:35, B. Blaser wrote:
> > Another possibility would be to reduce the fix to 'inexact method
> > references with *a unique potential target* and no stuck variables
> > would be pertinent to applicability'?
>
> I honestly believe you are looking in the wrong place. I think there's a
> reason (as I explained) as to why pertinent to applicability was defined
> the way it was. If there's a spec problem here, it seems like it lies in
> how incorporation fails to generate constraints for the underconstrained
> vars because of the presence of wildcards. That's a much more direct
> problem to fix, which doesn't involve re-architecting how overload
> selection is structured (which is not gonna happen).
I guess you're right, the method reference is probably shadowing the problem.
Take the following simpler example:
class Test3 {
interface I<V> {}
<W, X extends I<W>> X m() { return null; }
void n(I<Integer> p) {}
void o(I<? extends Integer> p) {}
void run() {
n(m());
o(this.<Integer, I<Integer>>m());
o(m()); // KO!
}
}
$ javac Test3.java
Test3.java:12: error: incompatible types: inferred type does not
conform to upper bound(s)
o(m()); // KO!
^
inferred: I<Object>
upper bound(s): I<Object>,I<? extends Integer>
Note: Some messages have been simplified; recompile with
-Xdiags:verbose to get full output
1 error
The problem is that when inferring 'n(m())' the bounds 'X <: I(W),
I(Integer)' implies 'W=Integer' per §18.3.1 but with 'o(m())' the
bounds 'X <: I(W), I(? extends Integer)' should probably imply 'W <:
Integer' instead of inferring 'W=Object'.
So, I did a voodoo cult devoted to inference which ended up with some
black magic on our good old friend 'Types::isSameType', see below.
While this experiment is somewhat incomplete, both examples 'putAll()'
and 'o(m())' are now working without any 'langtools:tier1' failure.
What do you think?
Bernard
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
@@ -1376,6 +1376,10 @@
@Override
public Boolean visitWildcardType(WildcardType t, Type s) {
if (!s.hasTag(WILDCARD)) {
+ if (!t.isUnbound() && t.isExtendsBound() &&
s.hasTag(UNDETVAR)) {
+ ((UndetVar)s).addBound(InferenceBound.UPPER,
t.type, Types.this);
+ return true;
+ }
return false;
} else {
WildcardType t2 = (WildcardType)s;
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
@@ -944,6 +944,10 @@
List<Type> allParamsSuperBound1 =
commonSupers.fst.allparams();
List<Type> allParamsSuperBound2 =
commonSupers.snd.allparams();
while (allParamsSuperBound1.nonEmpty() &&
allParamsSuperBound2.nonEmpty()) {
+ if
(allParamsSuperBound1.head.hasTag(WILDCARD) &&
!allParamsSuperBound2.head.hasTag(WILDCARD)) {
+ //try to match wildcard and undet var bounds
+ isSameType(allParamsSuperBound1.head,
inferenceContext.asUndetVar(allParamsSuperBound2.head));
+ }
//traverse the list of all params comparing them
if (!allParamsSuperBound1.head.hasTag(WILDCARD) &&
!allParamsSuperBound2.head.hasTag(WILDCARD)) {
More information about the compiler-dev
mailing list