[FIR] Support completion of lambdas with type variable as expected type

#KT-37310 Fixed
#KT-37304 Fixed
This commit is contained in:
Dmitriy Novozhilov
2020-03-06 14:11:31 +03:00
parent 643d7be12d
commit 1c0fd7342f
28 changed files with 281 additions and 186 deletions
@@ -49,7 +49,7 @@ fun Candidate.resolveArgumentExpression(
isDispatch: Boolean,
isSafeCall: Boolean
) {
return when (argument) {
when (argument) {
is FirFunctionCall, is FirWhenExpression, is FirTryExpression, is FirCheckNotNullCall -> resolveSubCallArgument(
csBuilder,
argument as FirResolvable,
@@ -41,7 +41,7 @@ class FirCallCompleter(
private val transformer: FirBodyResolveTransformer,
components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents
) : BodyResolveComponents by components {
val completer = ConstraintSystemCompleter(components.inferenceComponents)
val completer = ConstraintSystemCompleter(components)
private val inferenceSession
get() = inferenceComponents.inferenceSession
@@ -6,17 +6,18 @@
package org.jetbrains.kotlin.fir.resolve.inference
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.returnExpressions
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.TypeVariableDirectionCalculator
import org.jetbrains.kotlin.resolve.calls.inference.components.VariableFixationFinder
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
@@ -94,8 +95,8 @@ private fun Candidate.hasProperNonTrivialLowerConstraints(components: InferenceC
}
class ConstraintSystemCompleter(val components: InferenceComponents) {
private val variableFixationFinder = VariableFixationFinder(components.trivialConstraintTypeInferenceOracle)
class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
private val variableFixationFinder = VariableFixationFinder(components.inferenceComponents.trivialConstraintTypeInferenceOracle)
fun complete(
c: KotlinConstraintSystemCompleter.Context,
@@ -109,16 +110,18 @@ class ConstraintSystemCompleter(val components: InferenceComponents) {
if (analyzePostponeArgumentIfPossible(c, topLevelAtoms, analyze)) continue
val allTypeVariables = getOrderedAllTypeVariables(c, topLevelAtoms)
val postponedKtPrimitives = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
val postponedAtoms = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
val variableForFixation =
variableFixationFinder.findFirstVariableForFixation(
c, allTypeVariables, postponedKtPrimitives, completionMode, candidateReturnType
c, allTypeVariables, postponedAtoms, completionMode, candidateReturnType
) ?: break
// if (shouldForceCallableReferenceOrLambdaResolution(completionMode, variableForFixation)) {
// if (forcePostponedAtomResolution<ResolvedCallableReferenceAtom>(topLevelAtoms, analyze)) continue
// if (forcePostponedAtomResolution<LambdaWithTypeVariableAsExpectedTypeAtom>(topLevelAtoms, analyze)) continue
// }
if (
completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL &&
resolveLambdaOrCallableReferenceWithTypeVariableAsExpectedType(c, variableForFixation, postponedAtoms, analyze)
) {
continue
}
if (variableForFixation.hasProperConstraint || completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL) {
val variableWithConstraints = c.notFixedTypeVariables.getValue(variableForFixation.variable)
@@ -144,6 +147,89 @@ class ConstraintSystemCompleter(val components: InferenceComponents) {
}
}
private fun resolveLambdaOrCallableReferenceWithTypeVariableAsExpectedType(
c: KotlinConstraintSystemCompleter.Context,
variableForFixation: VariableFixationFinder.VariableForFixation,
postponedAtoms: List<PostponedResolvedAtom>,
/*diagnosticsHolder: KotlinDiagnosticsHolder,*/
analyze: (PostponedResolvedAtom) -> Unit
): Boolean {
val variable = variableForFixation.variable as ConeTypeVariableTypeConstructor
val hasProperAtom = postponedAtoms.any {
when (it) {
is LambdaWithTypeVariableAsExpectedTypeAtom/*, is PostponedCallableReferenceAtom*/
-> it.expectedType.typeConstructor(c) == variable // TODO
else -> false
}
}
if (
!hasProperAtom &&
variableForFixation.hasProperConstraint &&
!variableForFixation.hasOnlyTrivialProperConstraint
) return false
val postponedAtom = postponedAtoms.firstOrNull() ?: return false
val csBuilder = (c as NewConstraintSystemImpl).getBuilder()
val expectedTypeVariableConstructor = postponedAtom.expectedType?.typeConstructor(c)?.takeIf { it in c.allTypeVariables } as? ConeTypeVariableTypeConstructor ?: variable
val expectedTypeVariable = csBuilder.currentStorage().allTypeVariables[expectedTypeVariableConstructor] as ConeTypeVariable? ?: return false
val atomToAnalyze = when (postponedAtom) {
is LambdaWithTypeVariableAsExpectedTypeAtom -> {
postponedAtom.preparePostponedAtomWithTypeVariableAsExpectedType(
c, csBuilder, expectedTypeVariable,
parameterTypes = null,
isSuitable = { isBuiltinFunctionalType(components.session) },
typeVariableCreator = { ConeTypeVariableForLambdaReturnType(postponedAtom.atom, "_R") },
newAtomCreator = { returnTypeVariable, expectedType ->
postponedAtom.transformToResolvedLambda(csBuilder, expectedType, returnTypeVariable)
}
)
}
// is PostponedCallableReferenceAtom -> TODO()
else -> return false
}
analyze(atomToAnalyze)
return true
}
private inline fun <T : PostponedResolvedAtom, V : ConeTypeVariable> T.preparePostponedAtomWithTypeVariableAsExpectedType(
c: KotlinConstraintSystemCompleter.Context,
csBuilder: ConstraintSystemBuilder,
variable: ConeTypeVariable,
parameterTypes: Array<out ConeKotlinType?>?,
isSuitable: ConeKotlinType.() -> Boolean,
typeVariableCreator: () -> V,
newAtomCreator: (V, ConeKotlinType) -> PostponedResolvedAtom
): PostponedResolvedAtom {
val functionalType = (components.inferenceComponents.resultTypeResolver.findResultType(
c,
c.notFixedTypeVariables.getValue(variable.typeConstructor),
TypeVariableDirectionCalculator.ResolveDirection.TO_SUPERTYPE
) as ConeKotlinType).lowerBoundIfFlexible() as ConeClassLikeType
val isExtensionWithoutParameters = false
// TODO
// functionalType.isExtensionFunctionType && functionalType.arguments.size == 2 && parameterTypes?.isEmpty() == true
if (parameterTypes?.all { type -> type != null } == true && !isExtensionWithoutParameters) return this
if (!functionalType.isSuitable()) return this
val returnVariable = typeVariableCreator()
csBuilder.registerVariable(returnVariable)
val expectedType = ConeClassLikeTypeImpl(
lookupTag = functionalType.lookupTag,
typeArguments = (functionalType.typeArguments.dropLast(1) + returnVariable.defaultType).toTypedArray(),
isNullable = functionalType.isNullable
)
csBuilder.addSubtypeConstraint(
expectedType,
variable.defaultType,
SimpleConstraintSystemConstraintPosition
// ArgumentConstraintPosition(atom as KotlinCallArgument)
)
return newAtomCreator(returnVariable, expectedType)
}
private fun getOrderedAllTypeVariables(
c: KotlinConstraintSystemCompleter.Context,
topLevelAtoms: List<FirStatement>
@@ -158,6 +244,11 @@ class ConstraintSystemCompleter(val components: InferenceComponents) {
typeVariable.toTypeConstructor()
}
for (postponedAtom in candidate.postponedAtoms) {
when (postponedAtom) {
is ResolvedLambdaAtom -> postponedAtom.typeVariableForLambdaReturnType
}
}
for (lambdaAtom in candidate.postponedAtoms.filterIsInstance<ResolvedLambdaAtom>()) {
result.addIfNotNull(lambdaAtom.typeVariableForLambdaReturnType.toTypeConstructor())
}
@@ -191,7 +282,7 @@ class ConstraintSystemCompleter(val components: InferenceComponents) {
variableWithConstraints: VariableWithConstraints,
direction: TypeVariableDirectionCalculator.ResolveDirection
) {
val resultType = components.resultTypeResolver.findResultType(c, variableWithConstraints, direction)
val resultType = components.inferenceComponents.resultTypeResolver.findResultType(c, variableWithConstraints, direction)
c.fixVariable(variableWithConstraints.typeVariable, resultType, atom = null) // TODO: obtain atom for diagnostics
}
@@ -30,15 +30,16 @@ fun Candidate.preprocessLambdaArgument(
argument: FirAnonymousFunction,
expectedType: ConeKotlinType?,
expectedTypeRef: FirTypeRef,
forceResolution: Boolean = false
) {
forceResolution: Boolean = false,
returnTypeVariable: ConeTypeVariableForLambdaReturnType? = null
): PostponedResolvedAtom {
if (expectedType != null && !forceResolution && csBuilder.isTypeVariable(expectedType)) {
//return LambdaWithTypeVariableAsExpectedTypeAtom(argument, expectedType)
return LambdaWithTypeVariableAsExpectedTypeAtom(argument, expectedType, expectedTypeRef, this)
}
val resolvedArgument =
extractLambdaInfoFromFunctionalType(expectedType, expectedTypeRef, argument, bodyResolveComponents.session, bodyResolveComponents)
?: extraLambdaInfo(expectedType, argument, csBuilder, bodyResolveComponents.session, bodyResolveComponents)
extractLambdaInfoFromFunctionalType(expectedType, expectedTypeRef, argument, returnTypeVariable, bodyResolveComponents, this)
?: extraLambdaInfo(expectedType, argument, csBuilder, bodyResolveComponents.session, this)
if (expectedType != null) {
// TODO: add SAM conversion processing
@@ -46,7 +47,7 @@ fun Candidate.preprocessLambdaArgument(
csBuilder.addSubtypeConstraint(lambdaType, expectedType, SimpleConstraintSystemConstraintPosition)
}
postponedAtoms += resolvedArgument
return resolvedArgument
}
fun Candidate.preprocessCallableReference(
@@ -103,7 +104,7 @@ private fun extraLambdaInfo(
argument: FirAnonymousFunction,
csBuilder: ConstraintSystemBuilder,
session: FirSession,
components: BodyResolveComponents
candidate: Candidate?
): ResolvedLambdaAtom {
val isSuspend = expectedType?.isSuspendFunctionType(session) ?: false
@@ -111,7 +112,7 @@ private fun extraLambdaInfo(
expectedType != null && expectedType.lowerBoundIfFlexible()
.isBuiltinFunctionalType(session)//isNotNullOrNullableFunctionSupertype(expectedType)
val typeVariable = TypeVariableForLambdaReturnType(argument, "_L")
val typeVariable = ConeTypeVariableForLambdaReturnType(argument, "_L")
val receiverType = argument.receiverType
val returnType =
@@ -129,11 +130,13 @@ private fun extraLambdaInfo(
return ResolvedLambdaAtom(
argument,
expectedType,
isSuspend,
receiverType,
parameters,
returnType,
typeVariable.takeIf { newTypeVariableUsed }
typeVariable.takeIf { newTypeVariableUsed },
candidate
)
}
@@ -141,12 +144,14 @@ internal fun extractLambdaInfoFromFunctionalType(
expectedType: ConeKotlinType?,
expectedTypeRef: FirTypeRef,
argument: FirAnonymousFunction,
session: FirSession,
components: BodyResolveComponents
returnTypeVariable: ConeTypeVariableForLambdaReturnType?,
components: BodyResolveComponents,
candidate: Candidate?
): ResolvedLambdaAtom? {
val session = components.session
if (expectedType == null) return null
if (expectedType is ConeFlexibleType) {
return extractLambdaInfoFromFunctionalType(expectedType.lowerBound, expectedTypeRef, argument, session, components)
return extractLambdaInfoFromFunctionalType(expectedType.lowerBound, expectedTypeRef, argument, returnTypeVariable, components, candidate)
}
if (!expectedType.isBuiltinFunctionalType(session)) return null
@@ -156,11 +161,13 @@ internal fun extractLambdaInfoFromFunctionalType(
return ResolvedLambdaAtom(
argument,
expectedType,
expectedType.isSuspendFunctionType(session),
receiverType,
parameters,
returnType,
typeVariableForLambdaReturnType = null
typeVariableForLambdaReturnType = returnTypeVariable,
candidate
)
}
@@ -196,31 +203,54 @@ private fun ConeKotlinType.extractParametersForFunctionalType(
}
}
class TypeVariableForLambdaReturnType(val argument: FirAnonymousFunction, name: String) : ConeTypeVariable(name)
class ConeTypeVariableForLambdaReturnType(val argument: FirAnonymousFunction, name: String) : ConeTypeVariable(name)
sealed class PostponedResolvedAtom : PostponedResolvedAtomMarker {
abstract override val inputTypes: Collection<ConeKotlinType>
abstract override val outputType: ConeKotlinType?
override var analyzed: Boolean = false
abstract val expectedType: ConeKotlinType?
}
class ResolvedLambdaAtom(
val atom: FirAnonymousFunction,
override val expectedType: ConeKotlinType?,
val isSuspend: Boolean,
val receiver: ConeKotlinType?,
val parameters: List<ConeKotlinType>,
val returnType: ConeKotlinType,
val typeVariableForLambdaReturnType: TypeVariableForLambdaReturnType?
val typeVariableForLambdaReturnType: ConeTypeVariableForLambdaReturnType?,
val candidateForOuterCall: Candidate?
) : PostponedResolvedAtom() {
init {
candidateForOuterCall?.let {
it.postponedAtoms += this
}
}
lateinit var returnStatements: Collection<FirStatement>
override val inputTypes: Collection<ConeKotlinType> get() = receiver?.let { parameters + it } ?: parameters
override val outputType: ConeKotlinType get() = returnType
}
class LambdaWithTypeVariableAsExpectedTypeAtom(
val atom: FirAnonymousFunction,
override val expectedType: ConeKotlinType,
val expectedTypeRef: FirTypeRef,
val candidateForOuterCall: Candidate
) : PostponedResolvedAtom() {
init {
candidateForOuterCall.postponedAtoms += this
}
override val inputTypes: Collection<ConeKotlinType> get() = listOf(expectedType)
override val outputType: ConeKotlinType? get() = null
}
class ResolvedCallableReferenceAtom(
val reference: FirCallableReferenceAccess,
val expectedType: ConeKotlinType?,
override val expectedType: ConeKotlinType?,
val lhs: DoubleColonLHS?,
private val session: FirSession
) : PostponedResolvedAtom() {
@@ -11,14 +11,15 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.diagnostics.FirUnresolvedReferenceError
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.StoreNameReference
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.model.CoroutinePosition
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
import org.jetbrains.kotlin.types.model.StubTypeMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
import org.jetbrains.kotlin.types.model.freshTypeConstructor
@@ -53,17 +54,15 @@ class PostponedArgumentsAnalyzer(
candidate: Candidate
//diagnosticsHolder: KotlinDiagnosticsHolder
) {
when (argument) {
return when (argument) {
is ResolvedLambdaAtom ->
analyzeLambda(c, argument, candidate/*, diagnosticsHolder*/)
// is LambdaWithTypeVariableAsExpectedTypeAtom ->
// analyzeLambda(
// c, resolutionCallbacks, argument.transformToResolvedLambda(c.getBuilder()), diagnosticsHolder
// )
is LambdaWithTypeVariableAsExpectedTypeAtom ->
analyzeLambda(c, argument.transformToResolvedLambda(c.getBuilder()), candidate/*, diagnosticsHolder*/)
is ResolvedCallableReferenceAtom -> processCallableReference(argument, candidate)
//
// is ResolvedCollectionLiteralAtom -> TODO("Not supported")
}
}
@@ -184,4 +183,22 @@ class PostponedArgumentsAnalyzer(
}
}
fun LambdaWithTypeVariableAsExpectedTypeAtom.transformToResolvedLambda(
csBuilder: ConstraintSystemBuilder,
/*diagnosticHolder: KotlinDiagnosticsHolder,*/
expectedType: ConeKotlinType? = null,
returnTypeVariable: ConeTypeVariableForLambdaReturnType? = null
): ResolvedLambdaAtom {
val fixedExpectedType = (csBuilder.buildCurrentSubstitutor() as ConeSubstitutor)
.substituteOrSelf(expectedType ?: this.expectedType)
val resolvedAtom = candidateOfOuterCall.preprocessLambdaArgument(
csBuilder,
atom,
fixedExpectedType,
expectedTypeRef,
forceResolution = true,
returnTypeVariable
) as ResolvedLambdaAtom
analyzed = true
return resolvedAtom
}
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addIfNotNull
class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) {
private var primaryConstructorParametersScope: FirLocalScope? = null
@@ -491,7 +490,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
val expectedTypeRef = (data as? ResolutionMode.WithExpectedType)?.expectedTypeRef ?: buildImplicitTypeRef()
val resolvedLambdaAtom = (expectedTypeRef as? FirResolvedTypeRef)?.let {
extractLambdaInfoFromFunctionalType(
it.type, it, anonymousFunction, session, components
it.type, it, anonymousFunction, returnTypeVariable = null, components, candidate = null
)
}
var af = anonymousFunction
@@ -6,7 +6,7 @@ digraph lambdaAsReturnOfLambda_kt {
subgraph cluster_0 {
color=red
0 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
1 [label="Jump: ^@run lambda@fun <anonymous>(foo: R|ERROR CLASS: No type for parameter|): R|kotlin/Unit| {
1 [label="Jump: ^@run lambda@fun <anonymous>(foo: R|kotlin/String|): R|kotlin/Unit| {
R|/bar|(R|<local>/foo|)
}
"];
@@ -44,7 +44,7 @@ digraph lambdaAsReturnOfLambda_kt {
10 [label="Enter property" style="filled" fillcolor=red];
11 [label="Postponed enter to lambda"];
12 [label="Postponed exit from lambda"];
13 [label="Function call: R|/run|<R|(ERROR CLASS: No type for parameter) -> kotlin/Unit|>(<L> = run@fun <anonymous>(): R|(ERROR CLASS: No type for parameter) -> kotlin/Unit|)"];
13 [label="Function call: R|/run|<R|(kotlin/String) -> kotlin/Unit|>(<L> = run@fun <anonymous>(): R|(kotlin/String) -> kotlin/Unit|)"];
14 [label="Exit property" style="filled" fillcolor=red];
}
@@ -1,7 +1,7 @@
// !DUMP_CFG
val x4: (String) -> Unit = run {
return@run (lambda@{ foo ->
return@run (lambda@{ foo: String ->
bar(foo)
})
}
@@ -1,6 +1,6 @@
FILE: lambdaAsReturnOfLambda.kt
public final val x4: R|(kotlin/String) -> kotlin/Unit| = R|/run|<R|(ERROR CLASS: No type for parameter) -> kotlin/Unit|>(<L> = run@fun <anonymous>(): R|(ERROR CLASS: No type for parameter) -> kotlin/Unit| {
^@run lambda@fun <anonymous>(foo: R|ERROR CLASS: No type for parameter|): R|kotlin/Unit| {
public final val x4: R|(kotlin/String) -> kotlin/Unit| = R|/run|<R|(kotlin/String) -> kotlin/Unit|>(<L> = run@fun <anonymous>(): R|(kotlin/String) -> kotlin/Unit| {
^@run lambda@fun <anonymous>(foo: R|kotlin/String|): R|kotlin/Unit| {
R|/bar|(R|<local>/foo|)
}
@@ -26,9 +26,9 @@ fun case1(javaClass: JavaClass?) {
validType.checkType { _<Function1<JavaClass, Boolean>>() } //ok
invalidType.checkType { _<Function1<Nothing, Boolean>>() } //(!!!)
invalidType.checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Function1<Nothing, Boolean>>() } //(!!!)
Case1(javaClass).x.checkType { _<Function1<Nothing, Boolean>>() } //(!!!)
Case1(javaClass).x.checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Function1<Nothing, Boolean>>() } //(!!!)
}
class Case1(val javaClass: JavaClass?) {
@@ -55,9 +55,9 @@ fun case2(kotlinClass: KotlinClass?) {
validType.checkType { _<Function1<KotlinClass, Boolean>>() } //ok
invalidType.checkType { _<Function1<Nothing, Boolean>>() } //(!!!)
invalidType.checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Function1<Nothing, Boolean>>() } //(!!!)
Case2(kotlinClass).x.checkType { _<Function1<Nothing, Boolean>>() } //(!!!)
Case2(kotlinClass).x.checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Function1<Nothing, Boolean>>() } //(!!!)
}
class Case2(val kotlinClass: KotlinClass?) {
@@ -2,7 +2,7 @@ FILE: KotlinClass.kt
public final fun case1(javaClass: R|JavaClass?|): R|kotlin/Unit| {
lval validType: R|(JavaClass) -> kotlin/Boolean| = when () {
!=(R|<local>/javaClass|, Null(null)) -> {
fun <anonymous>(it: R|kotlin/Nothing|): R|kotlin/Boolean| {
fun <anonymous>(it: R|JavaClass|): R|kotlin/Boolean| {
^ ==(R|<local>/it|, R|<local>/javaClass|)
}
@@ -12,9 +12,9 @@ FILE: KotlinClass.kt
}
}
lval invalidType: R|(kotlin/Nothing) -> kotlin/Boolean| = when () {
lval invalidType: R|(JavaClass) -> kotlin/Boolean| = when () {
!=(R|<local>/javaClass|, Null(null)) -> {
fun <anonymous>(it: R|kotlin/Nothing|): R|kotlin/Boolean| {
fun <anonymous>(it: R|JavaClass|): R|kotlin/Boolean| {
^ ==(R|<local>/it|, R|<local>/javaClass|)
}
@@ -28,12 +28,12 @@ FILE: KotlinClass.kt
this@R|special/anonymous|.R|tests/_checkType/_|<R|(JavaClass) -> kotlin/Boolean|>()
}
)
R|<local>/invalidType|.R|tests/_checkType/checkType|<R|(kotlin/Nothing) -> kotlin/Boolean|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/Function1<kotlin/Nothing, kotlin/Boolean>>|.<anonymous>(): R|kotlin/Unit| {
this@R|special/anonymous|.R|tests/_checkType/_|<R|(kotlin/Nothing) -> kotlin/Boolean|>()
R|<local>/invalidType|.R|tests/_checkType/checkType|<R|(JavaClass) -> kotlin/Boolean|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/Function1<JavaClass, kotlin/Boolean>>|.<anonymous>(): R|kotlin/Unit| {
^ <Inapplicable(WRONG_RECEIVER): [tests/_checkType/_]>#<R|(kotlin/Nothing) -> kotlin/Boolean|>()
}
)
R|/Case1.Case1|(R|<local>/javaClass|).R|/Case1.x|.R|tests/_checkType/checkType|<R|(kotlin/Nothing) -> kotlin/Boolean|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/Function1<kotlin/Nothing, kotlin/Boolean>>|.<anonymous>(): R|kotlin/Unit| {
this@R|special/anonymous|.R|tests/_checkType/_|<R|(kotlin/Nothing) -> kotlin/Boolean|>()
R|/Case1.Case1|(R|<local>/javaClass|).R|/Case1.x|.R|tests/_checkType/checkType|<R|(KotlinClass) -> kotlin/Boolean|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/Function1<KotlinClass, kotlin/Boolean>>|.<anonymous>(): R|kotlin/Unit| {
^ <Inapplicable(WRONG_RECEIVER): [tests/_checkType/_]>#<R|(kotlin/Nothing) -> kotlin/Boolean|>()
}
)
}
@@ -45,9 +45,9 @@ FILE: KotlinClass.kt
public final val javaClass: R|JavaClass?| = R|<local>/javaClass|
public get(): R|JavaClass?|
public final val x: R|(kotlin/Nothing) -> kotlin/Boolean| = when () {
public final val x: R|(KotlinClass) -> kotlin/Boolean| = when () {
!=(R|<local>/javaClass|, Null(null)) -> {
fun <anonymous>(it: R|kotlin/Nothing|): R|kotlin/Boolean| {
fun <anonymous>(it: R|KotlinClass|): R|kotlin/Boolean| {
^ ==(R|<local>/it|, R|<local>/javaClass|)
}
@@ -57,7 +57,7 @@ FILE: KotlinClass.kt
}
}
public get(): R|(kotlin/Nothing) -> kotlin/Boolean|
public get(): R|(KotlinClass) -> kotlin/Boolean|
}
public final class BooCase1 : R|kotlin/Any| {
@@ -95,7 +95,7 @@ FILE: KotlinClass.kt
public final fun case2(kotlinClass: R|KotlinClass?|): R|kotlin/Unit| {
lval validType: R|(KotlinClass) -> kotlin/Boolean| = when () {
!=(R|<local>/kotlinClass|, Null(null)) -> {
fun <anonymous>(it: R|kotlin/Nothing|): R|kotlin/Boolean| {
fun <anonymous>(it: R|KotlinClass|): R|kotlin/Boolean| {
^ ==(R|<local>/it|, R|<local>/kotlinClass|)
}
@@ -105,9 +105,9 @@ FILE: KotlinClass.kt
}
}
lval invalidType: R|(kotlin/Nothing) -> kotlin/Boolean| = when () {
lval invalidType: R|(KotlinClass) -> kotlin/Boolean| = when () {
!=(R|<local>/kotlinClass|, Null(null)) -> {
fun <anonymous>(it: R|kotlin/Nothing|): R|kotlin/Boolean| {
fun <anonymous>(it: R|KotlinClass|): R|kotlin/Boolean| {
^ ==(R|<local>/it|, R|<local>/kotlinClass|)
}
@@ -121,12 +121,12 @@ FILE: KotlinClass.kt
this@R|special/anonymous|.R|tests/_checkType/_|<R|(KotlinClass) -> kotlin/Boolean|>()
}
)
R|<local>/invalidType|.R|tests/_checkType/checkType|<R|(kotlin/Nothing) -> kotlin/Boolean|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/Function1<kotlin/Nothing, kotlin/Boolean>>|.<anonymous>(): R|kotlin/Unit| {
this@R|special/anonymous|.R|tests/_checkType/_|<R|(kotlin/Nothing) -> kotlin/Boolean|>()
R|<local>/invalidType|.R|tests/_checkType/checkType|<R|(KotlinClass) -> kotlin/Boolean|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/Function1<KotlinClass, kotlin/Boolean>>|.<anonymous>(): R|kotlin/Unit| {
^ <Inapplicable(WRONG_RECEIVER): [tests/_checkType/_]>#<R|(kotlin/Nothing) -> kotlin/Boolean|>()
}
)
R|/Case2.Case2|(R|<local>/kotlinClass|).R|/Case2.x|.R|tests/_checkType/checkType|<R|(kotlin/Nothing) -> kotlin/Boolean|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/Function1<kotlin/Nothing, kotlin/Boolean>>|.<anonymous>(): R|kotlin/Unit| {
this@R|special/anonymous|.R|tests/_checkType/_|<R|(kotlin/Nothing) -> kotlin/Boolean|>()
R|/Case2.Case2|(R|<local>/kotlinClass|).R|/Case2.x|.R|tests/_checkType/checkType|<R|(KotlinClass) -> kotlin/Boolean|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/Function1<KotlinClass, kotlin/Boolean>>|.<anonymous>(): R|kotlin/Unit| {
^ <Inapplicable(WRONG_RECEIVER): [tests/_checkType/_]>#<R|(kotlin/Nothing) -> kotlin/Boolean|>()
}
)
}
@@ -138,9 +138,9 @@ FILE: KotlinClass.kt
public final val kotlinClass: R|KotlinClass?| = R|<local>/kotlinClass|
public get(): R|KotlinClass?|
public final val x: R|(kotlin/Nothing) -> kotlin/Boolean| = when () {
public final val x: R|(KotlinClass) -> kotlin/Boolean| = when () {
!=(R|<local>/kotlinClass|, Null(null)) -> {
fun <anonymous>(it: R|kotlin/Nothing|): R|kotlin/Boolean| {
fun <anonymous>(it: R|KotlinClass|): R|kotlin/Boolean| {
^ ==(R|<local>/it|, R|<local>/kotlinClass|)
}
@@ -150,7 +150,7 @@ FILE: KotlinClass.kt
}
}
public get(): R|(kotlin/Nothing) -> kotlin/Boolean|
public get(): R|(KotlinClass) -> kotlin/Boolean|
}
public final class BooCase2 : R|kotlin/Any| {
@@ -22,5 +22,5 @@ class A(val isLocked: Boolean) {
var classifierNamePolicy: ClassifierNamePolicy by property(ClassifierNamePolicy.SOURCE_CODE_QUALIFIED)
// getter has INAPPLICABLE diagnostic, see dump
var typeNormalizer by <!INAPPLICABLE_CANDIDATE!>property<!><(KotlinType) -> KotlinType>({ <!UNRESOLVED_REFERENCE!>it<!> })
var typeNormalizer by property<(KotlinType) -> KotlinType>({ it })
}
@@ -41,15 +41,15 @@ FILE: delegateTypeMismatch.kt
D|/A.classifierNamePolicy|.R|FakeOverride<kotlin/properties/ReadWriteProperty.setValue: R|kotlin/Unit|>|(this@R|/A|, ::R|/A.classifierNamePolicy|, R|<local>/classifierNamePolicy|)
}
public final var typeNormalizer: <ERROR TYPE REF: Ambiguity: getValue, [kotlin/getValue, kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>by <Inapplicable(INAPPLICABLE): [/A.property]>#<R|(KotlinType) -> KotlinType|>(property@fun <anonymous>(): R|ERROR CLASS: Unresolved name: it| {
^ <Unresolved name: it>#
public final var typeNormalizer: R|(KotlinType) -> KotlinType|by this@R|/A|.R|/A.property|<R|(KotlinType) -> KotlinType|>(property@fun <anonymous>(it: R|KotlinType|): R|KotlinType| {
^ R|<local>/it|
}
)
public get(): <ERROR TYPE REF: Ambiguity: getValue, [kotlin/getValue, kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]> {
^ D|/A.typeNormalizer|.<Ambiguity: getValue, [kotlin/getValue, kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>#(this@R|/A|, ::R|/A.typeNormalizer|)
public get(): R|(KotlinType) -> KotlinType| {
^ D|/A.typeNormalizer|.R|FakeOverride<kotlin/properties/ReadWriteProperty.getValue: R|(KotlinType) -> KotlinType|>|(this@R|/A|, ::R|/A.typeNormalizer|)
}
public set(<set-?>: <ERROR TYPE REF: Ambiguity: getValue, [kotlin/getValue, kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>): R|kotlin/Unit| {
D|/A.typeNormalizer|.<Inapplicable(INAPPLICABLE): [kotlin/collections/setValue]>#(this@R|/A|, ::R|/A.typeNormalizer|, R|<local>/typeNormalizer|)
public set(<set-?>: R|(KotlinType) -> KotlinType|): R|kotlin/Unit| {
D|/A.typeNormalizer|.R|FakeOverride<kotlin/properties/ReadWriteProperty.setValue: R|kotlin/Unit|>|(this@R|/A|, ::R|/A.typeNormalizer|, R|<local>/typeNormalizer|)
}
}
@@ -0,0 +1,12 @@
// ISSUE: KT-37304
import kotlin.properties.ReadWriteProperty
interface B
class A {
private fun <T> property(initialValue: T): ReadWriteProperty<A, T> = null!!
var conventer by property<(B) -> B>({ it })
var conventerWithExpectedType: (B) -> B by property({ it })
}
@@ -0,0 +1,35 @@
FILE: propertyWithFunctionalType.kt
public abstract interface B : R|kotlin/Any| {
}
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
private final fun <T> property(initialValue: R|T|): R|kotlin/properties/ReadWriteProperty<A, T>| {
^property Null(null)!!
}
public final var conventer: R|(B) -> B|by this@R|/A|.R|/A.property|<R|(B) -> B|>(property@fun <anonymous>(it: R|B|): R|B| {
^ R|<local>/it|
}
)
public get(): R|(B) -> B| {
^ D|/A.conventer|.R|FakeOverride<kotlin/properties/ReadWriteProperty.getValue: R|(B) -> B|>|(this@R|/A|, ::R|/A.conventer|)
}
public set(<set-?>: R|(B) -> B|): R|kotlin/Unit| {
D|/A.conventer|.R|FakeOverride<kotlin/properties/ReadWriteProperty.setValue: R|kotlin/Unit|>|(this@R|/A|, ::R|/A.conventer|, R|<local>/conventer|)
}
public final var conventerWithExpectedType: R|(B) -> B|by this@R|/A|.R|/A.property|<R|(B) -> B|>(property@fun <anonymous>(it: R|B|): R|B| {
^ R|<local>/it|
}
)
public get(): R|(B) -> B| {
^ D|/A.conventerWithExpectedType|.R|FakeOverride<kotlin/properties/ReadWriteProperty.getValue: R|(B) -> B|>|(this@R|/A|, ::R|/A.conventerWithExpectedType|)
}
public set(<set-?>: R|(B) -> B|): R|kotlin/Unit| {
D|/A.conventerWithExpectedType|.R|FakeOverride<kotlin/properties/ReadWriteProperty.setValue: R|kotlin/Unit|>|(this@R|/A|, ::R|/A.conventerWithExpectedType|, R|<local>/conventerWithExpectedType|)
}
}
@@ -519,6 +519,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic
runTest("compiler/fir/resolve/testData/resolveWithStdlib/delegates/delegateWithAnonymousObject.kt");
}
@TestMetadata("propertyWithFunctionalType.kt")
public void testPropertyWithFunctionalType() throws Exception {
runTest("compiler/fir/resolve/testData/resolveWithStdlib/delegates/propertyWithFunctionalType.kt");
}
@TestMetadata("simpleDelegateProvider.kt")
public void testSimpleDelegateProvider() throws Exception {
runTest("compiler/fir/resolve/testData/resolveWithStdlib/delegates/simpleDelegateProvider.kt");