diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/SamType.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/SamType.java index 902766fe74d..df165f3d694 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/SamType.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/SamType.java @@ -72,11 +72,8 @@ public class SamType { @NotNull public KotlinType getKotlinFunctionType() { ClassDescriptor descriptor = getClassDescriptor(); - if (descriptor instanceof JavaClassDescriptor) { - return ((JavaClassDescriptor) descriptor).getDefaultFunctionTypeForSamInterface(); - } - - return null; + //noinspection ConstantConditions + return descriptor.getDefaultFunctionTypeForSamInterface(); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyClassContext.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyClassContext.kt index 742906ef11d..27ccccd5275 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyClassContext.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyClassContext.kt @@ -45,4 +45,5 @@ interface LazyClassContext { val delegationFilter: DelegationFilter val wrappedTypeFactory: WrappedTypeFactory val kotlinTypeChecker: NewKotlinTypeChecker + val samConversionResolver: SamConversionResolver } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java index 6b23477eebd..0c77fce2e74 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java @@ -83,6 +83,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { private DelegationFilter delegationFilter; private WrappedTypeFactory wrappedTypeFactory; private PlatformDiagnosticSuppressor platformDiagnosticSuppressor; + private SamConversionResolver samConversionResolver; private final SyntheticResolveExtension syntheticResolveExtension; @@ -150,6 +151,11 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { this.platformDiagnosticSuppressor = platformDiagnosticSuppressor; } + @Inject + public void setSamConversionResolver(@NotNull SamConversionResolver samConversionResolver) { + this.samConversionResolver = samConversionResolver; + } + // Only calls from injectors expected @Deprecated public ResolveSession( @@ -477,4 +483,10 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { public NewKotlinTypeChecker getKotlinTypeChecker() { return kotlinTypeChecker; } + + @NotNull + @Override + public SamConversionResolver getSamConversionResolver() { + return samConversionResolver; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java index 641af53c4a5..53c51b2c48a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java @@ -421,6 +421,17 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes return companionObjectDescriptor.invoke(); } + @Nullable + @Override + public SimpleType getDefaultFunctionTypeForSamInterface() { + return c.getSamConversionResolver().resolveFunctionTypeIfSamInterface(this); + } + + @Override + public boolean isDefinitelyNotSamInterface() { + return !isFun(); + } + @NotNull @ReadOnly public List getDescriptorsForExtraCompanionObjects() { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LocalClassifierAnalyzer.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LocalClassifierAnalyzer.kt index e1cb7b1dca1..bde18700c5e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LocalClassifierAnalyzer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LocalClassifierAnalyzer.kt @@ -67,7 +67,8 @@ class LocalClassifierAnalyzer( private val languageVersionSettings: LanguageVersionSettings, private val delegationFilter: DelegationFilter, private val wrappedTypeFactory: WrappedTypeFactory, - private val kotlinTypeChecker: NewKotlinTypeChecker + private val kotlinTypeChecker: NewKotlinTypeChecker, + private val samConversionResolver: SamConversionResolver ) { fun processClassOrObject( scope: LexicalWritableScope?, @@ -101,7 +102,8 @@ class LocalClassifierAnalyzer( SyntheticResolveExtension.getInstance(project), delegationFilter, wrappedTypeFactory, - kotlinTypeChecker + kotlinTypeChecker, + samConversionResolver ), analyzerServices ) @@ -130,7 +132,8 @@ class LocalClassDescriptorHolder( val syntheticResolveExtension: SyntheticResolveExtension, val delegationFilter: DelegationFilter, val wrappedTypeFactory: WrappedTypeFactory, - val kotlinTypeChecker: NewKotlinTypeChecker + val kotlinTypeChecker: NewKotlinTypeChecker, + val samConversionResolver: SamConversionResolver ) { // We do not need to synchronize here, because this code is used strictly from one thread private var classDescriptor: ClassDescriptor? = null @@ -171,6 +174,7 @@ class LocalClassDescriptorHolder( override val delegationFilter: DelegationFilter = this@LocalClassDescriptorHolder.delegationFilter override val wrappedTypeFactory: WrappedTypeFactory = this@LocalClassDescriptorHolder.wrappedTypeFactory override val kotlinTypeChecker: NewKotlinTypeChecker = this@LocalClassDescriptorHolder.kotlinTypeChecker + override val samConversionResolver: SamConversionResolver = this@LocalClassDescriptorHolder.samConversionResolver }, containingDeclaration, classOrObject.nameAsSafeName, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/WrappedDescriptors.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/WrappedDescriptors.kt index cf9a5a21cf9..9af42eb5ebf 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/WrappedDescriptors.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/WrappedDescriptors.kt @@ -638,6 +638,14 @@ open class WrappedClassDescriptor( override fun acceptVoid(visitor: DeclarationDescriptorVisitor?) { visitor!!.visitClassDescriptor(this, null) } + + override fun getDefaultFunctionTypeForSamInterface(): SimpleType? { + return owner.descriptor.defaultFunctionTypeForSamInterface + } + + override fun isDefinitelyNotSamInterface(): Boolean { + return owner.descriptor.isDefinitelyNotSamInterface + } } class LazyTypeConstructor( @@ -751,6 +759,10 @@ open class WrappedEnumEntryDescriptor( override fun acceptVoid(visitor: DeclarationDescriptorVisitor?) { visitor!!.visitClassDescriptor(this, null) } + + override fun getDefaultFunctionTypeForSamInterface(): SimpleType? = null + + override fun isDefinitelyNotSamInterface() = true } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/descriptors/JavaClassDescriptor.java b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/descriptors/JavaClassDescriptor.java index 6d769cc868d..23f0232716f 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/descriptors/JavaClassDescriptor.java +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/descriptors/JavaClassDescriptor.java @@ -16,18 +16,7 @@ package org.jetbrains.kotlin.load.java.descriptors; -import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.ClassDescriptor; -import org.jetbrains.kotlin.types.SimpleType; public interface JavaClassDescriptor extends ClassDescriptor { - // Use SingleAbstractMethodUtils.getFunctionTypeForSamInterface() where possible. This is only a fallback - @Nullable - SimpleType getDefaultFunctionTypeForSamInterface(); - - /** - * May return false even in case when the class is not SAM interface, but returns true only if it's definitely not a SAM. - * But it should work much faster than the exact check. - */ - boolean isDefinitelyNotSamInterface(); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassDescriptor.java index 02133a552df..d79874f3bf8 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ClassDescriptor.java @@ -98,4 +98,14 @@ public interface ClassDescriptor extends ClassifierDescriptorWithTypeParameters, @NotNull @Override ClassDescriptor getOriginal(); + + // Use SingleAbstractMethodUtils.getFunctionTypeForSamInterface() where possible. This is only a fallback + @Nullable + SimpleType getDefaultFunctionTypeForSamInterface(); + + /** + * May return false even in case when the class is not SAM interface, but returns true only if it's definitely not a SAM. + * But it should work much faster than the exact check. + */ + boolean isDefinitelyNotSamInterface(); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java index a45eb8853cb..120215f847f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.descriptors.impl; import kotlin.jvm.functions.Function0; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.DescriptorUtils; @@ -176,4 +177,15 @@ public abstract class AbstractClassDescriptor extends ModuleAwareClassDescriptor public R accept(DeclarationDescriptorVisitor visitor, D data) { return visitor.visitClassDescriptor(this, data); } + + @Nullable + @Override + public SimpleType getDefaultFunctionTypeForSamInterface() { + return null; + } + + @Override + public boolean isDefinitelyNotSamInterface() { + return false; + } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java index 827371c5b5f..09b43f65548 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java @@ -308,4 +308,25 @@ public class LazySubstitutingClassDescriptor extends ModuleAwareClassDescriptor public Collection getSealedSubclasses() { return original.getSealedSubclasses(); } + + @Nullable + @Override + public SimpleType getDefaultFunctionTypeForSamInterface() { + SimpleType type = original.getDefaultFunctionTypeForSamInterface(); + if (type == null || originalSubstitutor.isEmpty()) return type; + + TypeSubstitutor substitutor = getSubstitutor(); + KotlinType substitutedType = substitutor.substitute(type, Variance.INVARIANT); + + assert substitutedType instanceof SimpleType : + "Substitution for SimpleType should also be a SimpleType, but it is " + substitutedType + "\n" + + "Unsubstituted: " + type; + + return (SimpleType) substitutedType; + } + + @Override + public boolean isDefinitelyNotSamInterface() { + return original.isDefinitelyNotSamInterface(); + } }