Fix delegated property resolve with intermediate ID provideDelegate
#KT-37406 Fixed
This commit is contained in:
Generated
+5
@@ -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);
|
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")
|
@TestMetadata("differentReceivers.kt")
|
||||||
public void testDifferentReceivers() throws Exception {
|
public void testDifferentReceivers() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");
|
||||||
|
|||||||
+26
-1
@@ -92,7 +92,15 @@ class DelegatedPropertyInferenceSession(
|
|||||||
|
|
||||||
object InferenceSessionForExistingCandidates : InferenceSession {
|
object InferenceSessionForExistingCandidates : InferenceSession {
|
||||||
override fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean {
|
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) {}
|
override fun addPartialCallInfo(callInfo: PartialCallInfo) {}
|
||||||
@@ -111,4 +119,21 @@ object InferenceSessionForExistingCandidates : InferenceSession {
|
|||||||
override fun shouldCompleteResolvedSubAtomsOf(resolvedCallAtom: ResolvedCallAtom): Boolean {
|
override fun shouldCompleteResolvedSubAtomsOf(resolvedCallAtom: ResolvedCallAtom): Boolean {
|
||||||
return !ErrorUtils.isError(resolvedCallAtom.candidateDescriptor)
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ class DelegatedPropertyResolver(
|
|||||||
): ExpressionTypingContext {
|
): ExpressionTypingContext {
|
||||||
return ExpressionTypingContext.newContext(
|
return ExpressionTypingContext.newContext(
|
||||||
trace, scopeForDelegate, dataFlowInfo,
|
trace, scopeForDelegate, dataFlowInfo,
|
||||||
NO_EXPECTED_TYPE, ContextDependency.DEPENDENT, StatementFilter.NONE,
|
NO_EXPECTED_TYPE, ContextDependency.INDEPENDENT, StatementFilter.NONE,
|
||||||
languageVersionSettings, dataFlowValueFactory, inferenceExtension
|
languageVersionSettings, dataFlowValueFactory, inferenceExtension
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -157,6 +157,8 @@ abstract class ManyCandidatesResolver<D : CallableDescriptor>(
|
|||||||
return allCandidates
|
return allCandidates
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun computeCompletionMode(candidate: KotlinResolutionCandidate) = null
|
||||||
|
|
||||||
private fun PartialCallInfo.asCallResolutionResult(
|
private fun PartialCallInfo.asCallResolutionResult(
|
||||||
diagnosticsHolder: KotlinDiagnosticsHolder.SimpleHolder,
|
diagnosticsHolder: KotlinDiagnosticsHolder.SimpleHolder,
|
||||||
commonSystem: NewConstraintSystem
|
commonSystem: NewConstraintSystem
|
||||||
|
|||||||
+4
-1
@@ -26,8 +26,11 @@ class CompletionModeCalculator {
|
|||||||
candidate: KotlinResolutionCandidate,
|
candidate: KotlinResolutionCandidate,
|
||||||
expectedType: UnwrappedType?,
|
expectedType: UnwrappedType?,
|
||||||
returnType: UnwrappedType?,
|
returnType: UnwrappedType?,
|
||||||
trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle
|
trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle,
|
||||||
|
inferenceSession: InferenceSession
|
||||||
): ConstraintSystemCompletionMode = with(candidate) {
|
): ConstraintSystemCompletionMode = with(candidate) {
|
||||||
|
inferenceSession.computeCompletionMode(candidate)?.let { return it }
|
||||||
|
|
||||||
val csCompleterContext = getSystem().asConstraintSystemCompleterContext()
|
val csCompleterContext = getSystem().asConstraintSystemCompleterContext()
|
||||||
|
|
||||||
if (candidate.isErrorCandidate()) return ConstraintSystemCompletionMode.FULL
|
if (candidate.isErrorCandidate()) return ConstraintSystemCompletionMode.FULL
|
||||||
|
|||||||
+5
-1
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.components
|
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.ConstraintStorage
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.types.TypeConstructor
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
@@ -28,6 +28,9 @@ interface InferenceSession {
|
|||||||
override fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean = false
|
override fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean = false
|
||||||
override fun callCompleted(resolvedAtom: ResolvedAtom): Boolean = false
|
override fun callCompleted(resolvedAtom: ResolvedAtom): Boolean = false
|
||||||
override fun shouldCompleteResolvedSubAtomsOf(resolvedCallAtom: ResolvedCallAtom) = true
|
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 writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean
|
||||||
fun callCompleted(resolvedAtom: ResolvedAtom): Boolean
|
fun callCompleted(resolvedAtom: ResolvedAtom): Boolean
|
||||||
fun shouldCompleteResolvedSubAtomsOf(resolvedCallAtom: ResolvedCallAtom): Boolean
|
fun shouldCompleteResolvedSubAtomsOf(resolvedCallAtom: ResolvedCallAtom): Boolean
|
||||||
|
fun computeCompletionMode(candidate: KotlinResolutionCandidate): KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode?
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PartialCallInfo {
|
interface PartialCallInfo {
|
||||||
|
|||||||
+3
-1
@@ -47,7 +47,9 @@ class KotlinCallCompleter(
|
|||||||
candidate.checkSamWithVararg(diagnosticHolder)
|
candidate.checkSamWithVararg(diagnosticHolder)
|
||||||
|
|
||||||
val completionMode =
|
val completionMode =
|
||||||
CompletionModeCalculator.computeCompletionMode(candidate, expectedType, returnType, trivialConstraintTypeInferenceOracle)
|
CompletionModeCalculator.computeCompletionMode(
|
||||||
|
candidate, expectedType, returnType, trivialConstraintTypeInferenceOracle, resolutionCallbacks.inferenceSession
|
||||||
|
)
|
||||||
|
|
||||||
return when (completionMode) {
|
return when (completionMode) {
|
||||||
ConstraintSystemCompletionMode.FULL -> {
|
ConstraintSystemCompletionMode.FULL -> {
|
||||||
|
|||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// KJS_WITH_FULL_RUNTIME
|
||||||
|
|
||||||
|
val test1: Map<String, String> by lazy(LazyThreadSafetyMode.NONE) {
|
||||||
|
mapOf("string" to "string").mapValues { it.toString() }
|
||||||
|
}
|
||||||
|
|
||||||
|
val test2: String by myDelegate("OK")
|
||||||
|
|
||||||
|
fun <T> myDelegate(initializer: T): Delegate<T> = Delegate(initializer)
|
||||||
|
|
||||||
|
class Delegate<T>(val initializer: T) {
|
||||||
|
operator fun getValue(thisRef: Any?, property: kotlin.reflect.KProperty<*>): T {
|
||||||
|
return initializer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun <T : Any> T.provideDelegate(receiver: Any?, property: kotlin.reflect.KProperty<*>): T = this
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
test1
|
||||||
|
return test2
|
||||||
|
}
|
||||||
Vendored
+1
-1
@@ -9,6 +9,6 @@ object CommonCase {
|
|||||||
operator fun <D, E, R> Fas<D, E, R>.provideDelegate(host: D, p: Any?): Fas<D, E, R> = TODO()
|
operator fun <D, E, R> Fas<D, E, R>.provideDelegate(host: D, p: Any?): Fas<D, E, R> = TODO()
|
||||||
operator fun <D, E, R> Fas<D, E, R>.getValue(receiver: E, p: Any?): R = TODO()
|
operator fun <D, E, R> Fas<D, E, R>.getValue(receiver: E, p: Any?): R = TODO()
|
||||||
|
|
||||||
val Long.test1: String by <!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>delegate<!>() // common test, not working because of Inference1
|
val Long.test1: String by <!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>delegate<!>() // common test, not working because of Inference1
|
||||||
val Long.test2: String by delegate<CommonCase, Long, String>() // should work
|
val Long.test2: String by delegate<CommonCase, Long, String>() // should work
|
||||||
}
|
}
|
||||||
+5
@@ -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);
|
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")
|
@TestMetadata("differentReceivers.kt")
|
||||||
public void testDifferentReceivers() throws Exception {
|
public void testDifferentReceivers() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");
|
||||||
|
|||||||
+10
-5
@@ -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);
|
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")
|
@TestMetadata("differentReceivers.kt")
|
||||||
public void testDifferentReceivers() throws Exception {
|
public void testDifferentReceivers() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");
|
||||||
@@ -24850,15 +24855,15 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
public static class MethodsFromAny extends AbstractLightAnalysisModeTest {
|
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 {
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
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 {
|
public void testAllFilesPresentInMethodsFromAny() throws Exception {
|
||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/methodsFromAny"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/methodsFromAny"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -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);
|
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")
|
@TestMetadata("differentReceivers.kt")
|
||||||
public void testDifferentReceivers() throws Exception {
|
public void testDifferentReceivers() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");
|
||||||
|
|||||||
Generated
+5
@@ -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);
|
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")
|
@TestMetadata("differentReceivers.kt")
|
||||||
public void testDifferentReceivers() throws Exception {
|
public void testDifferentReceivers() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");
|
||||||
|
|||||||
+5
@@ -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);
|
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")
|
@TestMetadata("differentReceivers.kt")
|
||||||
public void testDifferentReceivers() throws Exception {
|
public void testDifferentReceivers() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/differentReceivers.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user