JDK-8219318 (???): inferred type does not conform to upper bound(s) when collecting to a HashMap

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Fri Dec 13 21:52:52 UTC 2019


I'll need to think more about this - but I think the proposed fix 
doesn't seem conform with the JLS. Note that, during overload 
resolution, certain arguments are 'left behind', see JLS section 15.12.2.2:

"An argument expression is considered pertinent to applicability for a 
potentially applicable method m unless it has one of the following forms:
...

An inexact method reference expression (§15.13.1).

"

'stuck' is javac's way to call an argument that is not pertinent to 
applicability. So, to me, the fact that we get no constraints from 
HashMap::new during overload seems normal.

At the same time, the target type (Map<? extends Integer, ? extends 
Integer>) is _not_ considered during overload inference - which means 
that the M type-variable of the Collectors.toMap method is 
underconstrained (and will be inferred as Map<Object, Object>). As I 
said before, I'd need to think more about it (as this is a tricky 
issue), but it is possible that this is not an issue (for what it's 
worth, pasting the code with IntelliJ reveals the same issue).

Maurizio

On 13/12/2019 19:46, B. Blaser wrote:
> Hi,
>
> I looked at the following interesting issue [1]:
>
> public static void main(String... args) {
>      Map<Integer, Integer> destination = null;
>      Map<Integer, Integer> source = null;
>
>      destination.putAll( source.entrySet().stream().collect(
> Collectors.toMap( e -> 0, e -> 0, ( e1, e2 ) -> 0, HashMap::new ) ) );
> }
>
> Javac fails to infer the above expression during overload resolution
> of 'putAll()' when checking the return type of the partially inferred
> method 'collect()' whereas avoiding it succeeds:
>
>      Map<? extends Integer, ? extends Integer> broker =
> source.entrySet().stream().collect( Collectors.toMap( e -> 0, e -> 0,
> ( e1, e2 ) -> 0, HashMap::new ) );
>
> It seems that the inference context is missing constraints from
> 'HashMap::new' when checking the partially inferred method return type
> because of [2].
>
> Removing the line 'stuck = true' as here under makes the above example
> succeed but a couple of tests like [3] are then failing as statements
> like 'g4(MethodReference46::m)' are no more ambiguous which would be,
> at my mind, a good thing.
>
> What do you think, is the current behavior correct or should we fix
> this issue with something like below?
>
> Thanks,
> Bernard
>
> [1] https://bugs.openjdk.java.net/browse/JDK-8219318
> [2] http://hg.openjdk.java.net/jdk/jdk/file/cec148db7b55/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java#l1280
> [3] http://hg.openjdk.java.net/jdk/jdk/file/cec148db7b55/test/langtools/tools/javac/lambda/MethodReference46.java#l43
>
> diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
> b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
> @@ -1276,9 +1276,9 @@
>           @Override
>           public void visitReference(JCMemberReference tree) {
>               super.visitReference(tree);
> -            if (tree.getOverloadKind() !=
> JCMemberReference.OverloadKind.UNOVERLOADED) {
> -                stuck = true;
> -            }
> +//            if (tree.getOverloadKind() !=
> JCMemberReference.OverloadKind.UNOVERLOADED) {
> +//                stuck = true;
> +//            }
>           }
>       }


More information about the compiler-dev mailing list