diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index e5bf9d76466..7e856cdc064 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -9336,6 +9336,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/provideDelegate"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @TestMetadata("delegatedPropertyWithIdProvideDelegate.kt") + public void testDelegatedPropertyWithIdProvideDelegate() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/delegatedPropertyWithIdProvideDelegate.kt"); + } + @TestMetadata("differentReceivers.kt") public void testDifferentReceivers() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt index b2a69e6287a..56a6ff7a16c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyInferenceSession.kt @@ -92,7 +92,15 @@ class DelegatedPropertyInferenceSession( object InferenceSessionForExistingCandidates : InferenceSession { override fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean { - return !ErrorUtils.isError(candidate.resolvedCall.candidateDescriptor) + if (ErrorUtils.isError(candidate.resolvedCall.candidateDescriptor)) return false + + val builder = candidate.getSystem().getBuilder() + for ((_, variable) in builder.currentStorage().notFixedTypeVariables) { + val hasProperConstraint = variable.constraints.any { candidate.getSystem().getBuilder().isProperType(it.type) } + if (hasProperConstraint) return true + } + + return false } override fun addPartialCallInfo(callInfo: PartialCallInfo) {} @@ -111,4 +119,21 @@ object InferenceSessionForExistingCandidates : InferenceSession { override fun shouldCompleteResolvedSubAtomsOf(resolvedCallAtom: ResolvedCallAtom): Boolean { return !ErrorUtils.isError(resolvedCallAtom.candidateDescriptor) } + + override fun computeCompletionMode( + candidate: KotlinResolutionCandidate + ): KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode? { + // this is a hack to mitigate questionable behavior in delegated properties design, namely: + // see test DelegatedProperty.ProvideDelegate#testHostAndReceiver2 + + // Normally, provideDelegate should be analyzed in INDEPENDENT mode, but now in OI there is one corner case, which + // doesn't fit into this design + val builder = candidate.getSystem().getBuilder() + for ((_, variable) in builder.currentStorage().notFixedTypeVariables) { + val hasProperConstraint = variable.constraints.any { candidate.getSystem().getBuilder().isProperType(it.type) } + if (hasProperConstraint) return null + } + + return KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.kt index 7bf1e7f9f75..da767087761 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.kt @@ -406,7 +406,7 @@ class DelegatedPropertyResolver( ): ExpressionTypingContext { return ExpressionTypingContext.newContext( trace, scopeForDelegate, dataFlowInfo, - NO_EXPECTED_TYPE, ContextDependency.DEPENDENT, StatementFilter.NONE, + NO_EXPECTED_TYPE, ContextDependency.INDEPENDENT, StatementFilter.NONE, languageVersionSettings, dataFlowValueFactory, inferenceExtension ) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ManyCandidatesResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ManyCandidatesResolver.kt index 57814c28f2d..221a5c1e569 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ManyCandidatesResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ManyCandidatesResolver.kt @@ -157,6 +157,8 @@ abstract class ManyCandidatesResolver( return allCandidates } + override fun computeCompletionMode(candidate: KotlinResolutionCandidate) = null + private fun PartialCallInfo.asCallResolutionResult( diagnosticsHolder: KotlinDiagnosticsHolder.SimpleHolder, commonSystem: NewConstraintSystem diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CompletionModeCalculator.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CompletionModeCalculator.kt index 0dc000b6956..af2503cc5fb 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CompletionModeCalculator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CompletionModeCalculator.kt @@ -26,8 +26,11 @@ class CompletionModeCalculator { candidate: KotlinResolutionCandidate, expectedType: UnwrappedType?, returnType: UnwrappedType?, - trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle + trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle, + inferenceSession: InferenceSession ): ConstraintSystemCompletionMode = with(candidate) { + inferenceSession.computeCompletionMode(candidate)?.let { return it } + val csCompleterContext = getSystem().asConstraintSystemCompleterContext() if (candidate.isErrorCandidate()) return ConstraintSystemCompletionMode.FULL diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/InferenceSession.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/InferenceSession.kt index 8784e366f5b..54788e6b43f 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/InferenceSession.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/InferenceSession.kt @@ -5,8 +5,8 @@ package org.jetbrains.kotlin.resolve.calls.components +import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage -import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.UnwrappedType @@ -28,6 +28,9 @@ interface InferenceSession { override fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean = false override fun callCompleted(resolvedAtom: ResolvedAtom): Boolean = false override fun shouldCompleteResolvedSubAtomsOf(resolvedCallAtom: ResolvedCallAtom) = true + override fun computeCompletionMode( + candidate: KotlinResolutionCandidate + ): KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode? = null } } @@ -45,6 +48,7 @@ interface InferenceSession { fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean fun callCompleted(resolvedAtom: ResolvedAtom): Boolean fun shouldCompleteResolvedSubAtomsOf(resolvedCallAtom: ResolvedCallAtom): Boolean + fun computeCompletionMode(candidate: KotlinResolutionCandidate): KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode? } interface PartialCallInfo { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt index 53f5bad4982..d59df9b6175 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt @@ -47,7 +47,9 @@ class KotlinCallCompleter( candidate.checkSamWithVararg(diagnosticHolder) val completionMode = - CompletionModeCalculator.computeCompletionMode(candidate, expectedType, returnType, trivialConstraintTypeInferenceOracle) + CompletionModeCalculator.computeCompletionMode( + candidate, expectedType, returnType, trivialConstraintTypeInferenceOracle, resolutionCallbacks.inferenceSession + ) return when (completionMode) { ConstraintSystemCompletionMode.FULL -> { diff --git a/compiler/testData/codegen/box/delegatedProperty/provideDelegate/delegatedPropertyWithIdProvideDelegate.kt b/compiler/testData/codegen/box/delegatedProperty/provideDelegate/delegatedPropertyWithIdProvideDelegate.kt new file mode 100644 index 00000000000..e502a3241d9 --- /dev/null +++ b/compiler/testData/codegen/box/delegatedProperty/provideDelegate/delegatedPropertyWithIdProvideDelegate.kt @@ -0,0 +1,23 @@ +// WITH_RUNTIME +// KJS_WITH_FULL_RUNTIME + +val test1: Map by lazy(LazyThreadSafetyMode.NONE) { + mapOf("string" to "string").mapValues { it.toString() } +} + +val test2: String by myDelegate("OK") + +fun myDelegate(initializer: T): Delegate = Delegate(initializer) + +class Delegate(val initializer: T) { + operator fun getValue(thisRef: Any?, property: kotlin.reflect.KProperty<*>): T { + return initializer + } +} + +operator fun T.provideDelegate(receiver: Any?, property: kotlin.reflect.KProperty<*>): T = this + +fun box(): String { + test1 + return test2 +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/commonCaseForInference.kt b/compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/commonCaseForInference.kt index 8f5b12b2ebb..642a990d0dd 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/commonCaseForInference.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/commonCaseForInference.kt @@ -9,6 +9,6 @@ object CommonCase { operator fun Fas.provideDelegate(host: D, p: Any?): Fas = TODO() operator fun Fas.getValue(receiver: E, p: Any?): R = TODO() - val Long.test1: String by delegate() // common test, not working because of Inference1 + val Long.test1: String by delegate() // common test, not working because of Inference1 val Long.test2: String by delegate() // should work } \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 1e9ffba2bb7..e6cc56f08a7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -10551,6 +10551,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/provideDelegate"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @TestMetadata("delegatedPropertyWithIdProvideDelegate.kt") + public void testDelegatedPropertyWithIdProvideDelegate() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/delegatedPropertyWithIdProvideDelegate.kt"); + } + @TestMetadata("differentReceivers.kt") public void testDifferentReceivers() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 71f06b2f808..962e96c5339 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -10551,6 +10551,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/provideDelegate"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @TestMetadata("delegatedPropertyWithIdProvideDelegate.kt") + public void testDelegatedPropertyWithIdProvideDelegate() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/delegatedPropertyWithIdProvideDelegate.kt"); + } + @TestMetadata("differentReceivers.kt") public void testDifferentReceivers() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt"); @@ -24850,15 +24855,15 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public static class MethodsFromAny extends AbstractLightAnalysisModeTest { - @TestMetadata("adaptedCallableReferencesNotEqualToCallablesFromAPI.kt") - public void ignoreAdaptedCallableReferencesNotEqualToCallablesFromAPI() throws Exception { - runTest("compiler/testData/codegen/box/reflection/methodsFromAny/adaptedCallableReferencesNotEqualToCallablesFromAPI.kt"); - } - private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); } + @TestMetadata("adaptedCallableReferencesNotEqualToCallablesFromAPI.kt") + public void testAdaptedCallableReferencesNotEqualToCallablesFromAPI() throws Exception { + runTest("compiler/testData/codegen/box/reflection/methodsFromAny/adaptedCallableReferencesNotEqualToCallablesFromAPI.kt"); + } + public void testAllFilesPresentInMethodsFromAny() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/methodsFromAny"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index fd48edf863f..e259032337c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -9336,6 +9336,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/provideDelegate"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @TestMetadata("delegatedPropertyWithIdProvideDelegate.kt") + public void testDelegatedPropertyWithIdProvideDelegate() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/delegatedPropertyWithIdProvideDelegate.kt"); + } + @TestMetadata("differentReceivers.kt") public void testDifferentReceivers() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index e25c02af586..ba1b1ea5d9a 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -8001,6 +8001,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/provideDelegate"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); } + @TestMetadata("delegatedPropertyWithIdProvideDelegate.kt") + public void testDelegatedPropertyWithIdProvideDelegate() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/delegatedPropertyWithIdProvideDelegate.kt"); + } + @TestMetadata("differentReceivers.kt") public void testDifferentReceivers() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index fea29d8bf8d..746ef5fc504 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -8001,6 +8001,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/provideDelegate"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); } + @TestMetadata("delegatedPropertyWithIdProvideDelegate.kt") + public void testDelegatedPropertyWithIdProvideDelegate() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/delegatedPropertyWithIdProvideDelegate.kt"); + } + @TestMetadata("differentReceivers.kt") public void testDifferentReceivers() throws Exception { runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");