Ignore type parameters in value arguments while comparing SAM adapters

#KT-8388 Fixed
This commit is contained in:
Denis Zharkov
2015-07-10 08:46:27 +03:00
parent aa34fe6352
commit 76648878e0
11 changed files with 244 additions and 5 deletions
@@ -50,19 +50,27 @@ public class SamAdapterOverridabilityCondition implements ExternalOverridability
for (ValueParameterDescriptor param1 : parameters1) {
ValueParameterDescriptor param2 = parameters2.get(param1.getIndex());
if (!equalClasses(param2.getType(), param1.getType())) {
if (differentClasses(param2.getType(), param1.getType())) {
return false;
}
}
return true;
}
private static boolean equalClasses(@NotNull JetType type1, @NotNull JetType type2) {
private static boolean differentClasses(@NotNull JetType type1, @NotNull JetType type2) {
DeclarationDescriptor declarationDescriptor1 = type1.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor1 == null) return false; // No class, classes are not equal
if (declarationDescriptor1 == null) return true; // No class, classes are not equal
DeclarationDescriptor declarationDescriptor2 = type2.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor2 == null) return false; // Class of type1 is not null
return declarationDescriptor1.getOriginal().equals(declarationDescriptor2.getOriginal());
if (declarationDescriptor2 == null) return true; // Class of type1 is not null
if (declarationDescriptor1 instanceof TypeParameterDescriptor && declarationDescriptor2 instanceof TypeParameterDescriptor) {
// if type of value parameter is some generic parameter then their equality was checked by OverridingUtil before calling ExternalOverridabilityCondition
// Note that it's true unless we generate sam adapter for type parameter with SAM interface as upper bound:
// <K extends Runnable >void foo(K runnable) {}
return false;
}
return !declarationDescriptor1.getOriginal().equals(declarationDescriptor2.getOriginal());
}
// if function is or overrides declaration, returns null; otherwise, return original of sam adapter with substituted type parameters
@@ -0,0 +1,22 @@
// FILE: MyFunc.java
public interface MyFunc<K, V> {
V apply(K String);
}
// FILE: ConcMap.java
public interface ConcMap<K, V> {
V computeIfAbsent(K key, MyFunc<? super K,? extends V> mappingFunction);
}
// FILE: ConcHashMap.java
public class ConcHashMap<K, V> implements ConcMap<K, V> {
@Override
V computeIfAbsent(K key, MyFunc<? super K,? extends V> mappingFunction) { }
}
// FILE: main.kt
public fun concurrentMap() {
val map = ConcHashMap<String, String>()
map.computeIfAbsent("") { "" } // here
}
@@ -0,0 +1,29 @@
package
public /*synthesized*/ fun </*0*/ K, /*1*/ V> ConcMap(/*0*/ function: (K!, MyFunc<in K!, out V!>!) -> V!): ConcMap<K, V>
public /*synthesized*/ fun </*0*/ K, /*1*/ V> MyFunc(/*0*/ function: (K!) -> V!): MyFunc<K, V>
public fun concurrentMap(): kotlin.Unit
public open class ConcHashMap</*0*/ K, /*1*/ V> : ConcMap<K!, V!> {
public constructor ConcHashMap</*0*/ K, /*1*/ V>()
java.lang.Override() public/*package*/ final override /*1*/ /*synthesized*/ fun computeIfAbsent(/*0*/ key: K!, /*1*/ mappingFunction: ((K!) -> V!)!): V!
java.lang.Override() public/*package*/ open override /*1*/ fun computeIfAbsent(/*0*/ key: K!, /*1*/ mappingFunction: MyFunc<in K!, out V!>!): V!
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface ConcMap</*0*/ K, /*1*/ V> {
public final /*synthesized*/ fun computeIfAbsent(/*0*/ key: K!, /*1*/ mappingFunction: ((K!) -> V!)!): V!
public abstract fun computeIfAbsent(/*0*/ key: K!, /*1*/ mappingFunction: MyFunc<in K!, out V!>!): V!
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface MyFunc</*0*/ K, /*1*/ V> {
public abstract fun apply(/*0*/ String: K!): V!
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,22 @@
// FILE: MyFunc.java
public interface MyFunc {
String apply(String x);
}
// FILE: A.java
public interface A<K> {
K foo(K key, MyFunc f);
}
// FILE: B.java
public class B<E> implements A<E> {
@Override
public E foo(E key, MyFunc f) {return null;}
}
// FILE: main.kt
fun main() {
B<String>().foo("") { "" }
}
@@ -0,0 +1,29 @@
package
public /*synthesized*/ fun </*0*/ K> A(/*0*/ function: (K!, MyFunc!) -> K!): A<K>
public /*synthesized*/ fun MyFunc(/*0*/ function: (kotlin.String!) -> kotlin.String!): MyFunc
internal fun main(): kotlin.Unit
public interface A</*0*/ K> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final /*synthesized*/ fun foo(/*0*/ key: K!, /*1*/ f: ((kotlin.String!) -> kotlin.String!)!): K!
public abstract fun foo(/*0*/ key: K!, /*1*/ f: MyFunc!): K!
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public open class B</*0*/ E> : A<E!> {
public constructor B</*0*/ E>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
java.lang.Override() public final override /*1*/ /*synthesized*/ fun foo(/*0*/ key: E!, /*1*/ f: ((kotlin.String!) -> kotlin.String!)!): E!
java.lang.Override() public open override /*1*/ fun foo(/*0*/ key: E!, /*1*/ f: MyFunc!): E!
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface MyFunc {
public abstract fun apply(/*0*/ x: kotlin.String!): kotlin.String!
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,24 @@
package test;
class NoSamForTypeParameter<K extends Runnable> {
void foo(K runnable1, Runnable runnable2) {}
}
class NoSamForTypeParameterDerived1 extends NoSamForTypeParameter<Runnable> {
@Override
void foo(Runnable runnable1, Runnable runnable2) {}
}
class NoSamForTypeParameterDerived2<E extends Runnable> extends NoSamForTypeParameter<E> {
void foo(E runnable1, Runnable runnable2) {}
}
class NoSamForTypeParameterDerived3 extends NoSamForTypeParameterDerived1 {
@Override
void foo(Runnable runnable1, Runnable runnable2) {}
}
class NoSamForTypeParameterDerived4 extends NoSamForTypeParameterDerived2<Runnable> {
@Override
void foo(Runnable runnable1, Runnable runnable2) {}
}
@@ -0,0 +1,34 @@
package test
public/*package*/ open class NoSamForTypeParameter</*0*/ K : java.lang.Runnable!> {
public/*package*/ constructor NoSamForTypeParameter</*0*/ K : java.lang.Runnable!>()
public/*package*/ final /*synthesized*/ fun foo(/*0*/ p0: K!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ open fun foo(/*0*/ p0: K!, /*1*/ p1: java.lang.Runnable!): kotlin.Unit
}
public/*package*/ open class NoSamForTypeParameterDerived1 : test.NoSamForTypeParameter<java.lang.Runnable!> {
public/*package*/ constructor NoSamForTypeParameterDerived1()
public/*package*/ final /*synthesized*/ fun foo(/*0*/ p0: (() -> kotlin.Unit)!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ final override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: java.lang.Runnable!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ open override /*1*/ fun foo(/*0*/ p0: java.lang.Runnable!, /*1*/ p1: java.lang.Runnable!): kotlin.Unit
}
public/*package*/ open class NoSamForTypeParameterDerived2</*0*/ E : java.lang.Runnable!> : test.NoSamForTypeParameter<E!> {
public/*package*/ constructor NoSamForTypeParameterDerived2</*0*/ E : java.lang.Runnable!>()
public/*package*/ final override /*1*/ /*synthesized*/ fun foo(/*0*/ p0: E!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ open override /*1*/ fun foo(/*0*/ p0: E!, /*1*/ p1: java.lang.Runnable!): kotlin.Unit
}
public/*package*/ open class NoSamForTypeParameterDerived3 : test.NoSamForTypeParameterDerived1 {
public/*package*/ constructor NoSamForTypeParameterDerived3()
public/*package*/ final override /*1*/ /*synthesized*/ fun foo(/*0*/ p0: (() -> kotlin.Unit)!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ final override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: java.lang.Runnable!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ open override /*1*/ fun foo(/*0*/ p0: java.lang.Runnable!, /*1*/ p1: java.lang.Runnable!): kotlin.Unit
}
public/*package*/ open class NoSamForTypeParameterDerived4 : test.NoSamForTypeParameterDerived2<java.lang.Runnable!> {
public/*package*/ constructor NoSamForTypeParameterDerived4()
public/*package*/ final /*synthesized*/ fun foo(/*0*/ p0: (() -> kotlin.Unit)!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ final override /*1*/ /*fake_override*/ fun foo(/*0*/ p0: java.lang.Runnable!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ open override /*1*/ fun foo(/*0*/ p0: java.lang.Runnable!, /*1*/ p1: java.lang.Runnable!): kotlin.Unit
}
@@ -0,0 +1,20 @@
package test;
class NoSamForTypeParameter {
<K extends Runnable> void foo(K runnable1, Runnable runnable2) {}
}
class NoSamForTypeParameterDerived1 extends NoSamForTypeParameter {
@Override
void foo(Runnable runnable1, Runnable runnable2) {}
}
class NoSamForTypeParameterDerived2 extends NoSamForTypeParameter {
@Override
<K extends Runnable> void foo(K runnable1, Runnable runnable2) {}
}
class NoSamForTypeParameterDerived3 extends NoSamForTypeParameterDerived1 {
@Override
void foo(Runnable runnable1, Runnable runnable2) {}
}
@@ -0,0 +1,27 @@
package test
public/*package*/ open class NoSamForTypeParameter {
public/*package*/ constructor NoSamForTypeParameter()
public/*package*/ final /*synthesized*/ fun </*0*/ K : java.lang.Runnable!> foo(/*0*/ p0: K!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ open fun </*0*/ K : java.lang.Runnable!> foo(/*0*/ p0: K!, /*1*/ p1: java.lang.Runnable!): kotlin.Unit
}
public/*package*/ open class NoSamForTypeParameterDerived1 : test.NoSamForTypeParameter {
public/*package*/ constructor NoSamForTypeParameterDerived1()
public/*package*/ final /*synthesized*/ fun foo(/*0*/ p0: (() -> kotlin.Unit)!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ final override /*1*/ /*fake_override*/ fun </*0*/ K : java.lang.Runnable!> foo(/*0*/ p0: K!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ open fun foo(/*0*/ p0: java.lang.Runnable!, /*1*/ p1: java.lang.Runnable!): kotlin.Unit
}
public/*package*/ open class NoSamForTypeParameterDerived2 : test.NoSamForTypeParameter {
public/*package*/ constructor NoSamForTypeParameterDerived2()
public/*package*/ final override /*1*/ /*synthesized*/ fun </*0*/ K : java.lang.Runnable!> foo(/*0*/ p0: K!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ open override /*1*/ fun </*0*/ K : java.lang.Runnable!> foo(/*0*/ p0: K!, /*1*/ p1: java.lang.Runnable!): kotlin.Unit
}
public/*package*/ open class NoSamForTypeParameterDerived3 : test.NoSamForTypeParameterDerived1 {
public/*package*/ constructor NoSamForTypeParameterDerived3()
public/*package*/ final override /*1*/ /*synthesized*/ fun foo(/*0*/ p0: (() -> kotlin.Unit)!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ final override /*1*/ /*fake_override*/ fun </*0*/ K : java.lang.Runnable!> foo(/*0*/ p0: K!, /*1*/ p1: (() -> kotlin.Unit)!): kotlin.Unit
public/*package*/ open override /*1*/ fun foo(/*0*/ p0: java.lang.Runnable!, /*1*/ p1: java.lang.Runnable!): kotlin.Unit
}
@@ -7956,6 +7956,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("computeIfAbsentConcurrent.kt")
public void testComputeIfAbsentConcurrent() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/computeIfAbsentConcurrent.kt");
doTest(fileName);
}
@TestMetadata("GenericsInSupertypes.kt")
public void testGenericsInSupertypes() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/GenericsInSupertypes.kt");
@@ -8100,6 +8106,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("overrideWithSamAndTypeParameter.kt")
public void testOverrideWithSamAndTypeParameter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/overrideWithSamAndTypeParameter.kt");
doTest(fileName);
}
@TestMetadata("packagePrivateClassStaticMember.kt")
public void testPackagePrivateClassStaticMember() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/packagePrivateClassStaticMember.kt");
@@ -1580,6 +1580,18 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
doTestCompiledJava(fileName);
}
@TestMetadata("NoSamForClassTypeParameter.java")
public void testNoSamForClassTypeParameter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/sam/adapters/NoSamForClassTypeParameter.java");
doTestCompiledJava(fileName);
}
@TestMetadata("NoSamForMethodTypeParameter.java")
public void testNoSamForMethodTypeParameter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/sam/adapters/NoSamForMethodTypeParameter.java");
doTestCompiledJava(fileName);
}
@TestMetadata("NonTrivialFunctionType.java")
public void testNonTrivialFunctionType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/sam/adapters/NonTrivialFunctionType.java");