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 <eric.mil...@thomsonreuters.com>
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<String>`
+<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<String>`
 <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<String>`
-<2> so adding an `int` to a `List<String>` is a compile-time error
+<1> `list` is inferred as `ArrayList<String>`
+<2> so adding an `int` to a `ArrayList<String>` is a compile-time error
+<3> `list` is declared as `List<?>`
+<4> the inferred type of `list` here is `List<capture-of ?>`, 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<? extends Serializable>` and initialized with an 
empty list
+<1> `list` is declared as `List<Serializable>` 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<? extends Serializable>` 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/TypeCheckingTest.groovy
+++ b/src/spec/test/typing/TypeCheckingTest.groovy
@@ -688,32 +688,40 @@ import static 
org.codehaus.groovy.ast.tools.WideningCategories.lowestUpperBound
             }
             // end::flowtyping_typeconstraints[]
             flowTypingWithExplicitType()
-        ''', 'Cannot assign value of type java.lang.String to variable of type 
java.util.List'
+        ''',
+        'Cannot assign value of type java.lang.String to variable of type 
java.util.List'
     }
 
-    void testFlowTypingTypeConstraintsFailure() {
+    void testFlowTypingTypeConstraints2() {
         shouldFailWithMessages '''
             // tag::flowtyping_typeconstraints_failure[]
             @groovy.transform.TypeChecked
-            void flowTypingWithExplicitType() {
-                List list = ['a','b','c']           // <1>
+            void flowTypingTypeConstraints1() {
+                def list = ['a','b','c']            // <1>
                 list.add(1)                         // <2>
             }
+            @groovy.transform.TypeChecked
+            void flowTypingTypeConstraints2() {
+                List<?> list = []                   // <3>
+                list.addAll(['a','b','c'])          // <4>
+                list.add(1)                         // <5>
+            }
             // end::flowtyping_typeconstraints_failure[]
-            flowTypingWithExplicitType()
         ''',
-        'Cannot call java.util.ArrayList#add(java.lang.String) with arguments 
[int]'
+        'Cannot call java.util.ArrayList#add(java.lang.String) with arguments 
[int]',
+        'Cannot call java.util.ArrayList#addAll(java.util.Collection<? extends 
capture-of ?>) with arguments [java.util.ArrayList<java.lang.String>]',
+        'Cannot call java.util.ArrayList#add(capture-of ?) with arguments 
[int]'
 
         assertScript '''
             // tag::flowtyping_typeconstraints_fixed[]
             @groovy.transform.TypeChecked
-            void flowTypingWithExplicitType() {
-                List<? extends Serializable> list = []                      // 
<1>
-                list.addAll(['a','b','c'])                                  // 
<2>
-                list.add(1)                                                 // 
<3>
+            void flowTypingTypeConstraints3() {
+                List<Serializable> list = []        // <1>
+                list.addAll(['a','b','c'])          // <2>
+                list.add(1)                         // <3>
             }
             // end::flowtyping_typeconstraints_fixed[]
-            flowTypingWithExplicitType()
+            flowTypingTypeConstraints3()
         '''
     }
 
diff --git a/src/test/groovy/bugs/Groovy8084Bug.groovy 
b/src/test/groovy/bugs/Groovy8084Bug.groovy
deleted file mode 100644
index a2c34d4e5f..0000000000
--- a/src/test/groovy/bugs/Groovy8084Bug.groovy
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package groovy.bugs
-
-import gls.CompilableTestSupport
-import groovy.test.NotYetImplemented
-
-class Groovy8084Bug extends CompilableTestSupport {
-    // TODO REFINE ME
-    void testGroovy8084Bug() {
-        assertScript '''
-            import groovy.transform.CompileStatic
-
-            @CompileStatic
-            static def method(List<? extends Serializable> captured) {
-                captured.add('some string') // though the test passes now, but 
I expect a STC error here because of adding an element to a producer, which is 
not allowed in Java
-                return captured
-            }
-
-            println method(new ArrayList<Integer>())
-        '''
-    }
-}
diff --git a/src/test/groovy/bugs/Groovy9074.groovy 
b/src/test/groovy/bugs/Groovy9074.groovy
index f518ee5355..449a0dcdc7 100644
--- a/src/test/groovy/bugs/Groovy9074.groovy
+++ b/src/test/groovy/bugs/Groovy9074.groovy
@@ -18,84 +18,16 @@
  */
 package groovy.bugs
 
-import groovy.test.GroovyTestCase
-import groovy.transform.CompileStatic
 import org.codehaus.groovy.control.CompilationUnit
+import org.junit.Test
 
+import static groovy.test.GroovyAssert.shouldFail
 import static org.codehaus.groovy.control.Phases.CLASS_GENERATION
 
-@CompileStatic
-final class Groovy9074 extends GroovyTestCase {
+final class Groovy9074 {
 
-    void _FIXME_testWildcardCapture() {
-        def err = shouldFail '''
-            @groovy.transform.TypeChecked
-            class Main {
-                private static Collection<?> c = new ArrayList<String>()
-                static main(args) {
-                    c.add(new Object())
-                }
-            }
-        '''
-
-        // TODO: This is just a sample message; Java produces this for the 
equivalent code.
-        assert err =~ / The method add\(capture#1-of \?\) in the type 
Collection<capture#1-of \?> is not applicable for the arguments \(Object\)/
-    }
-
-    void _FIXME_testWildcardExtends() {
-        def err = shouldFail '''
-            import java.awt.Canvas
-            abstract class Shape {
-                abstract void draw(Canvas c)
-            }
-            class Circle extends Shape {
-                private int x, y, radius
-                @Override void draw(Canvas c) {}
-            }
-            class Rectangle extends Shape {
-                private int x, y, width, height
-                @Override void draw(Canvas c) {}
-            }
-
-            @groovy.transform.TypeChecked
-            void addRectangle(List<? extends Shape> shapes) {
-                shapes.add(0, new Rectangle()) // TODO: compile-time error!
-            }
-        '''
-
-        // TODO: This is just a sample message; Java produces this for the 
equivalent code.
-        assert err =~ / The method add(capture#1-of \?) in the type 
List<capture#1-of \?> is not applicable for the arguments \(Rectangle\)/
-    }
-
-    void testWildcardSuper() {
-        assertScript '''
-            import java.awt.Canvas
-            abstract class Shape {
-                abstract void draw(Canvas c)
-            }
-            class Circle extends Shape {
-                private int x, y, radius
-                @Override void draw(Canvas c) {}
-            }
-            class Rectangle extends Shape {
-                private int x, y, width, height
-                @Override void draw(Canvas c) {}
-            }
-
-            @groovy.transform.TypeChecked
-            void addRectangle(List<? super Shape> shapes) {
-                shapes.add(0, new Rectangle())
-            }
-
-            List<Shape> list = []
-            addRectangle(list)
-
-            assert list.size() == 1
-            assert list.get(0) instanceof Rectangle
-        '''
-    }
-
-    void testWildcardExtends2() {
+    @Test
+    void testWildcardExtends() {
         new CompilationUnit().with {
             addSource 'Main.groovy', '''
                 class Factory {
@@ -124,7 +56,8 @@ final class Groovy9074 extends GroovyTestCase {
         }
     }
 
-    void testWildcardSuper2() {
+    @Test
+    void testWildcardSuper() {
         new CompilationUnit().with {
             addSource 'Main.groovy', '''
                 class Factory {
diff --git a/src/test/groovy/transform/stc/BugsSTCTest.groovy 
b/src/test/groovy/transform/stc/BugsSTCTest.groovy
index d248cd4af0..020e7f7a58 100644
--- a/src/test/groovy/transform/stc/BugsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/BugsSTCTest.groovy
@@ -279,14 +279,6 @@ class BugsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    void testGroovyObjectInGenerics() {
-        assertScript '''
-            class A {}
-            List<? extends GroovyObject> list = new LinkedList<? extends 
GroovyObject>()
-            list.add(new A())
-        '''
-    }
-
     // GROOVY-5656
     void testShouldNotThrowAmbiguousMethodError() {
         assertScript '''import groovy.transform.*
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy 
b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 46c2b73b1c..f1dc0c97a9 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -53,45 +53,52 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         'Incompatible generic argument types. Cannot assign 
java.util.HashMap<java.lang.String, java.lang.Integer> to: java.util.Map<? 
extends java.lang.CharSequence, java.lang.String>'
     }
 
-    void testAddOnList() {
-        shouldFailWithMessages '''
-            List<String> list = []
-            list.add(1)
-        ''',
-        'Cannot call java.util.ArrayList#add(java.lang.String) with arguments 
[int]'
-    }
-
-    void testAddOnList2() {
+    void testAddOnList1() {
         assertScript '''
             List<String> list = []
-            list.add 'Hello'
+            list.add('string')
         '''
 
         assertScript '''
-            List<Integer> list = []
-            list.add 1
+            List<Number> list = []
+            list.add(1)
         '''
     }
 
-    void testAddOnListWithDiamond() {
+    void testAddOnList2() {
         assertScript '''
             List<String> list = new LinkedList<>()
-            list.add 'Hello'
+            list.add('string')
         '''
     }
 
-    void testAddOnListUsingLeftShift() {
+    void testAddOnList3() {
         shouldFailWithMessages '''
             List<String> list = []
-            list << 1
+            list.add(1)
         ''',
-        'Cannot call <T> 
org.codehaus.groovy.runtime.DefaultGroovyMethods#leftShift(java.util.List<T>, 
T) with arguments [java.util.ArrayList<java.lang.String>, int]'
+        'Cannot call java.util.ArrayList#add(java.lang.String) with arguments 
[int]'
     }
 
-    void testAddOnList2UsingLeftShift() {
+    // GROOVY-9074
+    void testAddOnList4() {
+        shouldFailWithMessages '''
+            List<?> list = []
+            list.add(1)
+        ''',
+        'Cannot call java.util.ArrayList#add(capture-of ?) with arguments 
[int]'
+
+        shouldFailWithMessages '''
+            List<? extends Number> list = []
+            list.add(1)
+        ''',
+        'Cannot call java.util.ArrayList#add(capture-of ? extends 
java.lang.Number) with arguments [int]'
+    }
+
+    void testAddOnListUsingLeftShift1() {
         assertScript '''
             List<String> list = []
-            list << 'Hello'
+            list << 'string'
         '''
 
         assertScript '''
@@ -100,12 +107,20 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    void testAddOnListWithParameterizedTypeLeftShift() {
-        assertScript '''
-            class Trie<T> {}
-            List<Trie<String>> list = []
-            list << new Trie<String>()
-        '''
+    void testAddOnListUsingLeftShift2() {
+        shouldFailWithMessages '''
+            List<String> list = []
+            list << 1
+        ''',
+        'Cannot call <T> 
org.codehaus.groovy.runtime.DefaultGroovyMethods#leftShift(java.util.List<T>, 
T) with arguments [java.util.ArrayList<java.lang.String>, int]'
+    }
+
+    void testAddOnListUsingLeftShift3() {
+        shouldFailWithMessages '''
+            def list = (List<? extends Number>) []
+            list << 1
+        ''',
+        'Cannot call <T> 
org.codehaus.groovy.runtime.DefaultGroovyMethods#leftShift(java.util.List<T>, 
T) with arguments [java.util.List<? extends java.lang.Number>, int]'
     }
 
     void testAddOnListWithDiamondUsingLeftShift() {
@@ -115,6 +130,14 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    void testAddOnListWithParameterizedTypeLeftShift() {
+        assertScript '''
+            class Trie<T> {}
+            List<Trie<String>> list = []
+            list << new Trie<String>()
+        '''
+    }
+
     void testListInferenceWithNullElems() {
         assertScript '''
             List<String> strings = ['a', null]
@@ -1923,6 +1946,20 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase 
{
         'Cannot assign java.util.ArrayList<java.lang.String> to: 
java.util.List<? super java.lang.Number>'
     }
 
+    // GROOVY-10371
+    void testAssignmentShouldFailBecauseOfUpperBound() {
+        shouldFailWithMessages '''
+            class A<X> {
+            }
+            class B<Y> extends A<Y> {
+            }
+
+            B<? extends Number> x = new B<Double>()
+            A<Number> y = x
+        ''',
+        'Incompatible generic argument types. Cannot assign 
B<java.lang.Double> to: A<java.lang.Number>'
+    }
+
     // GROOVY-9914, GROOVY-10036
     void testAssignmentShouldWorkForParameterizedMap() {
         assertScript '''
@@ -2447,20 +2484,19 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
             class Test {
                 static test2() {
                     if (new Random().nextBoolean()) {
-                        def a = new ArrayList<String>()
-                        a << "a" << "b" << "c"
-                        return a
+                        def list = new ArrayList<String>()
+                        list << "a" << "b" << "c"
+                        return list
                     } else {
-                        def b = new LinkedList<Number>()
-                        b << 1 << 2 << 3
-                        return b
+                        def list = new LinkedList<Integer>()
+                        list << 1 << 2 << 3
+                        return list
                     }
                 }
 
                 static test() {
                     def result = test2()
                     result[0].toInteger()
-                    //result[0].toString()
                 }
             }
             new Test()
@@ -2958,12 +2994,12 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
             Map<Date, Integer> map = [:]
 
             @ASTTest(phase=INSTRUCTION_SELECTION, value={
-                def infType = node.getNodeMetaData(INFERRED_TYPE)
-                assert infType == make(Set)
-                def entryInfType = infType.genericsTypes[0].type
-                assert entryInfType == make(Map.Entry)
-                assert entryInfType.genericsTypes[0].type == make(Date)
-                assert entryInfType.genericsTypes[1].type == Integer_TYPE
+                Object type = node.getNodeMetaData(INFERRED_TYPE)
+                assert type == SET_TYPE
+                       type = type.genericsTypes[0].type
+                assert type == make(Map.Entry)
+                assert type.genericsTypes[0].type == make(Date)
+                assert type.genericsTypes[1].type == Integer_TYPE
             })
             def entries = map?.entrySet()
         '''
@@ -2974,12 +3010,12 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
             List<Map<Date, Integer>> maps = []
 
             @ASTTest(phase=INSTRUCTION_SELECTION, value={
-                def listType = node.getNodeMetaData(INFERRED_TYPE)
-                assert listType == Iterator_TYPE
-                def infType = listType.genericsTypes[0].type
-                assert infType == make(Map)
-                assert infType.genericsTypes[0].type == make(Date)
-                assert infType.genericsTypes[1].type == Integer_TYPE
+                Object type = node.getNodeMetaData(INFERRED_TYPE)
+                assert type == Iterator_TYPE
+                       type = type.genericsTypes[0].type
+                assert type == MAP_TYPE
+                assert type.genericsTypes[0].type == make(Date)
+                assert type.genericsTypes[1].type == Integer_TYPE
             })
             def iter = maps?.iterator()
         '''
@@ -3304,12 +3340,12 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
     void testUncheckedAssignment() {
         assertScript '''
             @ASTTest(phase=INSTRUCTION_SELECTION, value={
-                def ift = node.getNodeMetaData(INFERRED_TYPE)
-                assert ift == make(List)
-                assert ift.isUsingGenerics()
-                def gts = ift.genericsTypes
-                assert gts.length==1
-                assert gts[0].type == STRING_TYPE
+                Object type = node.getNodeMetaData(INFERRED_TYPE)
+                assert type == LIST_TYPE
+                assert type.isUsingGenerics()
+                Object args = type.genericsTypes
+                assert args.length == 1
+                assert args[0].type == STRING_TYPE
             })
             List<String> list = (List) null
         '''
@@ -3318,12 +3354,12 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
     void testUncheckedAssignmentWithSuperInterface() {
         assertScript '''
             @ASTTest(phase=INSTRUCTION_SELECTION, value={
-                def ift = node.getNodeMetaData(INFERRED_TYPE)
-                assert ift == LIST_TYPE
-                def gts = ift.genericsTypes
-                assert gts != null
-                assert gts.length == 1
-                assert gts[0].type == STRING_TYPE
+                Object type = node.getNodeMetaData(INFERRED_TYPE)
+                assert type == LIST_TYPE
+                Object args = type.genericsTypes
+                assert args != null
+                assert args.length == 1
+                assert args[0].type == STRING_TYPE
             })
             Iterable<String> list = (List) null
         '''
@@ -3348,7 +3384,11 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase 
{
     // GROOVY-5692
     void testCompatibleArgumentsForPlaceholders2() {
         assertScript '''
-            def <T> boolean test(T one, List<T> many) { }
+            def <T> void test(T one, List<T> many) { }
+            test(1,[2,3])
+        '''
+        assertScript '''
+            def <T> void test(T one, List<? extends T> many) { }
             test(1,["II","III"])
         '''
     }
@@ -3852,7 +3892,18 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase 
{
         '''
     }
 
-    void testOutOfBoundsByExtendsGenericParameterType() {
+    // GROOVY-10588
+    void testOutOfBoundsByUnboundedGenericParameterType() {
+        shouldFailWithMessages '''
+            Map<String,?> one = [:]
+            Map<String,?> getTwo() { [:] }
+            def one_plus_two = one + two // <K,V> Map<K,V> plus(Map<K,V> left, 
Map<K,V> right)
+        ''',
+        'Cannot call <K,V> 
org.codehaus.groovy.runtime.DefaultGroovyMethods#plus(java.util.Map<K, V>, 
java.util.Map<K, V>)' +
+        ' with arguments [java.util.LinkedHashMap<java.lang.String, ?>, 
java.util.Map<java.lang.String, ? extends java.lang.Object>]'
+    }
+
+    void testOutOfBoundsByExtendsGenericParameterType1() {
         shouldFailWithMessages '''
             class Foo {
                 static <T extends List<? extends CharSequence>> void bar(T a) 
{}
@@ -3862,29 +3913,93 @@ class GenericsSTCTest extends 
StaticTypeCheckingTestCase {
         'Cannot call <T extends java.util.List<? extends 
java.lang.CharSequence>> Foo#bar(T) with arguments 
[java.util.ArrayList<java.lang.Object>]'
     }
 
-    void testOutOfBoundsBySuperGenericParameterType() {
+    void testOutOfBoundsByExtendsGenericParameterType2() {
         shouldFailWithMessages '''
             class Foo {
-                static <T extends List<? super CharSequence>> void bar(T a) {}
+                static <T extends List<? extends CharSequence>> void bar(T 
list) {}
+            }
+            def <U extends List<Object>> void baz(U list) {
+                Foo.bar(list)
             }
-            Foo.bar(['abc'])
         ''',
-        'Cannot call <T extends java.util.List<? super 
java.lang.CharSequence>> Foo#bar(T) with arguments 
[java.util.ArrayList<java.lang.String>]'
+        'Cannot call <T extends java.util.List<? extends 
java.lang.CharSequence>> Foo#bar(T) with arguments [U]'
     }
 
-    void testOutOfBoundsByExtendsPlaceholderParameterType() {
+    // GROOVY-8084
+    void testOutOfBoundsByExtendsGenericParameterType3() {
         shouldFailWithMessages '''
             class Foo {
-                static <T extends List<? extends CharSequence>> void bar(T 
list) {}
+                static m(List<? extends Serializable> list) {
+                    list.add('string')
+                }
             }
-            def <U extends List<Object>> void baz(U list) {
-                Foo.bar(list)
+            Foo.bar(new ArrayList<Integer>())
+        ''',
+        'Cannot call java.util.List#add(capture-of ? extends 
java.io.Serializable) with arguments [java.lang.String]',
+        'Cannot find matching method 
java.lang.Class#bar(java.util.ArrayList<java.lang.Integer>) or static method 
Foo#bar(java.util.ArrayList<java.lang.Integer>)'
+    }
+
+    // GROOVY-9074
+    void testOutOfBoundsByExtendsGenericParameterType4() {
+        shouldFailWithMessages '''
+            import java.awt.Canvas
+            abstract class Shape {
+                abstract void draw(Canvas c)
+            }
+            class Circle extends Shape {
+                private int x, y, radius
+                @Override void draw(Canvas c) {}
+            }
+            class Rectangle extends Shape {
+                private int x, y, width, height
+                @Override void draw(Canvas c) {}
+            }
+
+            void addRectangle(List<? extends Shape> shapes) {
+                shapes.add(0, new Rectangle())
             }
         ''',
-        'Cannot call <T extends java.util.List<? extends 
java.lang.CharSequence>> Foo#bar(T) with arguments [U]'
+        'Cannot call java.util.List#add(int, capture-of ? extends Shape) with 
arguments [int, Rectangle]'
+    }
+
+    void testNotOutOfBoundsBySuperGenericParameterType() {
+        assertScript '''
+            import java.awt.Canvas
+            abstract class Shape {
+                abstract void draw(Canvas c)
+            }
+            class Circle extends Shape {
+                private int x, y, radius
+                @Override void draw(Canvas c) {}
+            }
+            class Rectangle extends Shape {
+                private int x, y, width, height
+                @Override void draw(Canvas c) {}
+            }
+
+            void addRectangle(List<? super Shape> shapes) {
+                shapes.add(0, new Rectangle())
+            }
+
+            List<Shape> list = []
+            addRectangle(list)
+
+            assert list.size() == 1
+            assert list.get(0) instanceof Rectangle
+        '''
+    }
+
+    void testOutOfBoundsBySuperGenericParameterType1() {
+        shouldFailWithMessages '''
+            class Foo {
+                static <T extends List<? super CharSequence>> void bar(T a) {}
+            }
+            Foo.bar(['abc'])
+        ''',
+        'Cannot call <T extends java.util.List<? super 
java.lang.CharSequence>> Foo#bar(T) with arguments 
[java.util.ArrayList<java.lang.String>]'
     }
 
-    void testOutOfBoundsBySuperPlaceholderParameterType() {
+    void testOutOfBoundsBySuperGenericParameterType2() {
         shouldFailWithMessages '''
             class Foo {
                 static <T extends List<? super CharSequence>> void bar(T list) 
{}
@@ -4238,9 +4353,9 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             class Foo extends Bar {
                 static public Date genericItem() {
                     @ASTTest(phase=INSTRUCTION_SELECTION, value={
-                        def inft = node.getNodeMetaData(INFERRED_TYPE)
-                        assert inft == make(List)
-                        assert inft.genericsTypes[0].type == make(Date)
+                        Object type = node.getNodeMetaData(INFERRED_TYPE)
+                        assert type == LIST_TYPE
+                        assert type.genericsTypes[0].type == make(Date)
                     })
                     def res = bar(null)
 
@@ -4261,7 +4376,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
                         def cl = node.rightExpression.arguments[0]
                         assert cl instanceof ClosureExpression
                         def type = cl.getNodeMetaData(INFERRED_TYPE)
-                        assert type == make(Closure)
+                        assert type == CLOSURE_TYPE
                         assert type.isUsingGenerics()
                         assert type.genericsTypes
                         assert type.genericsTypes[0].type.name == 'CTypeTest'
diff --git a/src/test/groovy/transform/stc/MethodReferenceTest.groovy 
b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
index a9353cbde5..921edf719a 100644
--- a/src/test/groovy/transform/stc/MethodReferenceTest.groovy
+++ b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
@@ -1368,7 +1368,7 @@ final class MethodReferenceTest {
     // GROOVY-10813, GROOVY-10858, GROOVY-11363
     @Test
     void testMethodSelection() {
-        for (spec in ['', '<?>', '<Object>', '<? extends Object>', '<? super 
String>']) {
+        for (spec in ['', '<Object>', '<? super String>']) {
             assertScript shell, """
                 @CompileStatic
                 void test() {
@@ -1379,7 +1379,7 @@ final class MethodReferenceTest {
                 test()
             """
         }
-        for (spec in ['', '<?,?>', '<?,Object>', '<?,? extends Object>', '<?,? 
super String>']) {
+        for (spec in ['', '<Object,Object>', '<Object,? super String>']) {
             assertScript shell, """
                 @CompileStatic
                 void test() {
@@ -1393,7 +1393,7 @@ final class MethodReferenceTest {
         assertScript shell, '''
             @CompileStatic
             void test() {
-                BiConsumer<Script,?> c = Script::print
+                BiConsumer<Script,Object> c = Script::print
                 c.accept(this, 'hello world!')
             }
 
diff --git a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy 
b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
index 5d395506d9..e66b1d811c 100644
--- a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
@@ -1378,18 +1378,18 @@ class TypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
     // GROOVY-6835
     void testFlowTypingWithInstanceofAndInterfaceTypes() {
         assertScript '''
-            class ShowUnionTypeBug {
-                Map<String, Object> instanceMap = (Map<String,Object>)['a': 
'Hello World']
+            class ShowFlowTypeBug {
+                Map<String,Object> instanceMap = (Map<String,Object>)[a: 
'Hello World']
                 def findInstance(String key) {
-                    Set<? extends CharSequence> allInstances = [] as Set
-                    def instance = instanceMap.get(key)
+                    Set<CharSequence> instanceSet = []
+                    Object instance = instanceMap.get(key)
                     if(instance instanceof CharSequence) {
-                       allInstances.add(instance)
+                       instanceSet.add(instance)
                     }
-                    allInstances
+                    instanceSet
                 }
             }
-            assert new ShowUnionTypeBug().findInstance('a') == ['Hello World'] 
as Set
+            assert new ShowFlowTypeBug().findInstance('a') == ['Hello World'] 
as Set
         '''
     }
 

Reply via email to