Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
3.0.12, 3.0.13, 4.0.6
-
None
Description
This compiles in Groovy 3.0.11, but it does not compile in Groovy 3.0.12 or 3.0.13.
import groovy.transform.CompileStatic @CompileStatic abstract class NoticeRenderer { private static final Comparator<String> COMPARATOR = Comparator<String>.comparing(NoticeRenderer::getComponentDisplayName) public static String getComponentDisplayName(String component) { return component; } }
The error is
Failed to find the expected method[getComponentDisplayName(java.lang.Object)] in the type[NoticeRenderer] at line: 5, column: 79
I think something is going sideways when inferring the types to comparing.
Removing the type bound on the Comparator doesn't change the error.
private static final Comparator<String> COMPARATOR = Comparator.comparing(NoticeRenderer::getComponentDisplayName)
The type bound could be on the method itself. This produces the same error.
private static final Comparator<String> COMPARATOR = Comparator.<String>comparing(NoticeRenderer::getComponentDisplayName)
But comparing actually has two type parameters, so it's a little weird that the above doesn't complain. Specifying both type parameters still produces the same error.
private static final Comparator<String> COMPARATOR = Comparator.<String, String>comparing(NoticeRenderer::getComponentDisplayName)
If I mistakenly put the type bounds on Comparator, I don't expect this to work, but it produces BUG! output:
private static final Comparator<String> COMPARATOR = Comparator<String, String>.comparing(NoticeRenderer::getComponentDisplayName)
BUG! exception in phase 'instruction selection' in source unit 'ConsoleScript34' Expected earlier checking to detect generics parameter arity mismatch
Expected: java.util.Comparator<T>
Supplied: java.util.Comparator<java.lang.String,java.lang.String>
In Java, you don't need the type information at all:
private static final Comparator<String> COMPARATOR = Comparator.comparing(NoticeRenderer::getComponentDisplayName);
If you wanted to be verbose in Java, you could specify the bounds:
private static final Comparator<String> COMPARATOR = Comparator.<String, String>comparing(NoticeRenderer::getComponentDisplayName);
As a workaround...
If I avoid the use of the method reference, I can make something pass the static compiler:
private static final Comparator<String> COMPARATOR = Comparator.<String>comparing( { String it -> getComponentDisplayName(it) })
I need both the type bound on comparing and the type of the parameter.