diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt index 98b79206fc9..1cfdf0fab9c 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.SyntheticScope import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.checker.findCorrespondingSupertype import java.util.* import kotlin.properties.Delegates @@ -58,10 +59,8 @@ class SamAdapterFunctionsScope( override fun getSyntheticMemberFunctions(receiverTypes: Collection, name: Name, location: LookupLocation): Collection { var result: SmartList? = null for (type in receiverTypes) { - val substitutorForType by lazy { buildMemberScopeSubstitutorForType(type) } - for (function in type.memberScope.getContributedFunctions(name, location)) { - val extension = extensionForFunction(function.original)?.substitute(substitutorForType) + val extension = extensionForFunction(function.original)?.substituteForReceiverType(type) if (extension != null) { if (result == null) { result = SmartList() @@ -77,15 +76,24 @@ class SamAdapterFunctionsScope( } } - private fun buildMemberScopeSubstitutorForType(type: KotlinType) = - TypeConstructorSubstitution.create(type).wrapWithCapturingSubstitution(needApproximation = true).buildSubstitutor() + private fun FunctionDescriptor.substituteForReceiverType(receiverType: KotlinType): FunctionDescriptor? { + val containingClass = containingDeclaration as? ClassDescriptor ?: return null + val correspondingSupertype = findCorrespondingSupertype(receiverType, containingClass.defaultType) ?: return null + + return substitute( + TypeConstructorSubstitution + .create(correspondingSupertype) + .wrapWithCapturingSubstitution(needApproximation = true) + .buildSubstitutor() + ) + } override fun getSyntheticMemberFunctions(receiverTypes: Collection): Collection { return receiverTypes.flatMapTo(LinkedHashSet()) { type -> type.memberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS) .filterIsInstance() .mapNotNull { - extensionForFunction(it.original)?.substitute(buildMemberScopeSubstitutorForType(type)) + extensionForFunction(it.original)?.substituteForReceiverType(type) } } } diff --git a/compiler/testData/diagnostics/tests/j+k/sam/samOnTypeParameter.kt b/compiler/testData/diagnostics/tests/j+k/sam/samOnTypeParameter.kt new file mode 100644 index 00000000000..4b32b73471d --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/sam/samOnTypeParameter.kt @@ -0,0 +1,17 @@ +// FILE: FormFieldValidatorPresenterTest.java +public class FormFieldValidatorPresenterTest { + + public void setValidationListenerTest(ValidationListenerTest validationListener) { + } + + public interface ValidationListenerTest { + void onValidityChanged(boolean valid); + } +} +// FILE: main.kt +fun

> setValidationListener( + presenter: P, + validationListener: (Boolean) -> Unit +) { + presenter.setValidationListenerTest(validationListener) // Error: Type mismatch: inferred type is (Boolean) -> Unit but FormFieldValidatorPresenterTest.ValidationListenerTest! was expected +} diff --git a/compiler/testData/diagnostics/tests/j+k/sam/samOnTypeParameter.txt b/compiler/testData/diagnostics/tests/j+k/sam/samOnTypeParameter.txt new file mode 100644 index 00000000000..03e070dfeec --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/sam/samOnTypeParameter.txt @@ -0,0 +1,21 @@ +package + +public fun > setValidationListener(/*0*/ presenter: P, /*1*/ validationListener: (kotlin.Boolean) -> kotlin.Unit): kotlin.Unit + +public open class FormFieldValidatorPresenterTest { + public constructor FormFieldValidatorPresenterTest() + 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 fun setValidationListenerTest(/*0*/ validationListener: FormFieldValidatorPresenterTest.ValidationListenerTest!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public interface ValidationListenerTest { + 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 abstract fun onValidityChanged(/*0*/ valid: kotlin.Boolean): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + // Static members + public final /*synthesized*/ fun ValidationListenerTest(/*0*/ function: (valid: kotlin.Boolean) -> kotlin.Unit): FormFieldValidatorPresenterTest.ValidationListenerTest +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 65ab17d9739..48bba762f01 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -12234,6 +12234,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("samOnTypeParameter.kt") + public void testSamOnTypeParameter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/sam/samOnTypeParameter.kt"); + doTest(fileName); + } + @TestMetadata("typeInferenceOnSamAdapters.kt") public void testTypeInferenceOnSamAdapters() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/sam/typeInferenceOnSamAdapters.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/utils.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/utils.kt index cd9a2c8e613..3646b041b4f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/utils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/utils.kt @@ -27,7 +27,7 @@ private class SubtypePathNode(val type: KotlinType, val previous: SubtypePathNod fun findCorrespondingSupertype( subtype: KotlinType, supertype: KotlinType, - typeCheckingProcedureCallbacks: TypeCheckingProcedureCallbacks + typeCheckingProcedureCallbacks: TypeCheckingProcedureCallbacks = TypeCheckerProcedureCallbacksImpl() ): KotlinType? { val queue = ArrayDeque() queue.add(SubtypePathNode(subtype, null)) @@ -99,4 +99,4 @@ private fun TypeConstructor.debugInfo() = buildString { declarationDescriptor = declarationDescriptor.containingDeclaration } -} \ No newline at end of file +}