[NI] Resolve receiver of provideDelegate independently
#KT-38259 Fixed
This commit is contained in:
+5
@@ -6131,6 +6131,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
|||||||
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/provideDelegateOperatorDeclaration.kt");
|
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/provideDelegateOperatorDeclaration.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("provideDelegateResolutionWithStubTypes.kt")
|
||||||
|
public void testProvideDelegateResolutionWithStubTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/provideDelegateResolutionWithStubTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("setValue.kt")
|
@TestMetadata("setValue.kt")
|
||||||
public void testSetValue() throws Exception {
|
public void testSetValue() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/setValue.kt");
|
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/setValue.kt");
|
||||||
|
|||||||
Generated
+5
@@ -9527,6 +9527,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/generic.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/generic.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("genericDelegateWithNoAdditionalInfo.kt")
|
||||||
|
public void testGenericDelegateWithNoAdditionalInfo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/genericDelegateWithNoAdditionalInfo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("hostCheck.kt")
|
@TestMetadata("hostCheck.kt")
|
||||||
public void testHostCheck() throws Exception {
|
public void testHostCheck() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/hostCheck.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/hostCheck.kt");
|
||||||
|
|||||||
+4
-23
@@ -90,17 +90,9 @@ class DelegatedPropertyInferenceSession(
|
|||||||
override fun shouldCompleteResolvedSubAtomsOf(resolvedCallAtom: ResolvedCallAtom) = true
|
override fun shouldCompleteResolvedSubAtomsOf(resolvedCallAtom: ResolvedCallAtom) = true
|
||||||
}
|
}
|
||||||
|
|
||||||
object InferenceSessionForExistingCandidates : InferenceSession {
|
class InferenceSessionForExistingCandidates(private val resolveReceiverIndependently: Boolean) : InferenceSession {
|
||||||
override fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean {
|
override fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean {
|
||||||
if (ErrorUtils.isError(candidate.resolvedCall.candidateDescriptor)) return false
|
return !ErrorUtils.isError(candidate.resolvedCall.candidateDescriptor)
|
||||||
|
|
||||||
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) {}
|
||||||
@@ -122,18 +114,7 @@ object InferenceSessionForExistingCandidates : InferenceSession {
|
|||||||
|
|
||||||
override fun computeCompletionMode(
|
override fun computeCompletionMode(
|
||||||
candidate: KotlinResolutionCandidate
|
candidate: KotlinResolutionCandidate
|
||||||
): KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode? {
|
): KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode? = null
|
||||||
// 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
|
override fun resolveReceiverIndependently(): Boolean = resolveReceiverIndependently
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
|
|||||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.components.EmptySubstitutor
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
|
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.FROM_COMPLETER
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.FROM_COMPLETER
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor
|
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.toHandle
|
import org.jetbrains.kotlin.resolve.calls.inference.toHandle
|
||||||
@@ -45,6 +47,7 @@ import org.jetbrains.kotlin.types.*
|
|||||||
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
|
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
|
||||||
import org.jetbrains.kotlin.types.TypeUtils.noExpectedType
|
import org.jetbrains.kotlin.types.TypeUtils.noExpectedType
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.createFakeExpressionOfType
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.createFakeExpressionOfType
|
||||||
@@ -549,20 +552,35 @@ class DelegatedPropertyResolver(
|
|||||||
delegateType = delegateTypeConstructor.getApproximatedType()
|
delegateType = delegateTypeConstructor.getApproximatedType()
|
||||||
|
|
||||||
if (languageVersionSettings.supportsFeature(LanguageFeature.OperatorProvideDelegate)) {
|
if (languageVersionSettings.supportsFeature(LanguageFeature.OperatorProvideDelegate)) {
|
||||||
|
val traceForProvideDelegate = TemporaryBindingTrace.create(traceToResolveDelegatedProperty, "Trace to resolve provide delegate")
|
||||||
|
|
||||||
|
val substitutionMap: Map<UnwrappedType, UnwrappedType>? = buildSubstitutionMapOfNonFixedVariables(delegateType)
|
||||||
|
val nonFixedVariablesToStubTypesSubstitutor =
|
||||||
|
if (substitutionMap != null)
|
||||||
|
NewTypeSubstitutorByConstructorMap(substitutionMap.mapKeys { it.key.constructor })
|
||||||
|
else
|
||||||
|
EmptySubstitutor
|
||||||
|
|
||||||
|
val delegateTypeWithoutNonFixedVariables = nonFixedVariablesToStubTypesSubstitutor.safeSubstitute(delegateType.unwrap())
|
||||||
|
|
||||||
val contextForProvideDelegate = createContextForProvideDelegateMethod(
|
val contextForProvideDelegate = createContextForProvideDelegateMethod(
|
||||||
scopeForDelegate, delegateDataFlow, traceToResolveDelegatedProperty, InferenceSessionForExistingCandidates
|
scopeForDelegate, delegateDataFlow, traceForProvideDelegate, InferenceSessionForExistingCandidates(substitutionMap != null)
|
||||||
)
|
)
|
||||||
|
|
||||||
val provideDelegateResults = getProvideDelegateMethod(
|
val provideDelegateResults = getProvideDelegateMethod(
|
||||||
variableDescriptor, delegateExpression, delegateType, contextForProvideDelegate
|
variableDescriptor, delegateExpression, delegateTypeWithoutNonFixedVariables, contextForProvideDelegate
|
||||||
)
|
)
|
||||||
|
|
||||||
if (conventionMethodFound(provideDelegateResults)) {
|
if (conventionMethodFound(provideDelegateResults)) {
|
||||||
val provideDelegateDescriptor = provideDelegateResults.resultingDescriptor
|
val provideDelegateDescriptor = provideDelegateResults.resultingDescriptor
|
||||||
if (provideDelegateDescriptor.isOperator) {
|
if (provideDelegateDescriptor.isOperator) {
|
||||||
delegateType = provideDelegateDescriptor.returnType ?: return null
|
delegateType = inverseSubstitution(provideDelegateDescriptor.returnType, substitutionMap) ?: return null
|
||||||
delegateDataFlow = provideDelegateResults.resultingCall.dataFlowInfoForArguments.resultInfo
|
delegateDataFlow = provideDelegateResults.resultingCall.dataFlowInfoForArguments.resultInfo
|
||||||
}
|
}
|
||||||
trace.record(PROVIDE_DELEGATE_RESOLVED_CALL, variableDescriptor, provideDelegateResults.resultingCall)
|
if (substitutionMap == null) {
|
||||||
|
traceForProvideDelegate.record(PROVIDE_DELEGATE_RESOLVED_CALL, variableDescriptor, provideDelegateResults.resultingCall)
|
||||||
|
traceForProvideDelegate.commit() // otherwise we have to reanalyze provideDelegate with good delegate type
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return inferDelegateTypeFromGetSetValueMethods(
|
return inferDelegateTypeFromGetSetValueMethods(
|
||||||
@@ -570,6 +588,38 @@ class DelegatedPropertyResolver(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun inverseSubstitution(type: KotlinType?, substitutionMap: Map<UnwrappedType, UnwrappedType>?): UnwrappedType? {
|
||||||
|
if (type == null) return null
|
||||||
|
if (substitutionMap == null) return type.unwrap()
|
||||||
|
|
||||||
|
val invertedMap = hashMapOf<TypeConstructor, UnwrappedType>()
|
||||||
|
for ((variable, stubType) in substitutionMap) {
|
||||||
|
invertedMap[stubType.constructor] = variable
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewTypeSubstitutorByConstructorMap(invertedMap).safeSubstitute(type.unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildSubstitutionMapOfNonFixedVariables(type: KotlinType): Map<UnwrappedType, UnwrappedType>? {
|
||||||
|
// This is an exception for delegated properties that return just type variable
|
||||||
|
if (type.constructor is NewTypeVariableConstructor) return null
|
||||||
|
|
||||||
|
var substitutionMap: MutableMap<UnwrappedType, UnwrappedType>? = null
|
||||||
|
type.contains { innerType ->
|
||||||
|
val constructor = innerType.constructor
|
||||||
|
if (constructor is NewTypeVariableConstructor) {
|
||||||
|
if (substitutionMap == null) substitutionMap = hashMapOf()
|
||||||
|
if (innerType !in substitutionMap!!) {
|
||||||
|
substitutionMap!![innerType] = StubTypeForProvideDelegateReceiver(constructor, innerType.isMarkedNullable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
return substitutionMap
|
||||||
|
}
|
||||||
|
|
||||||
private fun inferDelegateTypeFromGetSetValueMethods(
|
private fun inferDelegateTypeFromGetSetValueMethods(
|
||||||
delegateExpression: KtExpression,
|
delegateExpression: KtExpression,
|
||||||
variableDescriptor: VariableDescriptorWithAccessors,
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
|
|||||||
+2
@@ -159,6 +159,8 @@ abstract class ManyCandidatesResolver<D : CallableDescriptor>(
|
|||||||
|
|
||||||
override fun computeCompletionMode(candidate: KotlinResolutionCandidate) = null
|
override fun computeCompletionMode(candidate: KotlinResolutionCandidate) = null
|
||||||
|
|
||||||
|
override fun resolveReceiverIndependently(): Boolean = false
|
||||||
|
|
||||||
private fun PartialCallInfo.asCallResolutionResult(
|
private fun PartialCallInfo.asCallResolutionResult(
|
||||||
diagnosticsHolder: KotlinDiagnosticsHolder.SimpleHolder,
|
diagnosticsHolder: KotlinDiagnosticsHolder.SimpleHolder,
|
||||||
commonSystem: NewConstraintSystem
|
commonSystem: NewConstraintSystem
|
||||||
|
|||||||
+3
@@ -31,6 +31,8 @@ interface InferenceSession {
|
|||||||
override fun computeCompletionMode(
|
override fun computeCompletionMode(
|
||||||
candidate: KotlinResolutionCandidate
|
candidate: KotlinResolutionCandidate
|
||||||
): KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode? = null
|
): KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode? = null
|
||||||
|
|
||||||
|
override fun resolveReceiverIndependently(): Boolean = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +51,7 @@ interface InferenceSession {
|
|||||||
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?
|
fun computeCompletionMode(candidate: KotlinResolutionCandidate): KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode?
|
||||||
|
fun resolveReceiverIndependently(): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PartialCallInfo {
|
interface PartialCallInfo {
|
||||||
|
|||||||
+2
-1
@@ -36,9 +36,10 @@ fun resolveKtPrimitive(
|
|||||||
diagnosticsHolder: KotlinDiagnosticsHolder,
|
diagnosticsHolder: KotlinDiagnosticsHolder,
|
||||||
receiverInfo: ReceiverInfo,
|
receiverInfo: ReceiverInfo,
|
||||||
convertedType: UnwrappedType?,
|
convertedType: UnwrappedType?,
|
||||||
|
inferenceSession: InferenceSession?
|
||||||
): ResolvedAtom = when (argument) {
|
): ResolvedAtom = when (argument) {
|
||||||
is SimpleKotlinCallArgument ->
|
is SimpleKotlinCallArgument ->
|
||||||
checkSimpleArgument(csBuilder, argument, expectedType, diagnosticsHolder, receiverInfo, convertedType)
|
checkSimpleArgument(csBuilder, argument, expectedType, diagnosticsHolder, receiverInfo, convertedType, inferenceSession)
|
||||||
|
|
||||||
is LambdaKotlinCallArgument ->
|
is LambdaKotlinCallArgument ->
|
||||||
preprocessLambdaArgument(csBuilder, argument, expectedType, diagnosticsHolder)
|
preprocessLambdaArgument(csBuilder, argument, expectedType, diagnosticsHolder)
|
||||||
|
|||||||
+3
-1
@@ -149,7 +149,9 @@ class PostponedArgumentsAnalyzer(
|
|||||||
|
|
||||||
val subResolvedKtPrimitives = allReturnArguments.map {
|
val subResolvedKtPrimitives = allReturnArguments.map {
|
||||||
resolveKtPrimitive(
|
resolveKtPrimitive(
|
||||||
c.getBuilder(), it, lambda.returnType.let(::substitute), diagnosticHolder, ReceiverInfo.notReceiver, convertedType = null
|
c.getBuilder(), it, lambda.returnType.let(::substitute),
|
||||||
|
diagnosticHolder, ReceiverInfo.notReceiver, convertedType = null,
|
||||||
|
inferenceSession
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -439,6 +439,7 @@ private fun KotlinResolutionCandidate.resolveKotlinArgument(
|
|||||||
} else null
|
} else null
|
||||||
|
|
||||||
|
|
||||||
|
val inferenceSession = resolutionCallbacks.inferenceSession
|
||||||
if (candidateExpectedType == null || // Nothing to convert
|
if (candidateExpectedType == null || // Nothing to convert
|
||||||
convertedExpectedType != null || // Type is already converted
|
convertedExpectedType != null || // Type is already converted
|
||||||
isReceiver || // Receivers don't participate in conversions
|
isReceiver || // Receivers don't participate in conversions
|
||||||
@@ -452,7 +453,8 @@ private fun KotlinResolutionCandidate.resolveKotlinArgument(
|
|||||||
expectedType,
|
expectedType,
|
||||||
this,
|
this,
|
||||||
receiverInfo,
|
receiverInfo,
|
||||||
convertedArgument?.unknownIntegerType?.unwrap()
|
convertedArgument?.unknownIntegerType?.unwrap(),
|
||||||
|
inferenceSession
|
||||||
)
|
)
|
||||||
|
|
||||||
addResolvedKtPrimitive(resolvedAtom)
|
addResolvedKtPrimitive(resolvedAtom)
|
||||||
@@ -465,7 +467,8 @@ private fun KotlinResolutionCandidate.resolveKotlinArgument(
|
|||||||
expectedType,
|
expectedType,
|
||||||
this@resolveKotlinArgument,
|
this@resolveKotlinArgument,
|
||||||
receiverInfo,
|
receiverInfo,
|
||||||
convertedArgument?.unknownIntegerType?.unwrap()
|
convertedArgument?.unknownIntegerType?.unwrap(),
|
||||||
|
inferenceSession
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!hasContradiction) {
|
if (!hasContradiction) {
|
||||||
@@ -496,7 +499,8 @@ private fun KotlinResolutionCandidate.resolveKotlinArgument(
|
|||||||
convertedTypeAfterSubtyping,
|
convertedTypeAfterSubtyping,
|
||||||
this@resolveKotlinArgument,
|
this@resolveKotlinArgument,
|
||||||
receiverInfo,
|
receiverInfo,
|
||||||
convertedArgument?.unknownIntegerType?.unwrap()
|
convertedArgument?.unknownIntegerType?.unwrap(),
|
||||||
|
inferenceSession
|
||||||
)
|
)
|
||||||
addResolvedKtPrimitive(resolvedAtom)
|
addResolvedKtPrimitive(resolvedAtom)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-3
@@ -51,10 +51,11 @@ fun checkSimpleArgument(
|
|||||||
expectedType: UnwrappedType?,
|
expectedType: UnwrappedType?,
|
||||||
diagnosticsHolder: KotlinDiagnosticsHolder,
|
diagnosticsHolder: KotlinDiagnosticsHolder,
|
||||||
receiverInfo: ReceiverInfo,
|
receiverInfo: ReceiverInfo,
|
||||||
convertedType: UnwrappedType?
|
convertedType: UnwrappedType?,
|
||||||
|
inferenceSession: InferenceSession?
|
||||||
): ResolvedAtom = when (argument) {
|
): ResolvedAtom = when (argument) {
|
||||||
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, argument, expectedType, diagnosticsHolder, receiverInfo.isReceiver, convertedType)
|
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, argument, expectedType, diagnosticsHolder, receiverInfo.isReceiver, convertedType)
|
||||||
is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, argument, expectedType, diagnosticsHolder, receiverInfo)
|
is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, argument, expectedType, diagnosticsHolder, receiverInfo, inferenceSession)
|
||||||
else -> unexpectedArgument(argument)
|
else -> unexpectedArgument(argument)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,8 +179,11 @@ private fun checkSubCallArgument(
|
|||||||
expectedType: UnwrappedType?,
|
expectedType: UnwrappedType?,
|
||||||
diagnosticsHolder: KotlinDiagnosticsHolder,
|
diagnosticsHolder: KotlinDiagnosticsHolder,
|
||||||
receiverInfo: ReceiverInfo,
|
receiverInfo: ReceiverInfo,
|
||||||
|
inferenceSession: InferenceSession?
|
||||||
): ResolvedAtom {
|
): ResolvedAtom {
|
||||||
val subCallResult = ResolvedSubCallArgument(subCallArgument)
|
val subCallResult = ResolvedSubCallArgument(
|
||||||
|
subCallArgument, receiverInfo.isReceiver && inferenceSession?.resolveReceiverIndependently() == true
|
||||||
|
)
|
||||||
|
|
||||||
if (expectedType == null) return subCallResult
|
if (expectedType == null) return subCallResult
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -65,8 +65,10 @@ class SimpleCandidateFactory(
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
val baseSystem = NewConstraintSystemImpl(callComponents.constraintInjector, callComponents.builtIns)
|
val baseSystem = NewConstraintSystemImpl(callComponents.constraintInjector, callComponents.builtIns)
|
||||||
baseSystem.addSubsystemFromArgument(kotlinCall.explicitReceiver)
|
if (!inferenceSession.resolveReceiverIndependently()) {
|
||||||
baseSystem.addSubsystemFromArgument(kotlinCall.dispatchReceiverForInvokeExtension)
|
baseSystem.addSubsystemFromArgument(kotlinCall.explicitReceiver)
|
||||||
|
baseSystem.addSubsystemFromArgument(kotlinCall.dispatchReceiverForInvokeExtension)
|
||||||
|
}
|
||||||
for (argument in kotlinCall.argumentsInParenthesis) {
|
for (argument in kotlinCall.argumentsInParenthesis) {
|
||||||
baseSystem.addSubsystemFromArgument(argument)
|
baseSystem.addSubsystemFromArgument(argument)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,9 +83,12 @@ class ResolvedExpressionAtom(override val atom: ExpressionKotlinCallArgument) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResolvedSubCallArgument(override val atom: SubKotlinCallArgument) : ResolvedAtom() {
|
class ResolvedSubCallArgument(override val atom: SubKotlinCallArgument, resolveIndependently: Boolean) : ResolvedAtom() {
|
||||||
init {
|
init {
|
||||||
setAnalyzedResults(listOf(atom.callResult))
|
if (resolveIndependently)
|
||||||
|
setAnalyzedResults(listOf())
|
||||||
|
else
|
||||||
|
setAnalyzedResults(listOf(atom.callResult))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
interface DelegateProvider<out T> {
|
||||||
|
operator fun provideDelegate(receiver: Any?, prop: kotlin.reflect.KProperty<*>): Lazy<T>
|
||||||
|
}
|
||||||
|
fun <Value : Any> delegate(): DelegateProvider<Value> = object : DelegateProvider<Value> {
|
||||||
|
override fun provideDelegate(receiver: Any?, prop: KProperty<*>): Lazy<Value> {
|
||||||
|
return lazy { "OK" } as Lazy<Value>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val value: String by delegate()
|
||||||
|
return value
|
||||||
|
}
|
||||||
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 <!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>delegate<!>() // common test, not working because of Inference1
|
val Long.test1: String by <!NI;DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE!><!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
|
||||||
}
|
}
|
||||||
Vendored
+1
-1
@@ -9,6 +9,6 @@ object Inference2 {
|
|||||||
operator fun <T> Foo<T>.provideDelegate(host: T, p: Any?): Foo<T> = TODO()
|
operator fun <T> Foo<T>.provideDelegate(host: T, p: Any?): Foo<T> = TODO()
|
||||||
operator fun <T> Foo<T>.getValue(receiver: Inference2, p: Any?): String = TODO()
|
operator fun <T> Foo<T>.getValue(receiver: Inference2, p: Any?): String = TODO()
|
||||||
|
|
||||||
val test1: String by <!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>delegate<!>() // same story like in Inference1
|
val test1: String by <!NI;DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE!><!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>delegate<!>()<!> // same story like in Inference1
|
||||||
val test2: String by delegate<Inference2>()
|
val test2: String by delegate<Inference2>()
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
|
||||||
|
val test: String by materializeDelegate()
|
||||||
|
|
||||||
|
fun <T> materializeDelegate(): Delegate<T> = Delegate()
|
||||||
|
|
||||||
|
operator fun <K> K.provideDelegate(receiver: Any?, property: kotlin.reflect.KProperty<*>): K = this
|
||||||
|
|
||||||
|
class Delegate<V> {
|
||||||
|
operator fun getValue(thisRef: Any?, property: kotlin.reflect.KProperty<*>): V = TODO()
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val test: kotlin.String
|
||||||
|
public fun </*0*/ T> materializeDelegate(): Delegate<T>
|
||||||
|
public operator fun </*0*/ K> K.provideDelegate(/*0*/ receiver: kotlin.Any?, /*1*/ property: kotlin.reflect.KProperty<*>): K
|
||||||
|
|
||||||
|
public final class Delegate</*0*/ V> {
|
||||||
|
public constructor Delegate</*0*/ V>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ property: kotlin.reflect.KProperty<*>): V
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -6138,6 +6138,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
|
|||||||
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/provideDelegateOperatorDeclaration.kt");
|
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/provideDelegateOperatorDeclaration.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("provideDelegateResolutionWithStubTypes.kt")
|
||||||
|
public void testProvideDelegateResolutionWithStubTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/provideDelegateResolutionWithStubTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("setValue.kt")
|
@TestMetadata("setValue.kt")
|
||||||
public void testSetValue() throws Exception {
|
public void testSetValue() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/setValue.kt");
|
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/setValue.kt");
|
||||||
|
|||||||
Generated
+5
@@ -6133,6 +6133,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
|||||||
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/provideDelegateOperatorDeclaration.kt");
|
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/provideDelegateOperatorDeclaration.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("provideDelegateResolutionWithStubTypes.kt")
|
||||||
|
public void testProvideDelegateResolutionWithStubTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/provideDelegateResolutionWithStubTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("setValue.kt")
|
@TestMetadata("setValue.kt")
|
||||||
public void testSetValue() throws Exception {
|
public void testSetValue() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/setValue.kt");
|
runTest("compiler/testData/diagnostics/tests/delegatedProperty/provideDelegate/setValue.kt");
|
||||||
|
|||||||
+5
@@ -10742,6 +10742,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/generic.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/generic.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("genericDelegateWithNoAdditionalInfo.kt")
|
||||||
|
public void testGenericDelegateWithNoAdditionalInfo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/genericDelegateWithNoAdditionalInfo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("hostCheck.kt")
|
@TestMetadata("hostCheck.kt")
|
||||||
public void testHostCheck() throws Exception {
|
public void testHostCheck() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/hostCheck.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/hostCheck.kt");
|
||||||
|
|||||||
+5
@@ -10742,6 +10742,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/generic.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/generic.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("genericDelegateWithNoAdditionalInfo.kt")
|
||||||
|
public void testGenericDelegateWithNoAdditionalInfo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/genericDelegateWithNoAdditionalInfo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("hostCheck.kt")
|
@TestMetadata("hostCheck.kt")
|
||||||
public void testHostCheck() throws Exception {
|
public void testHostCheck() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/hostCheck.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/hostCheck.kt");
|
||||||
|
|||||||
+5
@@ -9527,6 +9527,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/generic.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/generic.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("genericDelegateWithNoAdditionalInfo.kt")
|
||||||
|
public void testGenericDelegateWithNoAdditionalInfo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/genericDelegateWithNoAdditionalInfo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("hostCheck.kt")
|
@TestMetadata("hostCheck.kt")
|
||||||
public void testHostCheck() throws Exception {
|
public void testHostCheck() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/hostCheck.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/hostCheck.kt");
|
||||||
|
|||||||
@@ -13,14 +13,34 @@ import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
|||||||
|
|
||||||
// This type is used as a stub for postponed type variables, which are important for coroutine inference
|
// This type is used as a stub for postponed type variables, which are important for coroutine inference
|
||||||
class StubType(
|
class StubType(
|
||||||
private val originalTypeVariable: TypeConstructor,
|
originalTypeVariable: TypeConstructor,
|
||||||
override val isMarkedNullable: Boolean,
|
isMarkedNullable: Boolean,
|
||||||
override val constructor: TypeConstructor =
|
constructor: TypeConstructor = ErrorUtils.createErrorTypeConstructor("Constructor for non fixed type: $originalTypeVariable"),
|
||||||
ErrorUtils.createErrorTypeConstructor("Constructor for non fixed type: $originalTypeVariable"),
|
memberScope: MemberScope = ErrorUtils.createErrorScope("Scope for non fixed type: $originalTypeVariable")
|
||||||
override val memberScope: MemberScope =
|
) : AbstractStubType(originalTypeVariable, isMarkedNullable, constructor, memberScope), StubTypeMarker {
|
||||||
ErrorUtils.createErrorScope("Scope for non fixed type: $originalTypeVariable")
|
override fun materialize(newNullability: Boolean): AbstractStubType {
|
||||||
) : SimpleType(), StubTypeMarker {
|
return StubType(originalTypeVariable, newNullability, constructor, memberScope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This type is used as a replacement of type variables for provideDelegate resolve
|
||||||
|
class StubTypeForProvideDelegateReceiver(
|
||||||
|
originalTypeVariable: TypeConstructor,
|
||||||
|
isMarkedNullable: Boolean,
|
||||||
|
constructor: TypeConstructor = ErrorUtils.createErrorTypeConstructor("Constructor for non fixed type: $originalTypeVariable"),
|
||||||
|
memberScope: MemberScope = ErrorUtils.createErrorScope("Scope for non fixed type: $originalTypeVariable")
|
||||||
|
) : AbstractStubType(originalTypeVariable, isMarkedNullable, constructor, memberScope) {
|
||||||
|
override fun materialize(newNullability: Boolean): StubTypeForProvideDelegateReceiver {
|
||||||
|
return StubTypeForProvideDelegateReceiver(originalTypeVariable, newNullability, constructor, memberScope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractStubType(
|
||||||
|
protected val originalTypeVariable: TypeConstructor,
|
||||||
|
override val isMarkedNullable: Boolean,
|
||||||
|
override val constructor: TypeConstructor,
|
||||||
|
override val memberScope: MemberScope
|
||||||
|
) : SimpleType() {
|
||||||
override val arguments: List<TypeProjection>
|
override val arguments: List<TypeProjection>
|
||||||
get() = emptyList()
|
get() = emptyList()
|
||||||
|
|
||||||
@@ -30,10 +50,7 @@ class StubType(
|
|||||||
override fun replaceAnnotations(newAnnotations: Annotations): SimpleType = this
|
override fun replaceAnnotations(newAnnotations: Annotations): SimpleType = this
|
||||||
|
|
||||||
override fun makeNullableAsSpecified(newNullability: Boolean): SimpleType {
|
override fun makeNullableAsSpecified(newNullability: Boolean): SimpleType {
|
||||||
return if (newNullability == isMarkedNullable)
|
return if (newNullability == isMarkedNullable) this else materialize(newNullability)
|
||||||
this
|
|
||||||
else
|
|
||||||
StubType(originalTypeVariable, newNullability, constructor, memberScope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
@@ -42,4 +59,6 @@ class StubType(
|
|||||||
|
|
||||||
@TypeRefinement
|
@TypeRefinement
|
||||||
override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = this
|
override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = this
|
||||||
}
|
|
||||||
|
abstract fun materialize(newNullability: Boolean): AbstractStubType
|
||||||
|
}
|
||||||
Generated
+5
@@ -8182,6 +8182,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/generic.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/generic.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("genericDelegateWithNoAdditionalInfo.kt")
|
||||||
|
public void testGenericDelegateWithNoAdditionalInfo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/genericDelegateWithNoAdditionalInfo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("hostCheck.kt")
|
@TestMetadata("hostCheck.kt")
|
||||||
public void testHostCheck() throws Exception {
|
public void testHostCheck() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/hostCheck.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/hostCheck.kt");
|
||||||
|
|||||||
+5
@@ -8182,6 +8182,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/generic.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/generic.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("genericDelegateWithNoAdditionalInfo.kt")
|
||||||
|
public void testGenericDelegateWithNoAdditionalInfo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/genericDelegateWithNoAdditionalInfo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("hostCheck.kt")
|
@TestMetadata("hostCheck.kt")
|
||||||
public void testHostCheck() throws Exception {
|
public void testHostCheck() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/hostCheck.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/provideDelegate/hostCheck.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user