You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/11/18 16:58:27 UTC

[groovy] branch GROOVY_3_0_X updated: GROOVY-10813: `parameterizeSAM`: no type parameters from method context

This is an automated email from the ASF dual-hosted git repository.

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


The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
     new 321cfc6339 GROOVY-10813: `parameterizeSAM`: no type parameters from method context
321cfc6339 is described below

commit 321cfc6339acead488ded3e5800c65291f1068ba
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Nov 18 09:26:57 2022 -0600

    GROOVY-10813: `parameterizeSAM`: no type parameters from method context
---
 .../codehaus/groovy/ast/tools/GenericsUtils.java   |  91 ++--
 src/test/groovy/bugs/Groovy7204.groovy             | 559 ++++++++++++++++++++
 src/test/groovy/bugs/Groovy7204Bug.groovy          | 579 ---------------------
 src/test/groovy/bugs/Groovy8059Bug.groovy          |  49 --
 src/test/groovy/transform/stc/LambdaTest.groovy    |  25 +
 .../groovy/ast/tools/GenericsUtilsTest.groovy      | 145 ++++--
 6 files changed, 740 insertions(+), 708 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 35390dc31b..c71053c699 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -710,6 +710,17 @@ public class GenericsUtils {
 
     private static final boolean PARAMETERIZED_TYPE_CACHE_ENABLED = Boolean.parseBoolean(getSystemPropertySafe("groovy.enable.parameterized.type.cache", "true"));
 
+    private static final EvictableCache<ParameterizedTypeCacheKey, SoftReference<ClassNode>> PARAMETERIZED_TYPE_CACHE = new ConcurrentSoftCache<>(64);
+
+    /**
+     * Clears the parameterized type cache.
+     * <p>
+     * It is useful to IDE as the type being compiled are continuously being edited/altered, see GROOVY-8675
+     */
+    public static void clearParameterizedTypeCache() {
+        PARAMETERIZED_TYPE_CACHE.clearAll();
+    }
+
     /**
      * Convenience method for {@link #findParameterizedTypeFromCache(ClassNode, ClassNode, boolean)}
      * when the {@code tryToFindExactType} boolean is {@code false}.
@@ -732,7 +743,7 @@ public class GenericsUtils {
                 new ParameterizedTypeCacheKey(genericsClass, actualType),
                 key -> new SoftReference<>(findParameterizedType(key.getGenericsClass(), key.getActualType(), tryToFindExactType)));
 
-        return sr == null ? null : sr.get();
+        return sr != null ? sr.get() : null;
     }
 
     /**
@@ -763,41 +774,34 @@ public class GenericsUtils {
         ClassNode type;
 
         while ((type = todo.poll()) != null) {
-            if (type.equals(genericsClass)) {
-                return type;
-            }
             if (done.add(type)) {
-                boolean parameterized = (type.getGenericsTypes() != null);
-                for (ClassNode cn : type.getInterfaces()) {
-                    if (parameterized)
-                        cn = parameterizeType(type, cn);
-                    todo.add(cn);
-                }
-                if (!actualType.isInterface()) {
+                if (!type.isInterface()) {
                     ClassNode cn = type.getUnresolvedSuperClass();
                     if (cn != null && cn.redirect() != ClassHelper.OBJECT_TYPE) {
-                        if (parameterized)
+                        if (hasUnresolvedGenerics(cn)) {
                             cn = parameterizeType(type, cn);
+                        }
+                        if (cn.equals(genericsClass)) {
+                            return cn;
+                        }
                         todo.add(cn);
                     }
                 }
+                for (ClassNode cn : type.getInterfaces()) {
+                    if (hasUnresolvedGenerics(cn)) {
+                        cn = parameterizeType(type, cn);
+                    }
+                    if (cn.equals(genericsClass)) {
+                        return cn;
+                    }
+                    todo.add(cn);
+                }
             }
         }
 
         return null;
     }
 
-    private static final EvictableCache<ParameterizedTypeCacheKey, SoftReference<ClassNode>> PARAMETERIZED_TYPE_CACHE = new ConcurrentSoftCache<>(64);
-
-    /**
-     * Clears the parameterized type cache.
-     * <p>
-     * It is useful to IDE as the type being compiled are continuously being edited/altered, see GROOVY-8675
-     */
-    public static void clearParameterizedTypeCache() {
-        PARAMETERIZED_TYPE_CACHE.clearAll();
-    }
-
     /**
      * map declaring generics type to actual generics type, e.g. GROOVY-7204:
      * declaring generics types:      T,      S extends Serializable
@@ -812,7 +816,7 @@ public class GenericsUtils {
      * so we need actual types:  T: String, S: Long
      */
     public static Map<GenericsType, GenericsType> makeDeclaringAndActualGenericsTypeMap(final ClassNode declaringClass, final ClassNode actualReceiver) {
-        return doMakeDeclaringAndActualGenericsTypeMap(declaringClass, actualReceiver, false);
+        return correlateTypeParametersAndTypeArguments(declaringClass, actualReceiver, false);
     }
 
     /**
@@ -827,25 +831,42 @@ public class GenericsUtils {
      * @since 3.0.0
      */
     public static Map<GenericsType, GenericsType> makeDeclaringAndActualGenericsTypeMapOfExactType(final ClassNode declaringClass, final ClassNode actualReceiver) {
-        return doMakeDeclaringAndActualGenericsTypeMap(declaringClass, actualReceiver, true);
+        return correlateTypeParametersAndTypeArguments(declaringClass, actualReceiver, true);
     }
 
-    private static Map<GenericsType, GenericsType> doMakeDeclaringAndActualGenericsTypeMap(final ClassNode declaringClass, final ClassNode actualReceiver, final boolean tryToFindExactType) {
-        Map<GenericsType, GenericsType> map = Collections.emptyMap();
+    private static Map<GenericsType, GenericsType> correlateTypeParametersAndTypeArguments(final ClassNode declaringClass, final ClassNode actualReceiver, final boolean tryToFindExactType) {
         ClassNode parameterizedType = findParameterizedTypeFromCache(declaringClass, actualReceiver, tryToFindExactType);
         if (parameterizedType != null && parameterizedType.isRedirectNode() && !parameterizedType.isGenericsPlaceHolder()) { // GROOVY-10166
             // declaringClass may be "List<T> -> List<E>" and parameterizedType may be "List<String> -> List<E>" or "List<> -> List<E>"
-            GenericsType[] targetGenericsTypes = parameterizedType.redirect().getGenericsTypes();
-            if (targetGenericsTypes != null) {
-                GenericsType[] sourceGenericsTypes = parameterizedType.getGenericsTypes();
-                if (sourceGenericsTypes == null) sourceGenericsTypes = EMPTY_GENERICS_ARRAY;
-                map = new LinkedHashMap<>();
-                for (int i = 0, m = sourceGenericsTypes.length, n = targetGenericsTypes.length; i < n; i += 1) {
-                    map.put(targetGenericsTypes[i], i < m ? sourceGenericsTypes[i] : targetGenericsTypes[i]);
+            final GenericsType[] typeParameters = parameterizedType.redirect().getGenericsTypes();
+            if (typeParameters != null) {
+                final GenericsType[] typeArguments = parameterizedType.getGenericsTypes();
+                final int m = typeArguments == null ? 0 : typeArguments.length;
+                final int n = typeParameters.length;
+
+                Map<GenericsType, GenericsType> map = new LinkedHashMap<>();
+                for (int i = 0; i < n; i += 1) {
+                    map.put(typeParameters[i], i < m ? typeArguments[i] : erasure(typeParameters[i]));
                 }
+                return map;
             }
         }
-        return map;
+        return Collections.emptyMap();
+    }
+
+    /**
+     * @see org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport#extractType(GenericsType)
+     */
+    private static GenericsType erasure(GenericsType gt) {
+        ClassNode cn = gt.getType().redirect(); // discard the placeholder
+
+        if (gt.getType().getGenericsTypes() != null)
+            gt = gt.getType().getGenericsTypes()[0];
+
+        if (gt.getUpperBounds() != null)
+            cn = gt.getUpperBounds()[0]; // TODO: if length > 1 then union type?
+
+        return cn.asGenericsType();
     }
 
     /**
diff --git a/src/test/groovy/bugs/Groovy7204.groovy b/src/test/groovy/bugs/Groovy7204.groovy
new file mode 100644
index 0000000000..41e7b2fb09
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy7204.groovy
@@ -0,0 +1,559 @@
+/*
+ *  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 groovy.test.NotYetImplemented
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+final class Groovy7204 {
+
+    @Test
+    void testTypeChecked1() {
+        assertScript '''import groovy.transform.*
+            @TypeChecked
+            public class MyClass {
+                static MyRepository factory() {
+                    return new MyRepositoryImpl()
+                }
+
+                static void main(String[] args) {
+                    MyRepository r = factory()
+                    r.delete('foo')
+                }
+            }
+
+            @TypeChecked
+            interface CrudRepository<T, S extends Serializable> {
+                void delete(T arg)
+                void delete(S arg)
+            }
+
+            @TypeChecked
+            interface MyRepository extends CrudRepository<String, Long> {
+            }
+
+            @TypeChecked
+            class MyRepositoryImpl implements MyRepository {
+                @Override
+                public void delete(String arg) {
+                    assert true
+                }
+
+                @Override
+                public void delete(Long arg) {
+                    assert false: 'wrong method invoked'
+                }
+            }
+        '''
+    }
+
+    @Test
+    void testTypeChecked2() {
+        assertScript '''import groovy.transform.*
+            @TypeChecked
+            public class MyClass {
+                static MyRepository factory() {
+                    return new MyRepositoryImpl()
+                }
+
+                static void main(String[] args) {
+                    MyRepository r = factory()
+                    r.delete('foo')
+                }
+            }
+
+            @TypeChecked
+            abstract class CrudRepository<T, S extends Serializable> {
+                abstract void delete(T arg)
+                abstract void delete(S arg)
+            }
+
+            @TypeChecked
+            abstract class MyRepository extends CrudRepository<String, Long> {
+            }
+
+            @TypeChecked
+            class MyRepositoryImpl extends MyRepository {
+                @Override
+                public void delete(String arg) {
+                    assert true
+                }
+
+                @Override
+                public void delete(Long arg) {
+                    assert false: 'wrong method invoked'
+                }
+            }
+        '''
+    }
+
+    @Test
+    void testTypeChecked3() {
+        assertScript '''import groovy.transform.*
+            @TypeChecked
+            public class MyClass {
+                static MyRepository factory() {
+                    return new MyRepositoryImpl()
+                }
+
+                static void main(String[] args) {
+                    MyRepository r = factory()
+                    r.delete('foo')
+                }
+            }
+
+            @TypeChecked
+            interface CrudRepository<T, S extends Serializable> {
+                void delete(T arg)
+                void delete(S arg)
+            }
+
+            @TypeChecked
+            interface MyRepository2 extends CrudRepository<String, Long> {
+            }
+
+            @TypeChecked
+            interface MyRepository extends MyRepository2 {
+            }
+
+            @TypeChecked
+            class MyRepositoryImpl implements MyRepository {
+                @Override
+                public void delete(String arg) {
+                    assert true
+                }
+
+                @Override
+                public void delete(Long arg) {
+                    assert false: 'wrong method invoked'
+                }
+            }
+        '''
+    }
+
+    @Test
+    void testTypeChecked4() {
+        assertScript '''import groovy.transform.*
+            @TypeChecked
+            public class MyClass {
+                static MyRepository factory() {
+                    return new MyRepositoryImpl()
+                }
+
+                static void main(String[] args) {
+                    MyRepository r = factory()
+                    r.delete('foo')
+                }
+            }
+
+            @TypeChecked
+            abstract class CrudRepository<T, S extends Serializable> {
+                abstract void delete(T arg)
+                abstract void delete(S arg)
+            }
+
+            @TypeChecked
+            abstract class MyRepository2 extends CrudRepository<String, Long> {
+            }
+
+            @TypeChecked
+            abstract class MyRepository extends MyRepository2 {
+            }
+
+            @TypeChecked
+            class MyRepositoryImpl extends MyRepository {
+                @Override
+                public void delete(String arg) {
+                    assert true
+                }
+
+                @Override
+                public void delete(Long arg) {
+                    assert false: 'wrong method invoked'
+                }
+            }
+        '''
+    }
+
+    @Test
+    void testTypeChecked5() {
+        assertScript '''import groovy.transform.*
+            @TypeChecked
+            public class MyClass {
+                static MyRepository factory() {
+                    return new MyRepositoryImpl()
+                }
+
+                static void main(String[] args) {
+                    MyRepository r = factory()
+                    r.delete('foo')
+                }
+            }
+
+            @TypeChecked
+            interface CrudRepository<T, S extends Serializable> {
+                void delete(T arg)
+                void delete(S arg)
+            }
+
+            @TypeChecked
+            abstract class MyRepository2 implements CrudRepository<String, Long> {
+            }
+
+            @TypeChecked
+            abstract class MyRepository extends MyRepository2 {
+            }
+
+            @TypeChecked
+            class MyRepositoryImpl extends MyRepository {
+                @Override
+                public void delete(String arg) {
+                    assert true
+                }
+
+                @Override
+                public void delete(Long arg) {
+                    assert false: 'wrong method invoked'
+                }
+            }
+        '''
+    }
+
+    @NotYetImplemented @Test
+    void testTypeChecked6() {
+        assertScript '''import groovy.transform.*
+            class Repository<T, S extends Serializable> {
+                void delete(T arg) { assert true }
+                void delete(S arg) { assert false: 'wrong method invoked' }
+            }
+
+            @TypeChecked
+            def test() {
+                Repository<String, Long> r = new Repository<String, Long>()
+                r.delete('foo')
+            }
+
+            test()
+        '''
+    }
+
+    //
+
+    @Test
+    void testCompileStatic1() {
+        assertScript '''import groovy.transform.*
+            @CompileStatic
+            public class MyClass {
+                static MyRepository factory() {
+                    return new MyRepositoryImpl()
+                }
+
+                static void main(String[] args) {
+                    MyRepository r = factory()
+                    r.delete('foo')
+                }
+            }
+
+            @CompileStatic
+            interface CrudRepository<T, S extends Serializable> {
+                void delete(T arg)
+                void delete(S arg)
+            }
+
+            @CompileStatic
+            interface MyRepository extends CrudRepository<String, Long> {
+            }
+
+            @CompileStatic
+            class MyRepositoryImpl implements MyRepository {
+                @Override
+                public void delete(String arg) {
+                    assert true
+                }
+
+                @Override
+                public void delete(Long arg) {
+                    assert false: 'wrong method invoked'
+                }
+            }
+        '''
+    }
+
+    @Test
+    void testCompileStatic2() {
+        assertScript '''import groovy.transform.*
+            @CompileStatic
+            public class MyClass {
+                static MyRepository factory() {
+                    return new MyRepositoryImpl()
+                }
+
+                static void main(String[] args) {
+                    MyRepository r = factory()
+                    r.delete('foo')
+                }
+            }
+
+            @CompileStatic
+            abstract class CrudRepository<T, S extends Serializable> {
+                abstract void delete(T arg)
+                abstract void delete(S arg)
+            }
+
+            @CompileStatic
+            abstract class MyRepository extends CrudRepository<String, Long> {
+            }
+
+            @CompileStatic
+            class MyRepositoryImpl extends MyRepository {
+                @Override
+                public void delete(String arg) {
+                    assert true
+                }
+
+                @Override
+                public void delete(Long arg) {
+                    assert false: 'wrong method invoked'
+                }
+            }
+        '''
+    }
+
+    @Test
+    void testCompileStatic3() {
+        assertScript '''import groovy.transform.*
+            @CompileStatic
+            public class MyClass {
+                static MyRepository factory() {
+                    return new MyRepositoryImpl()
+                }
+
+                static void main(String[] args) {
+                    MyRepository r = factory()
+                    r.delete('foo')
+                }
+            }
+
+            @CompileStatic
+            interface CrudRepository<T, S extends Serializable> {
+                void delete(T arg)
+                void delete(S arg)
+            }
+
+            @CompileStatic
+            interface MyRepository2 extends CrudRepository<String, Long> {
+            }
+
+            @CompileStatic
+            interface MyRepository extends MyRepository2 {
+            }
+
+            @CompileStatic
+            class MyRepositoryImpl implements MyRepository {
+                @Override
+                public void delete(String arg) {
+                    assert true
+                }
+
+                @Override
+                public void delete(Long arg) {
+                    assert false: 'wrong method invoked'
+                }
+            }
+        '''
+    }
+
+    @Test
+    void testCompileStatic4() {
+        assertScript '''import groovy.transform.*
+            @CompileStatic
+            public class MyClass {
+                static MyRepository factory() {
+                    return new MyRepositoryImpl()
+                }
+
+                static void main(String[] args) {
+                    MyRepository r = factory()
+                    r.delete('foo')
+                }
+            }
+
+            @CompileStatic
+            abstract class CrudRepository<T, S extends Serializable> {
+                abstract void delete(T arg)
+                abstract void delete(S arg)
+            }
+
+            @CompileStatic
+            abstract class MyRepository2 extends CrudRepository<String, Long> {
+            }
+
+            @CompileStatic
+            abstract class MyRepository extends MyRepository2 {
+            }
+
+            @CompileStatic
+            class MyRepositoryImpl extends MyRepository {
+                @Override
+                public void delete(String arg) {
+                    assert true
+                }
+
+                @Override
+                public void delete(Long arg) {
+                    assert false: 'wrong method invoked'
+                }
+            }
+        '''
+    }
+
+    @Test
+    void testCompileStatic5() {
+        assertScript '''import groovy.transform.*
+            @CompileStatic
+            public class MyClass {
+                static MyRepository factory() {
+                    return new MyRepositoryImpl()
+                }
+
+                static void main(String[] args) {
+                    MyRepository r = factory()
+                    r.delete('foo')
+                }
+            }
+
+            @CompileStatic
+            interface CrudRepository<T, S extends Serializable> {
+                void delete(T arg)
+                void delete(S arg)
+            }
+
+            @CompileStatic
+            abstract class MyRepository2 implements CrudRepository<String, Long> {
+            }
+
+            @CompileStatic
+            abstract class MyRepository extends MyRepository2 {
+            }
+
+            @CompileStatic
+            class MyRepositoryImpl extends MyRepository {
+                @Override
+                public void delete(String arg) {
+                    assert true
+                }
+
+                @Override
+                public void delete(Long arg) {
+                    assert false: 'wrong method invoked'
+                }
+            }
+        '''
+    }
+
+    @Test
+    void testCompileStatic6() {
+        assertScript '''import groovy.transform.*
+            class Repository<T, S extends Serializable> {
+                void delete(T arg) { assert true }
+                void delete(S arg) { assert false: 'wrong method invoked' }
+            }
+
+            @CompileStatic
+            def test() {
+                Repository<String, Long> r = new Repository<String, Long>()
+                r.delete('foo')
+            }
+
+            test()
+        '''
+    }
+
+    @Test // GROOVY-8059
+    void testCompileStatic7() {
+        assertScript '''import groovy.transform.*
+            abstract class A<K extends Serializable, V> {
+                void delete(K key) {}
+                void delete(V val) {}
+            }
+            class C extends A<String, Integer> {
+            }
+
+            @CompileStatic
+            class Test {
+                Test() {
+                    def obj = new C()
+                    obj.delete(Integer.valueOf(1))
+                }
+            }
+
+            new Test()
+        '''
+    }
+
+    @Test
+    void testCompileStatic8() {
+        assertScript '''import groovy.transform.*
+            class Trie<T> {
+            }
+
+            @CompileStatic
+            class Base<T> {
+                protected List<Trie<T>> list = []
+                Base() {
+                    list.add(new Trie<String>()) // should fail!!
+                }
+            }
+
+            @CompileStatic
+            class Test extends Base<String> {
+                Trie<String> getFirstElement() {
+                    list.get(0)
+                }
+            }
+
+            assert new Test().firstElement instanceof Trie
+        '''
+    }
+
+    @Test
+    void testCompileStatic9() {
+        assertScript '''import groovy.transform.*
+            class Trie<T> {
+            }
+
+            class Base<T> extends ArrayList<Trie<T>> {
+            }
+
+            @CompileStatic
+            class Test extends Base<String> {
+                Test() {
+                    add(new Trie<String>())
+                }
+                Trie<String> getFirstElement() {
+                    get(0)
+                }
+            }
+
+            assert new Test().firstElement instanceof Trie
+        '''
+    }
+}
diff --git a/src/test/groovy/bugs/Groovy7204Bug.groovy b/src/test/groovy/bugs/Groovy7204Bug.groovy
deleted file mode 100644
index 5c5f20ec92..0000000000
--- a/src/test/groovy/bugs/Groovy7204Bug.groovy
+++ /dev/null
@@ -1,579 +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 groovy.test.GroovyTestCase
-
-class Groovy7204Bug extends GroovyTestCase {
-    void testTypeChecked1() {
-        assertScript '''
-        import java.io.Serializable;
-        
-        import groovy.transform.CompileStatic;
-        import groovy.transform.TypeChecked;
-        
-        @TypeChecked
-        public class MyClass {
-            static MyRepository factory() {
-                return new MyRepositoryImpl()
-            }
-            
-            static void main(String[] args) {
-                MyRepository r = factory()
-                r.delete('foo')
-            }
-        }
-        
-        @TypeChecked
-        interface CrudRepository<T, S extends Serializable> {
-            void delete(T arg);
-            void delete(S arg);
-        }
-        
-        @TypeChecked
-        interface MyRepository extends CrudRepository<String, Long> {
-        }
-        
-        @TypeChecked
-        class MyRepositoryImpl implements MyRepository {
-            @Override
-            public void delete(String arg) {
-                System.out.println("String");
-                assert true
-            }
-            
-            @Override
-            public void delete(Long arg) {
-                System.out.println("Long");
-                assert false: 'wrong method invoked'
-            }
-        }
-        '''
-    }
-
-    void testTypeChecked2() {
-        assertScript '''
-        import java.io.Serializable;
-        
-        import groovy.transform.CompileStatic;
-        import groovy.transform.TypeChecked;
-        
-        @TypeChecked
-        public class MyClass {
-            static MyRepository factory() {
-                return new MyRepositoryImpl()
-            }
-            
-            static void main(String[] args) {
-                MyRepository r = factory()
-                r.delete('foo')
-            }
-        }
-        
-        @TypeChecked
-        abstract class CrudRepository<T, S extends Serializable> {
-            abstract void delete(T arg);
-            abstract void delete(S arg);
-        }
-        
-        @TypeChecked
-        abstract class MyRepository extends CrudRepository<String, Long> {
-        }
-        
-        @TypeChecked
-        class MyRepositoryImpl extends MyRepository {
-            @Override
-            public void delete(String arg) {
-                System.out.println("String");
-                assert true
-            }
-            
-            @Override
-            public void delete(Long arg) {
-                System.out.println("Long");
-                assert false: 'wrong method invoked'
-            }
-        }
-        '''
-    }
-
-    void testTypeChecked3() {
-        assertScript '''
-        import java.io.Serializable;
-        
-        import groovy.transform.CompileStatic;
-        import groovy.transform.TypeChecked;
-        
-        @TypeChecked
-        public class MyClass {
-            static MyRepository factory() {
-                return new MyRepositoryImpl()
-            }
-            
-            static void main(String[] args) {
-                MyRepository r = factory()
-                r.delete('foo')
-            }
-        }
-        
-        @TypeChecked
-        interface CrudRepository<T, S extends Serializable> {
-            void delete(T arg);
-            void delete(S arg);
-        }
-        
-        @TypeChecked
-        interface MyRepository2 extends CrudRepository<String, Long> {
-        }
-        
-        @TypeChecked
-        interface MyRepository extends MyRepository2 {
-        }
-        
-        @TypeChecked
-        class MyRepositoryImpl implements MyRepository {
-            @Override
-            public void delete(String arg) {
-                System.out.println("String");
-                assert true
-            }
-            
-            @Override
-            public void delete(Long arg) {
-                System.out.println("Long");
-                assert false: 'wrong method invoked'
-            }
-        }
-        '''
-    }
-
-    void testTypeChecked4() {
-        assertScript '''
-        import java.io.Serializable;
-        
-        import groovy.transform.CompileStatic;
-        import groovy.transform.TypeChecked;
-        
-        @TypeChecked
-        public class MyClass {
-            static MyRepository factory() {
-                return new MyRepositoryImpl()
-            }
-            
-            static void main(String[] args) {
-                MyRepository r = factory()
-                r.delete('foo')
-            }
-        }
-        
-        @TypeChecked
-        abstract class CrudRepository<T, S extends Serializable> {
-            abstract void delete(T arg);
-            abstract void delete(S arg);
-        }
-        
-        @TypeChecked
-        abstract class MyRepository2 extends CrudRepository<String, Long> {
-        }
-        
-        @TypeChecked
-        abstract class MyRepository extends MyRepository2 {
-        }
-        
-        @TypeChecked
-        class MyRepositoryImpl extends MyRepository {
-            @Override
-            public void delete(String arg) {
-                System.out.println("String");
-                assert true
-            }
-            
-            @Override
-            public void delete(Long arg) {
-                System.out.println("Long");
-                assert false: 'wrong method invoked'
-            }
-        }
-        '''
-    }
-
-    void testTypeChecked5() {
-        assertScript '''
-        import java.io.Serializable;
-        
-        import groovy.transform.CompileStatic;
-        import groovy.transform.TypeChecked;
-        
-        @TypeChecked
-        public class MyClass {
-            static MyRepository factory() {
-                return new MyRepositoryImpl()
-            }
-            
-            static void main(String[] args) {
-                MyRepository r = factory()
-                r.delete('foo')
-            }
-        }
-        
-        @TypeChecked
-        interface CrudRepository<T, S extends Serializable> {
-            void delete(T arg);
-            void delete(S arg);
-        }
-        
-        @TypeChecked
-        abstract class MyRepository2 implements CrudRepository<String, Long> {
-        }
-        
-        @TypeChecked
-        abstract class MyRepository extends MyRepository2 {
-        }
-        
-        @TypeChecked
-        class MyRepositoryImpl extends MyRepository {
-            @Override
-            public void delete(String arg) {
-                System.out.println("String");
-                assert true
-            }
-            
-            @Override
-            public void delete(Long arg) {
-                System.out.println("Long");
-                assert false: 'wrong method invoked'
-            }
-        }
-        '''
-    }
-
-
-    void testCompileStatic1() {
-        assertScript '''
-        import java.io.Serializable;
-        
-        import groovy.transform.CompileStatic;
-        import groovy.transform.TypeChecked;
-        
-        @CompileStatic
-        public class MyClass {
-            static MyRepository factory() {
-                return new MyRepositoryImpl()
-            }
-            
-            static void main(String[] args) {
-                MyRepository r = factory()
-                r.delete('foo')
-            }
-        }
-        
-        @CompileStatic
-        interface CrudRepository<T, S extends Serializable> {
-            void delete(T arg);
-            void delete(S arg);
-        }
-        
-        @CompileStatic
-        interface MyRepository extends CrudRepository<String, Long> {
-        }
-        
-        @CompileStatic
-        class MyRepositoryImpl implements MyRepository {
-            @Override
-            public void delete(String arg) {
-                System.out.println("String");
-                assert true
-            }
-            
-            @Override
-            public void delete(Long arg) {
-                System.out.println("Long");
-                assert false: 'wrong method invoked'
-            }
-        }
-        '''
-    }
-
-    void testCompileStatic2() {
-        assertScript '''
-        import java.io.Serializable;
-        
-        import groovy.transform.CompileStatic;
-        import groovy.transform.TypeChecked;
-        
-        @CompileStatic
-        public class MyClass {
-            static MyRepository factory() {
-                return new MyRepositoryImpl()
-            }
-            
-            static void main(String[] args) {
-                MyRepository r = factory()
-                r.delete('foo')
-            }
-        }
-        
-        @CompileStatic
-        abstract class CrudRepository<T, S extends Serializable> {
-            abstract void delete(T arg);
-            abstract void delete(S arg);
-        }
-        
-        @CompileStatic
-        abstract class MyRepository extends CrudRepository<String, Long> {
-        }
-        
-        @CompileStatic
-        class MyRepositoryImpl extends MyRepository {
-            @Override
-            public void delete(String arg) {
-                System.out.println("String");
-                assert true
-            }
-            
-            @Override
-            public void delete(Long arg) {
-                System.out.println("Long");
-                assert false: 'wrong method invoked'
-            }
-        }
-        '''
-    }
-
-    void testCompileStatic3() {
-        assertScript '''
-        import java.io.Serializable;
-        
-        import groovy.transform.CompileStatic;
-        import groovy.transform.TypeChecked;
-        
-        @CompileStatic
-        public class MyClass {
-            static MyRepository factory() {
-                return new MyRepositoryImpl()
-            }
-            
-            static void main(String[] args) {
-                MyRepository r = factory()
-                r.delete('foo')
-            }
-        }
-        
-        @CompileStatic
-        interface CrudRepository<T, S extends Serializable> {
-            void delete(T arg);
-            void delete(S arg);
-        }
-        
-        @CompileStatic
-        interface MyRepository2 extends CrudRepository<String, Long> {
-        }
-        
-        @CompileStatic
-        interface MyRepository extends MyRepository2 {
-        }
-        
-        @CompileStatic
-        class MyRepositoryImpl implements MyRepository {
-            @Override
-            public void delete(String arg) {
-                System.out.println("String");
-                assert true
-            }
-            
-            @Override
-            public void delete(Long arg) {
-                System.out.println("Long");
-                assert false: 'wrong method invoked'
-            }
-        }
-        '''
-    }
-
-    void testCompileStatic4() {
-        assertScript '''
-        import java.io.Serializable;
-        
-        import groovy.transform.CompileStatic;
-        import groovy.transform.TypeChecked;
-        
-        @CompileStatic
-        public class MyClass {
-            static MyRepository factory() {
-                return new MyRepositoryImpl()
-            }
-            
-            static void main(String[] args) {
-                MyRepository r = factory()
-                r.delete('foo')
-            }
-        }
-        
-        @CompileStatic
-        abstract class CrudRepository<T, S extends Serializable> {
-            abstract void delete(T arg);
-            abstract void delete(S arg);
-        }
-        
-        @CompileStatic
-        abstract class MyRepository2 extends CrudRepository<String, Long> {
-        }
-        
-        @CompileStatic
-        abstract class MyRepository extends MyRepository2 {
-        }
-        
-        @CompileStatic
-        class MyRepositoryImpl extends MyRepository {
-            @Override
-            public void delete(String arg) {
-                System.out.println("String");
-                assert true
-            }
-            
-            @Override
-            public void delete(Long arg) {
-                System.out.println("Long");
-                assert false: 'wrong method invoked'
-            }
-        }
-        '''
-    }
-
-    void testCompileStatic5() {
-        assertScript '''
-        import java.io.Serializable;
-        
-        import groovy.transform.CompileStatic;
-        import groovy.transform.TypeChecked;
-        
-        @CompileStatic
-        public class MyClass {
-            static MyRepository factory() {
-                return new MyRepositoryImpl()
-            }
-            
-            static void main(String[] args) {
-                MyRepository r = factory()
-                r.delete('foo')
-            }
-        }
-        
-        @CompileStatic
-        interface CrudRepository<T, S extends Serializable> {
-            void delete(T arg);
-            void delete(S arg);
-        }
-        
-        @CompileStatic
-        abstract class MyRepository2 implements CrudRepository<String, Long> {
-        }
-        
-        @CompileStatic
-        abstract class MyRepository extends MyRepository2 {
-        }
-        
-        @CompileStatic
-        class MyRepositoryImpl extends MyRepository {
-            @Override
-            public void delete(String arg) {
-                System.out.println("String");
-                assert true
-            }
-            
-            @Override
-            public void delete(Long arg) {
-                System.out.println("Long");
-                assert false: 'wrong method invoked'
-            }
-        }
-        '''
-    }
-
-    void testCompileStatic6() {
-        assertScript '''
-        import java.io.Serializable;
-        import groovy.transform.CompileStatic;
-
-        @CompileStatic
-        class Repository<T, S extends Serializable> {
-            void delete(T arg) { assert true }
-            void delete(S arg) { assert false: 'wrong method invoked' }
-        }
-        
-        @CompileStatic
-        def test() {
-            Repository<String, Long> r = new Repository<String, Long>()
-            r.delete('foo')
-        }
-        
-        test()
-        '''
-    }
-
-    void testCompileStatic7() {
-        assertScript '''
-        @groovy.transform.CompileStatic
-        class Trie<T> {}
-        
-        @groovy.transform.CompileStatic
-        class Base<T> {
-            protected List<Trie<T>> list
-            
-            Base() {
-                list = new ArrayList<Trie<T>>()
-                list.add(new Trie<String>())
-            }
-        }
-        
-        @groovy.transform.CompileStatic
-        class Derived extends Base<String> {
-            Trie<String> getFirstElement() {
-                list.get(0)
-            }
-        }
-        
-        assert new Derived().getFirstElement() instanceof Trie
-        '''
-    }
-
-    void testCompileStatic8() {
-        assertScript '''
-        @groovy.transform.CompileStatic
-        class Trie<T> {}
-        
-        @groovy.transform.CompileStatic
-        class Base<T> extends ArrayList<Trie<T>> {
-            
-            Base() {
-                this.add(new Trie<String>())
-            }
-        }
-        
-        @groovy.transform.CompileStatic
-        class Derived extends Base<String> {
-            Trie<String> getFirstElement() {
-                this.get(0)
-            }
-        }
-        
-        assert new Derived().getFirstElement() instanceof Trie
-        '''
-    }
-}
diff --git a/src/test/groovy/bugs/Groovy8059Bug.groovy b/src/test/groovy/bugs/Groovy8059Bug.groovy
deleted file mode 100644
index 85d77fd676..0000000000
--- a/src/test/groovy/bugs/Groovy8059Bug.groovy
+++ /dev/null
@@ -1,49 +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 groovy.test.GroovyTestCase
-
-class Groovy8059Bug extends GroovyTestCase {
-    void test1() {
-        assertScript '''
-        @groovy.transform.CompileStatic
-        class Base<K extends Serializable, V> {
-            void delete(K key) {}
-            void delete(V value) {}
-        }
-        
-        @groovy.transform.CompileStatic
-        class Foo extends Base<String, Integer> {}
-        
-        @groovy.transform.CompileStatic
-        public class Class1 {
-            Class1() {
-                Foo foo = new Foo()        
-                foo.delete(Integer.valueOf(1))
-            }
-        }
-        new Class1()
-        '''
-    }
-}
diff --git a/src/test/groovy/transform/stc/LambdaTest.groovy b/src/test/groovy/transform/stc/LambdaTest.groovy
index f01c511a0e..31d531f9d1 100644
--- a/src/test/groovy/transform/stc/LambdaTest.groovy
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -799,6 +799,31 @@ final class LambdaTest {
         }
     }
 
+    @Test // GROOVY-10813
+    void testConsumer11() {
+        ['CompileStatic', 'TypeChecked'].each { xform ->
+            assertScript """
+                @groovy.transform.${xform}
+                void test() {
+                    java.util.function.Consumer c = x -> print(x)
+                    c.accept('works')
+                }
+                test()
+            """
+            assertScript """
+                interface I<T extends CharSequence> {
+                    void accept(T t)
+                }
+                @groovy.transform.${xform}
+                void test() {
+                    I i = x -> print(x)
+                    i.accept('works')
+                }
+                test()
+            """
+        }
+    }
+
     @Test
     void testFunctionalInterface1() {
         assertScript '''
diff --git a/src/test/org/codehaus/groovy/ast/tools/GenericsUtilsTest.groovy b/src/test/org/codehaus/groovy/ast/tools/GenericsUtilsTest.groovy
index 1b30f71817..ef2893362d 100644
--- a/src/test/org/codehaus/groovy/ast/tools/GenericsUtilsTest.groovy
+++ b/src/test/org/codehaus/groovy/ast/tools/GenericsUtilsTest.groovy
@@ -48,12 +48,12 @@ final class GenericsUtilsTest {
         ClassNode source = findClassNode('Derived', classNodeList)
         ClassNode result = GenericsUtils.findParameterizedType(target, source)
 
-        assert 'Base' == result.name
+        assert result.name == 'Base'
         assert result.isUsingGenerics()
-        assert 2 == result.genericsTypes.length
-        assert 'java.lang.String' == result.genericsTypes[0].type.name
-        assert 'java.util.List'   == result.genericsTypes[1].type.name
-        assert target === result.redirect()
+        assert result.genericsTypes.length == 2
+        assert result.genericsTypes[0].type.name == 'java.lang.String'
+        assert result.genericsTypes[1].type.name == 'java.util.List'
+        assert result.redirect() === target
     }
 
     @Test
@@ -67,12 +67,12 @@ final class GenericsUtilsTest {
         ClassNode source = findClassNode('Derived', classNodeList)
         ClassNode result = GenericsUtils.findParameterizedType(target, source)
 
-        assert 'Base' == result.name
+        assert result.name == 'Base'
         assert result.isUsingGenerics()
-        assert 2 == result.genericsTypes.length
-        assert 'java.lang.String' == result.genericsTypes[0].type.name
-        assert 'java.util.List'   == result.genericsTypes[1].type.name
-        assert target === result.redirect()
+        assert result.genericsTypes.length == 2
+        assert result.genericsTypes[0].type.name == 'java.lang.String'
+        assert result.genericsTypes[1].type.name == 'java.util.List'
+        assert result.redirect() === target
     }
 
     @Test
@@ -87,12 +87,12 @@ final class GenericsUtilsTest {
         ClassNode source = findClassNode('Derived', classNodeList)
         ClassNode result = GenericsUtils.findParameterizedType(target, source)
 
-        assert 'Base' == result.name
+        assert result.name == 'Base'
         assert result.isUsingGenerics()
-        assert 2 == result.genericsTypes.length
-        assert 'java.lang.String' == result.genericsTypes[0].type.name
-        assert 'java.util.List'   == result.genericsTypes[1].type.name
-        assert target === result.redirect()
+        assert result.genericsTypes.length == 2
+        assert result.genericsTypes[0].type.name == 'java.lang.String'
+        assert result.genericsTypes[1].type.name == 'java.util.List'
+        assert result.redirect() === target
     }
 
     @Test
@@ -106,12 +106,12 @@ final class GenericsUtilsTest {
         ClassNode source = findClassNode('Derived', classNodeList)
         ClassNode result = GenericsUtils.findParameterizedType(target, source)
 
-        assert 'Base' == result.name
+        assert result.name == 'Base'
         assert result.isUsingGenerics()
-        assert 2 == result.genericsTypes.length
-        assert 'java.lang.String' == result.genericsTypes[0].type.name
-        assert 'java.util.List'   == result.genericsTypes[1].type.name
-        assert target === result.redirect()
+        assert result.genericsTypes.length == 2
+        assert result.genericsTypes[0].type.name == 'java.lang.String'
+        assert result.genericsTypes[1].type.name == 'java.util.List'
+        assert result.redirect() === target
     }
 
     @Test
@@ -126,12 +126,12 @@ final class GenericsUtilsTest {
         ClassNode source = findClassNode('Derived', classNodeList)
         ClassNode result = GenericsUtils.findParameterizedType(target, source)
 
-        assert 'Base' == result.name
+        assert result.name == 'Base'
         assert result.isUsingGenerics()
-        assert 2 == result.genericsTypes.length
-        assert 'java.lang.String' == result.genericsTypes[0].type.name
-        assert 'java.util.List'   == result.genericsTypes[1].type.name
-        assert target === result.redirect()
+        assert result.genericsTypes.length == 2
+        assert result.genericsTypes[0].type.name == 'java.lang.String'
+        assert result.genericsTypes[1].type.name == 'java.util.List'
+        assert result.redirect() === target
     }
 
     @Test
@@ -147,12 +147,12 @@ final class GenericsUtilsTest {
         ClassNode source = findClassNode('Derived', classNodeList)
         ClassNode result = GenericsUtils.findParameterizedType(target, source)
 
-        assert 'Base' == result.name
+        assert result.name == 'Base'
         assert result.isUsingGenerics()
-        assert 2 == result.genericsTypes.length
-        assert 'java.lang.String' == result.genericsTypes[0].type.name
-        assert 'java.util.List'   == result.genericsTypes[1].type.name
-        assert target === result.redirect()
+        assert result.genericsTypes.length == 2
+        assert result.genericsTypes[0].type.name == 'java.lang.String'
+        assert result.genericsTypes[1].type.name == 'java.util.List'
+        assert result.redirect() === target
     }
 
     @Test
@@ -169,12 +169,12 @@ final class GenericsUtilsTest {
         ClassNode source = findClassNode('Derived', classNodeList)
         ClassNode result = GenericsUtils.findParameterizedType(target, source)
 
-        assert 'Base' == result.name
+        assert result.name == 'Base'
         assert result.isUsingGenerics()
-        assert 2 == result.genericsTypes.length
-        assert 'java.lang.String' == result.genericsTypes[0].type.name
-        assert 'java.util.List'   == result.genericsTypes[1].type.name
-        assert target === result.redirect()
+        assert result.genericsTypes.length == 2
+        assert result.genericsTypes[0].type.name == 'java.lang.String'
+        assert result.genericsTypes[1].type.name == 'java.util.List'
+        assert result.redirect() === target
     }
 
     @Test // GROOVY-9945
@@ -220,9 +220,9 @@ final class GenericsUtilsTest {
 
         Map<GenericsType, GenericsType> m = GenericsUtils.makeDeclaringAndActualGenericsTypeMapOfExactType(target, source)
 
+        assert m.size() == 2
         assert m.entrySet().find { it.key.name == 'T' }.value.type.name == 'java.lang.String'
         assert m.entrySet().find { it.key.name == 'U' }.value.type.name == 'java.lang.Integer'
-        assert m.size() == 2
     }
 
     @Test
@@ -237,14 +237,14 @@ final class GenericsUtilsTest {
 
         Map<GenericsType, GenericsType> m = GenericsUtils.makeDeclaringAndActualGenericsTypeMapOfExactType(target, source)
 
+        assert m.size() == 3
         assert m.entrySet().find { it.key.name == 'R' }.value.type.name == 'java.lang.Boolean'
         assert m.entrySet().find { it.key.name == 'T' }.value.type.name == 'java.lang.Integer'
         assert m.entrySet().find { it.key.name == 'U' }.value.type.name == 'java.lang.String'
-        assert m.size() == 3
     }
 
     @Test
-    void testParameterizeSAM() {
+    void testParameterizeSAM1() {
         def classNodeList = compile '''
             import java.util.function.*
             interface T extends Function<String, Integer> {}
@@ -253,10 +253,10 @@ final class GenericsUtilsTest {
 
         def typeInfo = GenericsUtils.parameterizeSAM(samType)
 
-        assert 1 == typeInfo[0].length
-        assert ClassHelper.STRING_TYPE == typeInfo[0][0]
+        assert typeInfo[0].length == 1
+        assert typeInfo[0][0] == ClassHelper.STRING_TYPE
 
-        assert ClassHelper.Integer_TYPE == typeInfo[1]
+        assert typeInfo[1] == ClassHelper.Integer_TYPE
     }
 
     @Test
@@ -269,10 +269,65 @@ final class GenericsUtilsTest {
 
         def typeInfo = GenericsUtils.parameterizeSAM(samType)
 
-        assert 2 == typeInfo[0].length
-        assert ClassHelper.Integer_TYPE == typeInfo[0][0]
-        assert ClassHelper.Integer_TYPE == typeInfo[0][1]
+        assert typeInfo.v1.length == 2
+        assert typeInfo.v1[0] == ClassHelper.Integer_TYPE
+        assert typeInfo.v1[1] == ClassHelper.Integer_TYPE
+
+        assert typeInfo.v2 == ClassHelper.Integer_TYPE
+    }
+
+    @Test // GROOVY-10813
+    void testParameterizeSAMWithRawType() {
+        def classNodeList = compile '''
+            interface I extends java.util.function.BinaryOperator {
+            }
+        '''
+        ClassNode samType = findClassNode('I', classNodeList).interfaces.find { it.name == 'java.util.function.BinaryOperator' }
+
+        def typeInfo = GenericsUtils.parameterizeSAM(samType)
+
+        assert typeInfo.v1.length == 2
+        assert typeInfo.v1[0].toString(false) == 'java.lang.Object'
+        assert typeInfo.v1[1].toString(false) == 'java.lang.Object'
+
+        assert typeInfo.v2.toString(false) == 'java.lang.Object'
+    }
+
+    @Test
+    void testParameterizeSAMWithRawTypeWithUpperBound() {
+        def classNodeList = compile '''
+            interface I<T extends CharSequence> {
+                T apply(T input);
+            }
+            abstract class A implements I {
+            }
+        '''
+        ClassNode samType = findClassNode('A', classNodeList).interfaces.find { it.name == 'I' }
+
+        def typeInfo = GenericsUtils.parameterizeSAM(samType)
+
+        assert typeInfo.v1.length == 1
+        assert typeInfo.v1[0].toString(false) == 'java.lang.CharSequence'
+
+        assert typeInfo.v2.toString(false) == 'java.lang.CharSequence'
+    }
+
+    @Test
+    void testParameterizeSAMWithRawTypeWithUpperBounds() {
+        def classNodeList = compile '''
+            interface I<T extends CharSequence & Serializable> {
+                T apply(T input);
+            }
+            abstract class A implements I {
+            }
+        '''
+        ClassNode samType = findClassNode('A', classNodeList).interfaces.find { it.name == 'I' }
+
+        def typeInfo = GenericsUtils.parameterizeSAM(samType)
+
+        assert typeInfo.v1.length == 1
+        assert typeInfo.v1[0].toString(false) == 'java.lang.CharSequence'
 
-        assert ClassHelper.Integer_TYPE == typeInfo[1]
+        assert typeInfo.v2.toString(false) == 'java.lang.CharSequence'
     }
 }