(groovy) 01/01: GROOVY-8084, GROOVY-9074, GROOVY-10588: STC: implement wildcard capture

2024-11-12 Thread emilles
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY-9074
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit de13eec22e6874afc42e477da367ef6dc5051726
Author: Eric Milles 
AuthorDate: Mon Nov 11 15:44:23 2024 -0600

GROOVY-8084, GROOVY-9074, GROOVY-10588: STC: implement wildcard capture
---
 .../transform/stc/StaticTypeCheckingSupport.java   |  10 +-
 src/spec/doc/core-semantics.adoc   |  17 +-
 src/spec/test/typing/TypeCheckingTest.groovy   |  30 ++-
 src/test/groovy/bugs/Groovy8084Bug.groovy  |  39 
 src/test/groovy/bugs/Groovy9074.groovy |  81 +--
 src/test/groovy/transform/stc/BugsSTCTest.groovy   |   8 -
 .../groovy/transform/stc/GenericsSTCTest.groovy| 259 +++--
 .../transform/stc/MethodReferenceTest.groovy   |   6 +-
 .../transform/stc/TypeInferenceSTCTest.groovy  |  14 +-
 9 files changed, 241 insertions(+), 223 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index bcf521910c..f79c62daac 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1346,6 +1346,7 @@ public abstract class StaticTypeCheckingSupport {
 if (type.isGenericsPlaceHolder()) {
 GenericsType gt = placeholders.get(new 
GenericsTypeName(type.getUnresolvedName()));
 if (gt != null) {
+if (gt.isWildcard()) return new ClassNode("capture-of " + gt, 
0, getCombinedBoundType(gt));
 return gt.getType();
 }
 ClassNode cn = extractType(type.asGenericsType()); // GROOVY-10756
@@ -1524,9 +1525,9 @@ public abstract class StaticTypeCheckingSupport {
 resolvedMethodGenerics.put(entry.getKey(), candidate);
 continue;
 } else if (!candidate.isPlaceholder() && 
!candidate.isWildcard()) {
-// combine "T=Integer" and "T=String" to produce "T=? 
extends Serializable & Comparable<...>"
+// combine "T=Integer" and "T=String" to produce 
"T=(Serializable & ... )"
 ClassNode lub = lowestUpperBound(candidate.getType(), 
resolved.getType());
-resolvedMethodGenerics.put(entry.getKey(), 
lub.asGenericsType());
+resolvedMethodGenerics.put(entry.getKey(), new 
GenericsType(lub));
 continue;
 }
 }
@@ -1559,6 +1560,11 @@ public abstract class StaticTypeCheckingSupport {
 }
 
 private static boolean compatibleConnection(final GenericsType resolved, 
final GenericsType connection) {
+if (resolved.isWildcard()
+// TODO: figure out capture of super
+&& resolved.getLowerBound() == null) {
+return false; // GROOVY-8084, GROOVY-9074, GROOVY-10588
+}
 if (resolved.isPlaceholder()
 &&  resolved.getUpperBounds() != null
 &&  resolved.getUpperBounds().length == 1
diff --git a/src/spec/doc/core-semantics.adoc b/src/spec/doc/core-semantics.adoc
index b217c9c445..8a74339de5 100644
--- a/src/spec/doc/core-semantics.adoc
+++ b/src/spec/doc/core-semantics.adoc
@@ -1777,8 +1777,8 @@ can assign to the variable:
 
 
include::../test/typing/TypeCheckingTest.groovy[tags=flowtyping_typeconstraints,indent=0]
 
-<1> `list` is declared as an unchecked `List` and assigned a list literal of 
`String`s
-<2> this line passes compilation because of flow typing: the type checker 
knows that `list` is at this point a `List`
+<1> `list` is declared as an unchecked `List` and assigned a list literal of 
strings
+<2> this line passes compilation because of flow typing: the type checker 
knows that `list` is at this point an `ArrayList`
 <3> but you can't assign a `String` to a `List` so this is a type checking 
error
 
 You can also note that even if the variable is declared *without* generics 
information, the type checker knows what is
@@ -1788,18 +1788,21 @@ the component type. Therefore, such code would fail 
compilation:
 
 
include::../test/typing/TypeCheckingTest.groovy[tags=flowtyping_typeconstraints_failure,indent=0]
 
-<1> `list` is inferred as `List`
-<2> so adding an `int` to a `List` is a compile-time error
+<1> `list` is inferred as `ArrayList`
+<2> so adding an `int` to a `ArrayList` is a compile-time error
+<3> `list` is declared as `List`
+<4> the inferred type of `list` here is `List`, so calling 
`addAll` with a list of anything is a compile-time error
+<5> and calling `add` with an `int` is also a compile-time error for the same 
reason; only `add(null)` is allowed
 
-Fixing this requires adding an explicit generi

(groovy) 01/01: GROOVY-8084, GROOVY-9074, GROOVY-10588: STC: implement wildcard capture

2024-11-11 Thread emilles
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY-9074
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 9dcfcb9c501f365d8fc431234f8359504adfbae6
Author: Eric Milles 
AuthorDate: Mon Nov 11 15:44:23 2024 -0600

GROOVY-8084, GROOVY-9074, GROOVY-10588: STC: implement wildcard capture
---
 .../transform/stc/StaticTypeCheckingSupport.java   |   6 +
 src/spec/doc/core-semantics.adoc   |  17 +-
 src/spec/test/typing/TypeCheckingTest.groovy   |  30 ++-
 src/test/groovy/bugs/Groovy8084Bug.groovy  |  39 
 src/test/groovy/bugs/Groovy9074.groovy |  81 +---
 src/test/groovy/transform/stc/BugsSTCTest.groovy   |   8 -
 .../groovy/transform/stc/GenericsSTCTest.groovy| 223 +++--
 .../transform/stc/MethodReferenceTest.groovy   |   6 +-
 .../transform/stc/TypeInferenceSTCTest.groovy  |  14 +-
 9 files changed, 215 insertions(+), 209 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index bcf521910c..d833c6ce0b 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1346,6 +1346,7 @@ public abstract class StaticTypeCheckingSupport {
 if (type.isGenericsPlaceHolder()) {
 GenericsType gt = placeholders.get(new 
GenericsTypeName(type.getUnresolvedName()));
 if (gt != null) {
+if (gt.isWildcard()) return new ClassNode("capture-of " + gt, 
0, getCombinedBoundType(gt));
 return gt.getType();
 }
 ClassNode cn = extractType(type.asGenericsType()); // GROOVY-10756
@@ -1559,6 +1560,11 @@ public abstract class StaticTypeCheckingSupport {
 }
 
 private static boolean compatibleConnection(final GenericsType resolved, 
final GenericsType connection) {
+if (resolved.isWildcard()
+// TODO: figure out capture of super
+&& resolved.getLowerBound() == null) {
+return false; // GROOVY-8084, GROOVY-9074, GROOVY-10588
+}
 if (resolved.isPlaceholder()
 &&  resolved.getUpperBounds() != null
 &&  resolved.getUpperBounds().length == 1
diff --git a/src/spec/doc/core-semantics.adoc b/src/spec/doc/core-semantics.adoc
index b217c9c445..8a74339de5 100644
--- a/src/spec/doc/core-semantics.adoc
+++ b/src/spec/doc/core-semantics.adoc
@@ -1777,8 +1777,8 @@ can assign to the variable:
 
 
include::../test/typing/TypeCheckingTest.groovy[tags=flowtyping_typeconstraints,indent=0]
 
-<1> `list` is declared as an unchecked `List` and assigned a list literal of 
`String`s
-<2> this line passes compilation because of flow typing: the type checker 
knows that `list` is at this point a `List`
+<1> `list` is declared as an unchecked `List` and assigned a list literal of 
strings
+<2> this line passes compilation because of flow typing: the type checker 
knows that `list` is at this point an `ArrayList`
 <3> but you can't assign a `String` to a `List` so this is a type checking 
error
 
 You can also note that even if the variable is declared *without* generics 
information, the type checker knows what is
@@ -1788,18 +1788,21 @@ the component type. Therefore, such code would fail 
compilation:
 
 
include::../test/typing/TypeCheckingTest.groovy[tags=flowtyping_typeconstraints_failure,indent=0]
 
-<1> `list` is inferred as `List`
-<2> so adding an `int` to a `List` is a compile-time error
+<1> `list` is inferred as `ArrayList`
+<2> so adding an `int` to a `ArrayList` is a compile-time error
+<3> `list` is declared as `List`
+<4> the inferred type of `list` here is `List`, so calling 
`addAll` with a list of anything is a compile-time error
+<5> and calling `add` with an `int` is also a compile-time error for the same 
reason; only `add(null)` is allowed
 
-Fixing this requires adding an explicit generic type to the declaration:
+Fixing this requires adding an explicit, non-wildcard type argument:
 
 [source,groovy]
 
 
include::../test/typing/TypeCheckingTest.groovy[tags=flowtyping_typeconstraints_fixed,indent=0]
 
-<1> `list` declared as `List` and initialized with an 
empty list
+<1> `list` is declared as `List` and initialized with an empty 
list
 <2> elements added to the list conform to the declaration type of the list
-<3> so adding an `int` to a `List` is allowed
+<3> and adding an integer is allowed
 
 Flow typing has been introduced to reduce the difference in semantics between 
classic and static Groovy. In particular,
 consider the behavior of this code in Java:
diff --git a/src/spec/test/typing/TypeCheckingTest.groovy 
b/src/spec/test/typing/TypeCheckingTest.groovy
index f4f4f16812..1b36511eb9 100644
--- a/src/spec/test/typing