Skip to content

Commit 312ed11

Browse files
committed
GROOVY-7992
1 parent 8370dff commit 312ed11

File tree

6 files changed

+92
-41
lines changed

6 files changed

+92
-41
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/StaticCompilationTests.java

+24-2
Original file line numberDiff line numberDiff line change
@@ -7196,7 +7196,7 @@ public void testCompileStatic10033a() {
71967196
public void testCompileStatic10047() {
71977197
assumeTrue(isParrotParser());
71987198

7199-
for (String value : new String[] {"String::length", "String.&length", "s -> s.length()", "{s -> s.length()}"}) {
7199+
for (String value : new String[] {"String::length", "String.&length", "(String s) -> s.length()", "{String s -> s.length()}"}) {
72007200
//@formatter:off
72017201
String[] sources = {
72027202
"Main.groovy",
@@ -7215,7 +7215,29 @@ public void testCompileStatic10047() {
72157215
}
72167216

72177217
@Test
7218-
public void testCompileStatic10047x() {
7218+
public void testCompileStatic10047a() {
7219+
assumeTrue(isParrotParser());
7220+
7221+
for (String value : new String[] {"s -> s.length()", "{s -> s.length()}"}) { // no type for "s" -- should this work?
7222+
//@formatter:off
7223+
String[] sources = {
7224+
"Main.groovy",
7225+
"import static java.util.stream.Collectors.toMap\n" +
7226+
"import java.util.function.Function\n" +
7227+
"@groovy.transform.CompileStatic\n" +
7228+
"void test() {\n" +
7229+
" print(['a','bc','def'].stream().collect(toMap(Function.<String>identity(), " + value + ")))\n" +
7230+
"}\n" + // <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K>,Function<? super T,? extends U>)
7231+
"test()\n",
7232+
};
7233+
//@formatter:on
7234+
7235+
runConformTest(sources, "[a:1, bc:2, def:3]");
7236+
}
7237+
}
7238+
7239+
@Test
7240+
public void testCompileStatic10047b() {
72197241
assumeTrue(isParrotParser());
72207242

72217243
//@formatter:off

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java

+23
Original file line numberDiff line numberDiff line change
@@ -1755,6 +1755,29 @@ public void testTypeChecked7945() {
17551755
"----------\n");
17561756
}
17571757

1758+
@Test
1759+
public void testTypeChecked7992() {
1760+
//@formatter:off
1761+
String[] sources = {
1762+
"Main.groovy",
1763+
"@groovy.transform.TypeChecked\n" +
1764+
"void test() {\n" +
1765+
" Comparator<Object> cmp = { o1, o2 -> o1.toString() <=> o2.toString() }\n" +
1766+
" List<String> strings = ['foo','bar','baz']\n" +
1767+
" @groovy.transform.ASTTest(phase=INSTRUCTION_SELECTION, value={\n" +
1768+
" def type = node.getNodeMetaData(org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_TYPE)\n" +
1769+
" assert type.toString(false) == 'java.util.List<java.lang.String>'\n" +
1770+
" })\n" +
1771+
" def result = strings.sort(false, cmp)\n" +
1772+
" print(result)\n" +
1773+
"}\n" +
1774+
"test()\n",
1775+
};
1776+
//@formatter:on
1777+
1778+
runConformTest(sources, "[bar, baz, foo]");
1779+
}
1780+
17581781
@Test
17591782
public void testTypeChecked8001() {
17601783
//@formatter:off

base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

+15-13
Original file line numberDiff line numberDiff line change
@@ -1878,7 +1878,7 @@ public static ClassNode getCorrectedClassNode(ClassNode type, ClassNode superCla
18781878
return corrected;
18791879
}
18801880

1881-
private static void extractGenericsConnections(Map<GenericsTypeName, GenericsType> connections, GenericsType[] usage, GenericsType[] declaration) {
1881+
private static void extractGenericsConnections(final Map<GenericsTypeName, GenericsType> connections, final GenericsType[] usage, final GenericsType[] declaration) {
18821882
// if declaration does not provide generics, there is no connection to make
18831883
if (usage == null || declaration == null || declaration.length == 0) return;
18841884
final int n; if ((n = usage.length) != declaration.length) return;
@@ -1887,14 +1887,14 @@ private static void extractGenericsConnections(Map<GenericsTypeName, GenericsTyp
18871887
for (int i = 0; i < n; i += 1) {
18881888
GenericsType ui = usage[i];
18891889
GenericsType di = declaration[i];
1890-
if (di.isPlaceholder()) {
1890+
if (di.isPlaceholder()) { // di like "T"
18911891
connections.put(new GenericsTypeName(di.getName()), ui);
1892-
} else if (di.isWildcard()) {
1892+
} else if (di.isWildcard()) { // di like "?", "? super T", "? extends T", ...
18931893
ClassNode lowerBound = di.getLowerBound(), upperBounds[] = di.getUpperBounds();
1894-
if (ui.isWildcard()) {
1894+
if (ui.isWildcard()) { // ui like "?", "? super Type" or "? extends Type"
18951895
extractGenericsConnections(connections, ui.getLowerBound(), lowerBound);
18961896
extractGenericsConnections(connections, ui.getUpperBounds(), upperBounds);
1897-
/* GRECLIPSE edit -- GROOVY-9998
1897+
/* GRECLIPSE edit -- GROOVY-9998, GROOVY-10328, GROOVY-10499, et al.
18981898
} else {
18991899
ClassNode ui_type = ui.getType();
19001900
extractGenericsConnections(connections, ui_type, lowerBound);
@@ -1907,11 +1907,14 @@ private static void extractGenericsConnections(Map<GenericsTypeName, GenericsTyp
19071907
*/
19081908
} else if (!isUnboundedWildcard(di)) {
19091909
ClassNode boundType = lowerBound != null ? lowerBound : upperBounds[0];
1910-
if (boundType.isGenericsPlaceHolder() /* GROOVY-10765: */&& boundType != ui.getType()) {
1911-
ui = new GenericsType(ui.getType()); ui.setPlaceHolder(false); ui.setWildcard(true);
1912-
connections.put(new GenericsTypeName(boundType.getUnresolvedName()), ui);
1913-
} else { // di like "? super Iterable<T>" and ui like "Collection<Type>"
1910+
if (!boundType.isGenericsPlaceHolder()) {
1911+
// di like "? extends Iterable<T>" and ui like "Collection<Type>"
1912+
extractGenericsConnections(connections, ui.getType(), boundType);
1913+
} else if (lowerBound == null) { // di like "? extends T"
19141914
extractGenericsConnections(connections, ui.getType(), boundType);
1915+
} else { // 6731,8983,10047,10749 : di like "? super T"
1916+
ui = new GenericsType(ui.getType()); ui.setWildcard(true); // weak sauce
1917+
connections.put(new GenericsTypeName(boundType.getUnresolvedName()), ui);
19151918
}
19161919
}
19171920
// GRECLIPSE end
@@ -2077,10 +2080,9 @@ static ClassNode getCombinedBoundType(GenericsType genericsType) {
20772080
return genericsType.getType();
20782081
}
20792082

2080-
// GRECLIPSE add -- GROOVY-9998, GROOVY-10339, GROOVY-10499
2081-
static GenericsType getCombinedGenericsType(GenericsType gt1, GenericsType gt2) {
2082-
if (isUnboundedWildcard(gt1)) gt1 = gt1.getType().asGenericsType();
2083-
if (isUnboundedWildcard(gt2)) gt2 = gt2.getType().asGenericsType();
2083+
// GRECLIPSE add -- GROOVY-7992, GROOVY-9998, GROOVY-10339, GROOVY-10499, GROOVY-10765
2084+
static GenericsType getCombinedGenericsType(final GenericsType gt1, final GenericsType gt2) {
2085+
if (isUnboundedWildcard(gt1) != isUnboundedWildcard(gt2)) return isUnboundedWildcard(gt2) ? gt1 : gt2;
20842086
ClassNode cn1 = GenericsUtils.makeClassSafe0(CLASS_Type, gt1);
20852087
ClassNode cn2 = GenericsUtils.makeClassSafe0(CLASS_Type, gt2);
20862088
ClassNode lub = WideningCategories.lowestUpperBound(cn1, cn2);

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

+16-13
Original file line numberDiff line numberDiff line change
@@ -1804,14 +1804,14 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
18041804
for (int i = 0; i < n; i += 1) {
18051805
GenericsType ui = usage[i];
18061806
GenericsType di = declaration[i];
1807-
if (di.isPlaceholder()) {
1807+
if (di.isPlaceholder()) { // di like "T"
18081808
connections.put(new GenericsTypeName(di.getName()), ui);
1809-
} else if (di.isWildcard()) {
1809+
} else if (di.isWildcard()) { // di like "?", "? super T", "? extends T", ...
18101810
ClassNode lowerBound = di.getLowerBound(), upperBounds[] = di.getUpperBounds();
1811-
if (ui.isWildcard()) {
1811+
if (ui.isWildcard()) { // ui like "?", "? super Type" or "? extends Type"
18121812
extractGenericsConnections(connections, ui.getLowerBound(), lowerBound);
18131813
extractGenericsConnections(connections, ui.getUpperBounds(), upperBounds);
1814-
/* GRECLIPSE edit -- GROOVY-9998, GROOVY-10328
1814+
/* GRECLIPSE edit -- GROOVY-9998, GROOVY-10328, GROOVY-10499, et al.
18151815
} else {
18161816
ClassNode ui_type = ui.getType();
18171817
extractGenericsConnections(connections, ui_type, lowerBound);
@@ -1824,11 +1824,14 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
18241824
*/
18251825
} else if (!isUnboundedWildcard(di)) {
18261826
ClassNode boundType = lowerBound != null ? lowerBound : upperBounds[0];
1827-
if (boundType.isGenericsPlaceHolder() /* GROOVY-10765: */&& boundType != ui.getType()) {
1828-
ui = new GenericsType(ui.getType()); ui.setPlaceHolder(false); ui.setWildcard(true);
1829-
connections.put(new GenericsTypeName(boundType.getUnresolvedName()), ui);
1830-
} else { // di like "? super Iterable<T>" and ui like "Collection<Type>"
1827+
if (!boundType.isGenericsPlaceHolder()) {
1828+
// di like "? extends Iterable<T>" and ui like "Collection<Type>"
1829+
extractGenericsConnections(connections, ui.getType(), boundType);
1830+
} else if (lowerBound == null) { // di like "? extends T"
18311831
extractGenericsConnections(connections, ui.getType(), boundType);
1832+
} else { // 6731,8983,10047,10749 : di like "? super T"
1833+
ui = new GenericsType(ui.getType()); ui.setWildcard(true); // weak sauce
1834+
connections.put(new GenericsTypeName(boundType.getUnresolvedName()), ui);
18321835
}
18331836
}
18341837
// GRECLIPSE end
@@ -1982,11 +1985,11 @@ static ClassNode getCombinedBoundType(final GenericsType genericsType) {
19821985
return genericsType.getType();
19831986
}
19841987

1985-
static GenericsType getCombinedGenericsType(GenericsType gt1, GenericsType gt2) {
1986-
// GRECLIPSE add -- GROOVY-9998, GROOVY-10339, GROOVY-10499
1987-
if (isUnboundedWildcard(gt1)) gt1 = gt1.getType().asGenericsType();
1988-
if (isUnboundedWildcard(gt2)) gt2 = gt2.getType().asGenericsType();
1989-
// GRECLIPSE end
1988+
static GenericsType getCombinedGenericsType(final GenericsType gt1, final GenericsType gt2) {
1989+
// GROOVY-7992, GROOVY-10765: "? super T" for gt1 or gt2?
1990+
if (isUnboundedWildcard(gt1) != isUnboundedWildcard(gt2))
1991+
return isUnboundedWildcard(gt2) ? gt1 : gt2;
1992+
// GROOVY-10339
19901993
ClassNode cn1 = GenericsUtils.makeClassSafe0(CLASS_Type, gt1);
19911994
ClassNode cn2 = GenericsUtils.makeClassSafe0(CLASS_Type, gt2);
19921995
ClassNode lub = WideningCategories.lowestUpperBound(cn1, cn2);

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

-1
Original file line numberDiff line numberDiff line change
@@ -5903,7 +5903,6 @@ protected ClassNode inferReturnTypeGenerics(final ClassNode receiver, final Meth
59035903
}
59045904
}
59055905
*/
5906-
for (GenericsType gt : methodGenericTypes) resolvedPlaceholders.put(new GenericsTypeName(gt.getName()), gt);
59075906
applyGenericsConnections(extractGenericsConnectionsFromArguments(methodGenericTypes, Arrays.stream(method.getParameters()).map(param ->
59085907
new Parameter(applyGenericsContext(context, param.getType()), param.getName())
59095908
).toArray(Parameter[]::new), arguments, explicitTypeHints), resolvedPlaceholders);

base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

+14-12
Original file line numberDiff line numberDiff line change
@@ -1779,25 +1779,26 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
17791779
// both have generics
17801780
for (int i = 0, n = usage.length; i < n; i += 1) {
17811781
GenericsType ui = usage[i], di = declaration[i];
1782-
if (di.isPlaceholder()) {
1782+
if (di.isPlaceholder()) { // di like "T"
17831783
storeGenericsConnection(connections, di.getName(), ui);
1784-
} else if (di.isWildcard()) {
1784+
} else if (di.isWildcard()) { // di like "?", "? super T", "? extends T", ...
17851785
ClassNode lowerBound = di.getLowerBound(), upperBounds[] = di.getUpperBounds();
1786-
if (ui.isWildcard()) {
1786+
if (ui.isWildcard()) { // ui like "?", "? super Type" or "? extends Type"
17871787
extractGenericsConnections(connections, ui.getLowerBound(), lowerBound);
17881788
extractGenericsConnections(connections, ui.getUpperBounds(), upperBounds);
17891789
} else if (!isUnboundedWildcard(di)) {
17901790
ClassNode boundType = lowerBound != null ? lowerBound : upperBounds[0];
1791-
if (boundType.isGenericsPlaceHolder() // GROOVY-9998
1792-
&& boundType != ui.getType()) { // GROOVY-10765
1791+
if (boundType.isGenericsPlaceHolder()) { // di like "? extends/super T"
1792+
// 6731,7992,8983,9998,10047,10499,10749,10765,...
1793+
ui = new GenericsType(ui.getType()); // erase type
1794+
if (lowerBound != null) ui.setWildcard(true); // weak
17931795
String placeholderName = boundType.getUnresolvedName();
1794-
ui = new GenericsType(ui.getType()); ui.setWildcard(true);
17951796
storeGenericsConnection(connections, placeholderName, ui);
1796-
} else { // di like "? super Collection<T>" and ui like "List<Type>"
1797+
} else { // di like "? extends Iterable<T>" and ui like "List<Type>"
17971798
extractGenericsConnections(connections, ui.getType(), boundType);
17981799
}
17991800
}
1800-
} else {
1801+
} else { // di like "List<T>", "List<Type>", "List<? extends T>", ...
18011802
extractGenericsConnections(connections, ui.getType(), di.getType());
18021803
}
18031804
}
@@ -1950,10 +1951,11 @@ static ClassNode getCombinedBoundType(final GenericsType genericsType) {
19501951
return genericsType.getType();
19511952
}
19521953

1953-
static GenericsType getCombinedGenericsType(GenericsType gt1, GenericsType gt2) {
1954-
// GROOVY-9998, GROOVY-10499: unpack "?" that is from "? extends T"
1955-
if (isUnboundedWildcard(gt1)) gt1 = gt1.getType().asGenericsType();
1956-
if (isUnboundedWildcard(gt2)) gt2 = gt2.getType().asGenericsType();
1954+
static GenericsType getCombinedGenericsType(final GenericsType gt1, final GenericsType gt2) {
1955+
// GROOVY-7992, GROOVY-10765: "? super T" for gt1 or gt2?
1956+
if (isUnboundedWildcard(gt1) != isUnboundedWildcard(gt2))
1957+
return isUnboundedWildcard(gt2) ? gt1 : gt2;
1958+
// GROOVY-10315, GROOVY-10317, GROOVY-10339, ...
19571959
ClassNode cn1 = GenericsUtils.makeClassSafe0(CLASS_Type, gt1);
19581960
ClassNode cn2 = GenericsUtils.makeClassSafe0(CLASS_Type, gt2);
19591961
ClassNode lub = lowestUpperBound(cn1, cn2);

0 commit comments

Comments
 (0)