(groovy) 01/01: GROOVY-8084, GROOVY-9074, GROOVY-10588: STC: implement wildcard capture
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
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