diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SamConversionResolverImpl.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SamConversionResolverImpl.kt index c11d47c13ad..fccd048386f 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SamConversionResolverImpl.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SamConversionResolverImpl.kt @@ -19,20 +19,13 @@ package org.jetbrains.kotlin.load.java.sam import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.load.java.components.SamConversionResolver import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaConstructorDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor -import org.jetbrains.kotlin.load.java.sources.JavaSourceElement -import org.jetbrains.kotlin.load.java.structure.JavaClass -import org.jetbrains.kotlin.load.java.structure.JavaMethod import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.checker.KotlinTypeChecker -import java.util.* object SamConversionResolverImpl : SamConversionResolver { override fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?): SamConstructorDescriptor? { @@ -51,41 +44,8 @@ object SamConversionResolverImpl : SamConversionResolver { } } - override fun resolveFunctionTypeIfSamInterface( - classDescriptor: JavaClassDescriptor, - resolveMethod: (JavaMethod) -> FunctionDescriptor - ): KotlinType? { - val jClass = (classDescriptor.source as? JavaSourceElement)?.javaElement as? JavaClass ?: return null - val samInterfaceMethod = SingleAbstractMethodUtils.getSamInterfaceMethod(jClass) ?: return null - val abstractMethod = if (jClass.fqName == samInterfaceMethod.containingClass.fqName) { - resolveMethod(samInterfaceMethod) - } - else { - findFunctionWithMostSpecificReturnType(TypeUtils.getAllSupertypes(classDescriptor.defaultType)) - } + override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): KotlinType? { + val abstractMethod = SingleAbstractMethodUtils.getSingleAbstractMethodOrNull(classDescriptor) ?: return null return SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(abstractMethod) } - - private fun findFunctionWithMostSpecificReturnType(supertypes: Set): SimpleFunctionDescriptor { - val candidates = ArrayList(supertypes.size) - for (supertype in supertypes) { - val abstractMembers = SingleAbstractMethodUtils.getAbstractMembers(supertype) - if (!abstractMembers.isEmpty()) { - candidates.add((abstractMembers[0] as SimpleFunctionDescriptor)) - } - } - if (candidates.isEmpty()) { - throw IllegalStateException("Couldn't find abstract method in supertypes " + supertypes) - } - var currentMostSpecificType = candidates[0] - for (candidate in candidates) { - val candidateReturnType = candidate.returnType - val currentMostSpecificReturnType = currentMostSpecificType.returnType - assert(candidateReturnType != null && currentMostSpecificReturnType != null) { "$candidate, $currentMostSpecificReturnType" } - if (KotlinTypeChecker.DEFAULT.isSubtypeOf(candidateReturnType!!, currentMostSpecificReturnType!!)) { - currentMostSpecificType = candidate - } - } - return currentMostSpecificType - } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java index 6fb230f115e..a22a8c9e552 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java @@ -18,26 +18,23 @@ package org.jetbrains.kotlin.load.java.sam; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl; -import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils; import org.jetbrains.kotlin.load.java.descriptors.*; import org.jetbrains.kotlin.load.java.lazy.types.LazyJavaTypeResolver; -import org.jetbrains.kotlin.load.java.structure.*; -import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.DescriptorUtils; -import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructorKt; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils; import org.jetbrains.kotlin.types.*; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; -import static org.jetbrains.kotlin.types.Variance.INVARIANT; import static org.jetbrains.kotlin.types.Variance.IN_VARIANCE; public class SingleAbstractMethodUtils { @@ -95,19 +92,23 @@ public class SingleAbstractMethodUtils { return DescriptorUtilsKt.getBuiltIns(function).getFunctionType(Annotations.Companion.getEMPTY(), null, parameterTypes, returnType); } - private static boolean isSamInterface(@NotNull ClassDescriptor klass) { + @Nullable + public static FunctionDescriptor getSingleAbstractMethodOrNull(@NotNull ClassDescriptor klass) { if (klass.getKind() != ClassKind.INTERFACE) { - return false; + return null; } List abstractMembers = getAbstractMembers(klass.getDefaultType()); if (abstractMembers.size() == 1) { CallableMemberDescriptor member = abstractMembers.get(0); if (member instanceof SimpleFunctionDescriptor) { - return member.getTypeParameters().isEmpty(); + return member.getTypeParameters().isEmpty() + ? (FunctionDescriptor) member + : null; } } - return false; + + return null; } @NotNull @@ -115,7 +116,7 @@ public class SingleAbstractMethodUtils { @NotNull DeclarationDescriptor owner, @NotNull JavaClassDescriptor samInterface ) { - assert isSamInterface(samInterface) : samInterface; + assert getSingleAbstractMethodOrNull(samInterface) != null : samInterface; SamConstructorDescriptor result = new SamConstructorDescriptor(owner, samInterface); @@ -282,29 +283,6 @@ public class SingleAbstractMethodUtils { return new TypeParameters(typeParameters, typeParametersSubstitutor); } - // Returns null if not SAM interface - @Nullable - public static JavaMethod getSamInterfaceMethod(@NotNull JavaClass javaClass) { - FqName fqName = javaClass.getFqName(); - if (fqName == null || fqName.toUnsafe().startsWith(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME)) { - return null; - } - if (!javaClass.isInterface() || javaClass.isAnnotationType()) { - return null; - } - - return findOnlyAbstractMethod(javaClass); - } - - @Nullable - private static JavaMethod findOnlyAbstractMethod(@NotNull JavaClass javaClass) { - OnlyAbstractMethodFinder finder = new OnlyAbstractMethodFinder(); - if (finder.find(javaClass.getDefaultType())) { - return finder.getFoundMethod(); - } - return null; - } - private static class TypeParameters { public final List descriptors; public final TypeSubstitutor substitutor; @@ -323,88 +301,5 @@ public class SingleAbstractMethodUtils { ); } - private static class OnlyAbstractMethodFinder { - private static final FqName OBJECT_FQ_NAME = new FqName("java.lang.Object"); - private JavaMethod foundMethod; - private JavaTypeSubstitutor foundClassSubstitutor; - - private boolean find(@NotNull JavaClassifierType classifierType) { - JavaTypeSubstitutor classSubstitutor = classifierType.getSubstitutor(); - JavaClassifier classifier = classifierType.getClassifier(); - if (classifier == null) { - return false; // can't resolve class -> not a SAM interface - } - assert classifier instanceof JavaClass : "Classifier should be a class here: " + classifier; - JavaClass javaClass = (JavaClass) classifier; - if (OBJECT_FQ_NAME.equals(javaClass.getFqName())) { - return true; - } - for (JavaMethod method : javaClass.getMethods()) { - - //skip java 8 default methods - if (!method.isAbstract()) { - continue; - } - - if (DescriptorResolverUtils.isObjectMethod(method)) { // e.g., ignore toString() declared in interface - continue; - } - if (!method.getTypeParameters().isEmpty()) { - return false; // if interface has generic methods, it is not a SAM interface - } - - if (foundMethod == null) { - foundMethod = method; - foundClassSubstitutor = classSubstitutor; - continue; - } - - if (!areSignaturesErasureEqual(method, classSubstitutor, foundMethod, foundClassSubstitutor)) { - return false; // different signatures - } - } - - for (JavaClassifierType t : classifierType.getSupertypes()) { - if (!find(t)) { - return false; - } - } - - return true; - } - - /** - * @see com.intellij.psi.util.MethodSignatureUtil#areSignaturesErasureEqual - */ - private static boolean areSignaturesErasureEqual( - @NotNull JavaMethod method1, - @NotNull JavaTypeSubstitutor substitutor1, - @NotNull JavaMethod method2, - @NotNull JavaTypeSubstitutor substitutor2 - ) { - if (!method1.getName().equals(method2.getName())) return false; - - Collection parameters1 = method1.getValueParameters(); - Collection parameters2 = method2.getValueParameters(); - if (parameters1.size() != parameters2.size()) return false; - - for (Iterator it1 = parameters1.iterator(), it2 = parameters2.iterator(); it1.hasNext(); ) { - JavaValueParameter param1 = it1.next(); - JavaValueParameter param2 = it2.next(); - if (param1.isVararg() != param2.isVararg()) return false; - - JavaType type1 = JavaResolverUtils.erasure(substitutor1.substitute(param1.getType()), substitutor1); - JavaType type2 = JavaResolverUtils.erasure(substitutor2.substitute(param2.getType()), substitutor2); - if (!(type1 == null ? type2 == null : type1.equals(type2))) return false; - } - - return true; - } - - @Nullable - private JavaMethod getFoundMethod() { - return foundMethod; - } - } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JavaResolverUtils.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JavaResolverUtils.java index 62188840bf6..b3b90476ef6 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JavaResolverUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JavaResolverUtils.java @@ -34,81 +34,6 @@ public class JavaResolverUtils { private JavaResolverUtils() { } - /** - * @see com.intellij.psi.util.TypeConversionUtil#erasure(com.intellij.psi.PsiType) - */ - @Nullable - public static JavaType erasure(@NotNull JavaType type) { - return erasure(type, JavaTypeSubstitutor.EMPTY); - } - - /** - * @see com.intellij.psi.util.TypeConversionUtil#erasure(com.intellij.psi.PsiType, com.intellij.psi.PsiSubstitutor) - */ - @Nullable - public static JavaType erasure(@NotNull JavaType type, @NotNull JavaTypeSubstitutor substitutor) { - if (type instanceof JavaClassifierType) { - JavaClassifier classifier = ((JavaClassifierType) type).getClassifier(); - if (classifier instanceof JavaClass) { - return ((JavaClass) classifier).getDefaultType(); - } - else if (classifier instanceof JavaTypeParameter) { - JavaTypeParameter typeParameter = (JavaTypeParameter) classifier; - return typeParameterErasure(typeParameter, new HashSet(), substitutor); - } - else { - return null; - } - } - else if (type instanceof JavaPrimitiveType) { - return type; - } - else if (type instanceof JavaArrayType) { - JavaType erasure = erasure(((JavaArrayType) type).getComponentType(), substitutor); - return erasure == null ? null : erasure.createArrayType(); - } - else if (type instanceof JavaWildcardType) { - JavaWildcardType wildcardType = (JavaWildcardType) type; - JavaType bound = wildcardType.getBound(); - if (bound != null && wildcardType.isExtends()) { - return erasure(bound, substitutor); - } - return wildcardType.getTypeProvider().createJavaLangObjectType(); - } - else { - throw new IllegalStateException("Unsupported type: " + type); - } - } - - /** - * @see com.intellij.psi.util.TypeConversionUtil#typeParameterErasure(com.intellij.psi.PsiTypeParameter) - */ - @Nullable - private static JavaType typeParameterErasure( - @NotNull JavaTypeParameter typeParameter, - @NotNull HashSet visited, - @NotNull JavaTypeSubstitutor substitutor - ) { - Collection upperBounds = typeParameter.getUpperBounds(); - if (!upperBounds.isEmpty()) { - JavaClassifier classifier = upperBounds.iterator().next().getClassifier(); - if (classifier instanceof JavaTypeParameter && !visited.contains(classifier)) { - JavaTypeParameter typeParameterBound = (JavaTypeParameter) classifier; - visited.add(typeParameterBound); - JavaType substitutedType = substitutor.substitute(typeParameterBound); - if (substitutedType != null) { - return erasure(substitutedType); - } - return typeParameterErasure(typeParameterBound, visited, substitutor); - } - else if (classifier instanceof JavaClass) { - return ((JavaClass) classifier).getDefaultType(); - } - } - return typeParameter.getTypeProvider().createJavaLangObjectType(); - } - - @NotNull public static Map recreateTypeParametersAndReturnMapping( @NotNull List originalParameters, @Nullable DeclarationDescriptor newOwner diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaCycle.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaCycle.kt new file mode 100644 index 00000000000..f7631022981 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaCycle.kt @@ -0,0 +1,28 @@ +// FILE: A.java + +public interface A extends A { + int getFoo(); +} + +// FILE: B.java + +public class B { + interface B1 extends B2 { + int getFoo(); + } + interface B2 extends B3 { + int getFoo(); + } + interface B3 extends B2 { + int getFoo(); + } +} + +// FILE: main.kt +fun foo() { + object : A { override fun getFoo() = 1 } + object : B.B1 { override fun getFoo() = 1 } + object : B.B2 { override fun getFoo() = 1 } + object : B.B3 { override fun getFoo() = 1 } +} + diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaCycle.txt b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaCycle.txt new file mode 100644 index 00000000000..941a2828b49 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaCycle.txt @@ -0,0 +1,32 @@ +package + +public /*synthesized*/ fun A(/*0*/ function: () -> kotlin.Int): A +public fun foo(): kotlin.Unit + +public interface A { + public abstract fun getFoo(): kotlin.Int +} + +public open class B { + public constructor B() + 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/*package*/ interface B1 : B.B2 { + public abstract override /*1*/ fun getFoo(): kotlin.Int + } + + public/*package*/ interface B2 { + public abstract fun getFoo(): kotlin.Int + } + + public/*package*/ interface B3 { + public abstract fun getFoo(): kotlin.Int + } + + // Static members + public/*package*/ final /*synthesized*/ fun B1(/*0*/ function: () -> kotlin.Int): B.B1 + public/*package*/ final /*synthesized*/ fun B2(/*0*/ function: () -> kotlin.Int): B.B2 + public/*package*/ final /*synthesized*/ fun B3(/*0*/ function: () -> kotlin.Int): B.B3 +} diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaNested.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaNested.kt new file mode 100644 index 00000000000..82a5d2f8eb6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaNested.kt @@ -0,0 +1,24 @@ +// FILE: A.java + +public interface A extends A.B { + interface B extends A { public int getFoo() { return 1; } } +} + +// FILE: A0.java +public interface A0 extends A0.B { + interface B { public int getFoo() { return 1; } } +} + +// FILE: B.java + +public class B extends D { + public int getFoo() { return 1; } + public static class C { + public int getFoo() { return 1; } + } +} + +// FILE: D.java +public class D extends B.C { + public int getFoo() { return 1; } +} diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaNested.txt b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaNested.txt new file mode 100644 index 00000000000..af0c054661f --- /dev/null +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaNested.txt @@ -0,0 +1,42 @@ +package + +public interface A { + + public interface B { + public abstract fun getFoo(): kotlin.Int + } + + // Static members + public final /*synthesized*/ fun B(/*0*/ function: () -> kotlin.Int): A.B +} + +public interface A0 { + + public interface B { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun getFoo(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + // Static members + public final /*synthesized*/ fun B(/*0*/ function: () -> kotlin.Int): A0.B +} + +public open class B { + public constructor B() + public open fun getFoo(): kotlin.Int + + public open class C { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun getFoo(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public open class D { + public constructor D() + public open fun getFoo(): kotlin.Int +} diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.txt b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.txt index 3d4d8052a1f..58e05105ad5 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.txt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.txt @@ -1,5 +1,8 @@ package +public/*package*/ /*synthesized*/ fun A(/*0*/ function: () -> kotlin.Unit): A +public/*package*/ /*synthesized*/ fun C(/*0*/ function: () -> kotlin.Unit): C + public/*package*/ interface A { public abstract fun foo(): kotlin.Unit } diff --git a/compiler/testData/diagnostics/tests/j+k/sam/enhancedSamConstructor.kt b/compiler/testData/diagnostics/tests/j+k/sam/enhancedSamConstructor.kt new file mode 100644 index 00000000000..240e825292f --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/sam/enhancedSamConstructor.kt @@ -0,0 +1,27 @@ +// FILE: J.java +import org.jetbrains.annotations.*; + +public interface J { + @NotNull + String foo(@Nullable String x); +} + +// FILE: J2.java +import org.jetbrains.annotations.Nullable; + +public interface J2 extends J { + String foo(String x); +} + +// FILE: main.kt +fun main() { + J { s: String -> s} // should be prohibited, because SAM value parameter has nullable type + J { "" + it.length } + J { null } + J { it?.length?.toString() } + + J2 { s: String -> s} + J2 { "" + it.length } + J2 { null } + J2 { it?.length?.toString() } +} diff --git a/compiler/testData/diagnostics/tests/j+k/sam/enhancedSamConstructor.txt b/compiler/testData/diagnostics/tests/j+k/sam/enhancedSamConstructor.txt new file mode 100644 index 00000000000..7be6a24e1a5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/sam/enhancedSamConstructor.txt @@ -0,0 +1,19 @@ +package + +public /*synthesized*/ fun J(/*0*/ function: (kotlin.String?) -> kotlin.String): J +public /*synthesized*/ fun J2(/*0*/ function: (kotlin.String?) -> kotlin.String): J2 +public fun main(): kotlin.Unit + +public interface J { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + @org.jetbrains.annotations.NotNull() public abstract fun foo(/*0*/ @org.jetbrains.annotations.Nullable() x: kotlin.String?): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface J2 : J { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*1*/ fun foo(/*0*/ x: kotlin.String?): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/types/returnCollection.txt b/compiler/testData/diagnostics/tests/j+k/types/returnCollection.txt index 5ac7d687cda..08467aacde0 100644 --- a/compiler/testData/diagnostics/tests/j+k/types/returnCollection.txt +++ b/compiler/testData/diagnostics/tests/j+k/types/returnCollection.txt @@ -1,6 +1,6 @@ package -public/*package*/ /*synthesized*/ fun J(/*0*/ function: () -> kotlin.collections.(Mutable)List!): J +public/*package*/ /*synthesized*/ fun J(/*0*/ function: () -> kotlin.collections.List): J public/*package*/ interface J : K { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean diff --git a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/flexibleReturnTypeIn.txt b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/flexibleReturnTypeIn.txt index 8e8e7d9af33..2f7c2ee9bb1 100644 --- a/compiler/testData/diagnostics/tests/override/clashesOnInheritance/flexibleReturnTypeIn.txt +++ b/compiler/testData/diagnostics/tests/override/clashesOnInheritance/flexibleReturnTypeIn.txt @@ -1,8 +1,8 @@ package public /*synthesized*/ fun J1(/*0*/ function: () -> In!): J1 -public /*synthesized*/ fun J2(/*0*/ function: () -> In!): J2 -public /*synthesized*/ fun J3(/*0*/ function: () -> In!): J3 +public /*synthesized*/ fun J2(/*0*/ function: () -> In): J2 +public /*synthesized*/ fun J3(/*0*/ function: () -> In?): J3 public interface In { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean diff --git a/compiler/testData/diagnostics/tests/platformTypes/noAnnotationInClassPath.txt b/compiler/testData/diagnostics/tests/platformTypes/noAnnotationInClassPath.txt index ebb70227eed..f02304cbe6a 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/noAnnotationInClassPath.txt +++ b/compiler/testData/diagnostics/tests/platformTypes/noAnnotationInClassPath.txt @@ -1,6 +1,6 @@ package -public /*synthesized*/ fun A(/*0*/ function: (T!) -> kotlin.Boolean): A +public /*synthesized*/ fun A(/*0*/ function: (T?) -> kotlin.Boolean): A public fun test(): kotlin.Unit public interface A { diff --git a/compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/enhancementFromAnnotation.txt b/compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/enhancementFromAnnotation.txt index 669fcc06979..5e50485a22e 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/enhancementFromAnnotation.txt +++ b/compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/enhancementFromAnnotation.txt @@ -1,6 +1,6 @@ package -public /*synthesized*/ fun A(/*0*/ function: (T!) -> kotlin.Unit): A +public /*synthesized*/ fun A(/*0*/ function: (T) -> kotlin.Unit): A public fun test(): kotlin.Unit public interface A { diff --git a/compiler/testData/diagnostics/tests/platformTypes/rawOverrides.txt b/compiler/testData/diagnostics/tests/platformTypes/rawOverrides.txt index 035ec4df2c5..fbe24904556 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/rawOverrides.txt +++ b/compiler/testData/diagnostics/tests/platformTypes/rawOverrides.txt @@ -1,5 +1,7 @@ package +public /*synthesized*/ fun B(/*0*/ function: (kotlin.Any!, kotlin.collections.(Mutable)List<(raw) kotlin.Any?>!) -> kotlin.String!): B + public interface A { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public abstract fun foo(/*0*/ x: T!, /*1*/ y: (kotlin.collections.MutableList..kotlin.collections.List?)): E! diff --git a/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/saveAnnotationAfterSubstitution.txt b/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/saveAnnotationAfterSubstitution.txt index dfa37ea45d8..4a40a46df32 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/saveAnnotationAfterSubstitution.txt +++ b/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/saveAnnotationAfterSubstitution.txt @@ -1,8 +1,8 @@ package -public /*synthesized*/ fun A(/*0*/ function: (T!, T!) -> kotlin.Unit): A +public /*synthesized*/ fun A(/*0*/ function: (T, T?) -> kotlin.Unit): A public /*synthesized*/ fun B1(/*0*/ function: (kotlin.String, kotlin.String?) -> kotlin.Unit): B1 -public /*synthesized*/ fun B2(/*0*/ function: (kotlin.String!, kotlin.String!) -> kotlin.Unit): B2 +public /*synthesized*/ fun B2(/*0*/ function: (kotlin.String, kotlin.String?) -> kotlin.Unit): B2 public /*synthesized*/ fun B3(/*0*/ function: (kotlin.String!, kotlin.String!) -> kotlin.Unit): B3 public interface A { diff --git a/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentParameterNullability.txt b/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentParameterNullability.txt index 4bdf98d4c2e..5f1871f76fb 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentParameterNullability.txt +++ b/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentParameterNullability.txt @@ -1,7 +1,7 @@ package -public /*synthesized*/ fun A(/*0*/ function: (kotlin.String!) -> kotlin.Unit): A -public /*synthesized*/ fun B(/*0*/ function: (kotlin.String!) -> kotlin.Unit): B +public /*synthesized*/ fun A(/*0*/ function: (kotlin.String?) -> kotlin.Unit): A +public /*synthesized*/ fun B(/*0*/ function: (kotlin.String) -> kotlin.Unit): B public interface A { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean diff --git a/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentReturnNullability.txt b/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentReturnNullability.txt index 1b5d34c1d19..bed63d30087 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentReturnNullability.txt +++ b/compiler/testData/diagnostics/tests/platformTypes/typeEnhancement/supertypeDifferentReturnNullability.txt @@ -1,7 +1,7 @@ package -public /*synthesized*/ fun A(/*0*/ function: () -> kotlin.String!): A -public /*synthesized*/ fun B(/*0*/ function: () -> kotlin.String!): B +public /*synthesized*/ fun A(/*0*/ function: () -> kotlin.String?): A +public /*synthesized*/ fun B(/*0*/ function: () -> kotlin.String): B public interface A { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/ParameterTypeAnnotation.txt b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/ParameterTypeAnnotation.txt index 31cd431d011..b7e62da3057 100644 --- a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/ParameterTypeAnnotation.txt +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/ParameterTypeAnnotation.txt @@ -1,6 +1,6 @@ package -public /*synthesized*/ fun JavaInterface(/*0*/ function: (kotlin.String!, java.lang.Runnable!) -> kotlin.Unit): JavaInterface +public /*synthesized*/ fun JavaInterface(/*0*/ function: (kotlin.String, java.lang.Runnable) -> kotlin.Unit): JavaInterface public fun foo(/*0*/ javaInterface: JavaInterface): kotlin.Unit public interface JavaInterface { diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 8433d6cc4af..77de74927f1 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -3585,6 +3585,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("javaJavaCycle.kt") + public void testJavaJavaCycle() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaCycle.kt"); + doTest(fileName); + } + + @TestMetadata("javaJavaNested.kt") + public void testJavaJavaNested() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/cyclicHierarchy/javaJavaNested.kt"); + doTest(fileName); + } + @TestMetadata("javaKotlinJavaCycle.kt") public void testJavaKotlinJavaCycle() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.kt"); @@ -10476,6 +10488,21 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { } } + @TestMetadata("compiler/testData/diagnostics/tests/j+k/sam") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Sam extends AbstractDiagnosticsTest { + public void testAllFilesPresentInSam() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/sam"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("enhancedSamConstructor.kt") + public void testEnhancedSamConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/sam/enhancedSamConstructor.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/j+k/samByProjectedType") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/SamConversionResolver.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/SamConversionResolver.kt index 491094ff9be..12e5c947b11 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/SamConversionResolver.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/SamConversionResolver.kt @@ -21,24 +21,18 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor -import org.jetbrains.kotlin.load.java.structure.JavaMethod import org.jetbrains.kotlin.types.KotlinType interface SamConversionResolver { companion object EMPTY : SamConversionResolver { override fun resolveSamAdapter(original: D) = null override fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?) = null - override fun resolveFunctionTypeIfSamInterface( - classDescriptor: JavaClassDescriptor, resolveMethod: (JavaMethod) -> FunctionDescriptor - ): KotlinType? = null + override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): KotlinType? = null } fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?): SamConstructorDescriptor? fun resolveSamAdapter(original: D): D? - fun resolveFunctionTypeIfSamInterface( - classDescriptor: JavaClassDescriptor, - resolveMethod: (JavaMethod) -> FunctionDescriptor - ): KotlinType? + fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): KotlinType? } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt index 2fe1d1b9ffc..e1760d62693 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt @@ -107,9 +107,7 @@ class LazyJavaClassDescriptor( override fun getAnnotations() = annotations() private val functionTypeForSamInterface = c.storageManager.createNullableLazyValue { - c.components.samConversionResolver.resolveFunctionTypeIfSamInterface(this) { method -> - unsubstitutedMemberScope.resolveMethodToFunctionDescriptor(method) - } + c.components.samConversionResolver.resolveFunctionTypeIfSamInterface(this) } private val declaredParameters = c.storageManager.createLazyValue {