[FIR] Support completion of lambdas with type variable as expected type
#KT-37310 Fixed #KT-37304 Fixed
This commit is contained in:
@@ -49,7 +49,7 @@ fun Candidate.resolveArgumentExpression(
|
|||||||
isDispatch: Boolean,
|
isDispatch: Boolean,
|
||||||
isSafeCall: Boolean
|
isSafeCall: Boolean
|
||||||
) {
|
) {
|
||||||
return when (argument) {
|
when (argument) {
|
||||||
is FirFunctionCall, is FirWhenExpression, is FirTryExpression, is FirCheckNotNullCall -> resolveSubCallArgument(
|
is FirFunctionCall, is FirWhenExpression, is FirTryExpression, is FirCheckNotNullCall -> resolveSubCallArgument(
|
||||||
csBuilder,
|
csBuilder,
|
||||||
argument as FirResolvable,
|
argument as FirResolvable,
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ class FirCallCompleter(
|
|||||||
private val transformer: FirBodyResolveTransformer,
|
private val transformer: FirBodyResolveTransformer,
|
||||||
components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents
|
components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents
|
||||||
) : BodyResolveComponents by components {
|
) : BodyResolveComponents by components {
|
||||||
val completer = ConstraintSystemCompleter(components.inferenceComponents)
|
val completer = ConstraintSystemCompleter(components)
|
||||||
private val inferenceSession
|
private val inferenceSession
|
||||||
get() = inferenceComponents.inferenceSession
|
get() = inferenceComponents.inferenceSession
|
||||||
|
|
||||||
|
|||||||
+104
-13
@@ -6,17 +6,18 @@
|
|||||||
package org.jetbrains.kotlin.fir.resolve.inference
|
package org.jetbrains.kotlin.fir.resolve.inference
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
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.Candidate
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||||
import org.jetbrains.kotlin.fir.returnExpressions
|
import org.jetbrains.kotlin.fir.returnExpressions
|
||||||
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
|
||||||
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.TypeVariableDirectionCalculator
|
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.components.VariableFixationFinder
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
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.inference.model.VariableWithConstraints
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
|
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
|
||||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
@@ -94,8 +95,8 @@ private fun Candidate.hasProperNonTrivialLowerConstraints(components: InferenceC
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ConstraintSystemCompleter(val components: InferenceComponents) {
|
class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
|
||||||
private val variableFixationFinder = VariableFixationFinder(components.trivialConstraintTypeInferenceOracle)
|
private val variableFixationFinder = VariableFixationFinder(components.inferenceComponents.trivialConstraintTypeInferenceOracle)
|
||||||
|
|
||||||
fun complete(
|
fun complete(
|
||||||
c: KotlinConstraintSystemCompleter.Context,
|
c: KotlinConstraintSystemCompleter.Context,
|
||||||
@@ -109,16 +110,18 @@ class ConstraintSystemCompleter(val components: InferenceComponents) {
|
|||||||
if (analyzePostponeArgumentIfPossible(c, topLevelAtoms, analyze)) continue
|
if (analyzePostponeArgumentIfPossible(c, topLevelAtoms, analyze)) continue
|
||||||
|
|
||||||
val allTypeVariables = getOrderedAllTypeVariables(c, topLevelAtoms)
|
val allTypeVariables = getOrderedAllTypeVariables(c, topLevelAtoms)
|
||||||
val postponedKtPrimitives = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
|
val postponedAtoms = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
|
||||||
val variableForFixation =
|
val variableForFixation =
|
||||||
variableFixationFinder.findFirstVariableForFixation(
|
variableFixationFinder.findFirstVariableForFixation(
|
||||||
c, allTypeVariables, postponedKtPrimitives, completionMode, candidateReturnType
|
c, allTypeVariables, postponedAtoms, completionMode, candidateReturnType
|
||||||
) ?: break
|
) ?: break
|
||||||
|
|
||||||
// if (shouldForceCallableReferenceOrLambdaResolution(completionMode, variableForFixation)) {
|
if (
|
||||||
// if (forcePostponedAtomResolution<ResolvedCallableReferenceAtom>(topLevelAtoms, analyze)) continue
|
completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL &&
|
||||||
// if (forcePostponedAtomResolution<LambdaWithTypeVariableAsExpectedTypeAtom>(topLevelAtoms, analyze)) continue
|
resolveLambdaOrCallableReferenceWithTypeVariableAsExpectedType(c, variableForFixation, postponedAtoms, analyze)
|
||||||
// }
|
) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if (variableForFixation.hasProperConstraint || completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL) {
|
if (variableForFixation.hasProperConstraint || completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL) {
|
||||||
val variableWithConstraints = c.notFixedTypeVariables.getValue(variableForFixation.variable)
|
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(
|
private fun getOrderedAllTypeVariables(
|
||||||
c: KotlinConstraintSystemCompleter.Context,
|
c: KotlinConstraintSystemCompleter.Context,
|
||||||
topLevelAtoms: List<FirStatement>
|
topLevelAtoms: List<FirStatement>
|
||||||
@@ -158,6 +244,11 @@ class ConstraintSystemCompleter(val components: InferenceComponents) {
|
|||||||
typeVariable.toTypeConstructor()
|
typeVariable.toTypeConstructor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (postponedAtom in candidate.postponedAtoms) {
|
||||||
|
when (postponedAtom) {
|
||||||
|
is ResolvedLambdaAtom -> postponedAtom.typeVariableForLambdaReturnType
|
||||||
|
}
|
||||||
|
}
|
||||||
for (lambdaAtom in candidate.postponedAtoms.filterIsInstance<ResolvedLambdaAtom>()) {
|
for (lambdaAtom in candidate.postponedAtoms.filterIsInstance<ResolvedLambdaAtom>()) {
|
||||||
result.addIfNotNull(lambdaAtom.typeVariableForLambdaReturnType.toTypeConstructor())
|
result.addIfNotNull(lambdaAtom.typeVariableForLambdaReturnType.toTypeConstructor())
|
||||||
}
|
}
|
||||||
@@ -191,7 +282,7 @@ class ConstraintSystemCompleter(val components: InferenceComponents) {
|
|||||||
variableWithConstraints: VariableWithConstraints,
|
variableWithConstraints: VariableWithConstraints,
|
||||||
direction: TypeVariableDirectionCalculator.ResolveDirection
|
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
|
c.fixVariable(variableWithConstraints.typeVariable, resultType, atom = null) // TODO: obtain atom for diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+46
-16
@@ -30,15 +30,16 @@ fun Candidate.preprocessLambdaArgument(
|
|||||||
argument: FirAnonymousFunction,
|
argument: FirAnonymousFunction,
|
||||||
expectedType: ConeKotlinType?,
|
expectedType: ConeKotlinType?,
|
||||||
expectedTypeRef: FirTypeRef,
|
expectedTypeRef: FirTypeRef,
|
||||||
forceResolution: Boolean = false
|
forceResolution: Boolean = false,
|
||||||
) {
|
returnTypeVariable: ConeTypeVariableForLambdaReturnType? = null
|
||||||
|
): PostponedResolvedAtom {
|
||||||
if (expectedType != null && !forceResolution && csBuilder.isTypeVariable(expectedType)) {
|
if (expectedType != null && !forceResolution && csBuilder.isTypeVariable(expectedType)) {
|
||||||
//return LambdaWithTypeVariableAsExpectedTypeAtom(argument, expectedType)
|
return LambdaWithTypeVariableAsExpectedTypeAtom(argument, expectedType, expectedTypeRef, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
val resolvedArgument =
|
val resolvedArgument =
|
||||||
extractLambdaInfoFromFunctionalType(expectedType, expectedTypeRef, argument, bodyResolveComponents.session, bodyResolveComponents)
|
extractLambdaInfoFromFunctionalType(expectedType, expectedTypeRef, argument, returnTypeVariable, bodyResolveComponents, this)
|
||||||
?: extraLambdaInfo(expectedType, argument, csBuilder, bodyResolveComponents.session, bodyResolveComponents)
|
?: extraLambdaInfo(expectedType, argument, csBuilder, bodyResolveComponents.session, this)
|
||||||
|
|
||||||
if (expectedType != null) {
|
if (expectedType != null) {
|
||||||
// TODO: add SAM conversion processing
|
// TODO: add SAM conversion processing
|
||||||
@@ -46,7 +47,7 @@ fun Candidate.preprocessLambdaArgument(
|
|||||||
csBuilder.addSubtypeConstraint(lambdaType, expectedType, SimpleConstraintSystemConstraintPosition)
|
csBuilder.addSubtypeConstraint(lambdaType, expectedType, SimpleConstraintSystemConstraintPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
postponedAtoms += resolvedArgument
|
return resolvedArgument
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Candidate.preprocessCallableReference(
|
fun Candidate.preprocessCallableReference(
|
||||||
@@ -103,7 +104,7 @@ private fun extraLambdaInfo(
|
|||||||
argument: FirAnonymousFunction,
|
argument: FirAnonymousFunction,
|
||||||
csBuilder: ConstraintSystemBuilder,
|
csBuilder: ConstraintSystemBuilder,
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
components: BodyResolveComponents
|
candidate: Candidate?
|
||||||
): ResolvedLambdaAtom {
|
): ResolvedLambdaAtom {
|
||||||
val isSuspend = expectedType?.isSuspendFunctionType(session) ?: false
|
val isSuspend = expectedType?.isSuspendFunctionType(session) ?: false
|
||||||
|
|
||||||
@@ -111,7 +112,7 @@ private fun extraLambdaInfo(
|
|||||||
expectedType != null && expectedType.lowerBoundIfFlexible()
|
expectedType != null && expectedType.lowerBoundIfFlexible()
|
||||||
.isBuiltinFunctionalType(session)//isNotNullOrNullableFunctionSupertype(expectedType)
|
.isBuiltinFunctionalType(session)//isNotNullOrNullableFunctionSupertype(expectedType)
|
||||||
|
|
||||||
val typeVariable = TypeVariableForLambdaReturnType(argument, "_L")
|
val typeVariable = ConeTypeVariableForLambdaReturnType(argument, "_L")
|
||||||
|
|
||||||
val receiverType = argument.receiverType
|
val receiverType = argument.receiverType
|
||||||
val returnType =
|
val returnType =
|
||||||
@@ -129,11 +130,13 @@ private fun extraLambdaInfo(
|
|||||||
|
|
||||||
return ResolvedLambdaAtom(
|
return ResolvedLambdaAtom(
|
||||||
argument,
|
argument,
|
||||||
|
expectedType,
|
||||||
isSuspend,
|
isSuspend,
|
||||||
receiverType,
|
receiverType,
|
||||||
parameters,
|
parameters,
|
||||||
returnType,
|
returnType,
|
||||||
typeVariable.takeIf { newTypeVariableUsed }
|
typeVariable.takeIf { newTypeVariableUsed },
|
||||||
|
candidate
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,12 +144,14 @@ internal fun extractLambdaInfoFromFunctionalType(
|
|||||||
expectedType: ConeKotlinType?,
|
expectedType: ConeKotlinType?,
|
||||||
expectedTypeRef: FirTypeRef,
|
expectedTypeRef: FirTypeRef,
|
||||||
argument: FirAnonymousFunction,
|
argument: FirAnonymousFunction,
|
||||||
session: FirSession,
|
returnTypeVariable: ConeTypeVariableForLambdaReturnType?,
|
||||||
components: BodyResolveComponents
|
components: BodyResolveComponents,
|
||||||
|
candidate: Candidate?
|
||||||
): ResolvedLambdaAtom? {
|
): ResolvedLambdaAtom? {
|
||||||
|
val session = components.session
|
||||||
if (expectedType == null) return null
|
if (expectedType == null) return null
|
||||||
if (expectedType is ConeFlexibleType) {
|
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
|
if (!expectedType.isBuiltinFunctionalType(session)) return null
|
||||||
|
|
||||||
@@ -156,11 +161,13 @@ internal fun extractLambdaInfoFromFunctionalType(
|
|||||||
|
|
||||||
return ResolvedLambdaAtom(
|
return ResolvedLambdaAtom(
|
||||||
argument,
|
argument,
|
||||||
|
expectedType,
|
||||||
expectedType.isSuspendFunctionType(session),
|
expectedType.isSuspendFunctionType(session),
|
||||||
receiverType,
|
receiverType,
|
||||||
parameters,
|
parameters,
|
||||||
returnType,
|
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 {
|
sealed class PostponedResolvedAtom : PostponedResolvedAtomMarker {
|
||||||
abstract override val inputTypes: Collection<ConeKotlinType>
|
abstract override val inputTypes: Collection<ConeKotlinType>
|
||||||
abstract override val outputType: ConeKotlinType?
|
abstract override val outputType: ConeKotlinType?
|
||||||
override var analyzed: Boolean = false
|
override var analyzed: Boolean = false
|
||||||
|
abstract val expectedType: ConeKotlinType?
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResolvedLambdaAtom(
|
class ResolvedLambdaAtom(
|
||||||
val atom: FirAnonymousFunction,
|
val atom: FirAnonymousFunction,
|
||||||
|
override val expectedType: ConeKotlinType?,
|
||||||
val isSuspend: Boolean,
|
val isSuspend: Boolean,
|
||||||
val receiver: ConeKotlinType?,
|
val receiver: ConeKotlinType?,
|
||||||
val parameters: List<ConeKotlinType>,
|
val parameters: List<ConeKotlinType>,
|
||||||
val returnType: ConeKotlinType,
|
val returnType: ConeKotlinType,
|
||||||
val typeVariableForLambdaReturnType: TypeVariableForLambdaReturnType?
|
val typeVariableForLambdaReturnType: ConeTypeVariableForLambdaReturnType?,
|
||||||
|
val candidateForOuterCall: Candidate?
|
||||||
) : PostponedResolvedAtom() {
|
) : PostponedResolvedAtom() {
|
||||||
|
init {
|
||||||
|
candidateForOuterCall?.let {
|
||||||
|
it.postponedAtoms += this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lateinit var returnStatements: Collection<FirStatement>
|
lateinit var returnStatements: Collection<FirStatement>
|
||||||
|
|
||||||
override val inputTypes: Collection<ConeKotlinType> get() = receiver?.let { parameters + it } ?: parameters
|
override val inputTypes: Collection<ConeKotlinType> get() = receiver?.let { parameters + it } ?: parameters
|
||||||
override val outputType: ConeKotlinType get() = returnType
|
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(
|
class ResolvedCallableReferenceAtom(
|
||||||
val reference: FirCallableReferenceAccess,
|
val reference: FirCallableReferenceAccess,
|
||||||
val expectedType: ConeKotlinType?,
|
override val expectedType: ConeKotlinType?,
|
||||||
val lhs: DoubleColonLHS?,
|
val lhs: DoubleColonLHS?,
|
||||||
private val session: FirSession
|
private val session: FirSession
|
||||||
) : PostponedResolvedAtom() {
|
) : PostponedResolvedAtom() {
|
||||||
|
|||||||
+25
-8
@@ -11,14 +11,15 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement
|
|||||||
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
|
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.FirUnresolvedReferenceError
|
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.resolve.transformers.StoreNameReference
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
|
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
|
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.CoroutinePosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
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.StubTypeMarker
|
||||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||||
import org.jetbrains.kotlin.types.model.freshTypeConstructor
|
import org.jetbrains.kotlin.types.model.freshTypeConstructor
|
||||||
@@ -53,17 +54,15 @@ class PostponedArgumentsAnalyzer(
|
|||||||
candidate: Candidate
|
candidate: Candidate
|
||||||
//diagnosticsHolder: KotlinDiagnosticsHolder
|
//diagnosticsHolder: KotlinDiagnosticsHolder
|
||||||
) {
|
) {
|
||||||
when (argument) {
|
return when (argument) {
|
||||||
is ResolvedLambdaAtom ->
|
is ResolvedLambdaAtom ->
|
||||||
analyzeLambda(c, argument, candidate/*, diagnosticsHolder*/)
|
analyzeLambda(c, argument, candidate/*, diagnosticsHolder*/)
|
||||||
|
|
||||||
// is LambdaWithTypeVariableAsExpectedTypeAtom ->
|
is LambdaWithTypeVariableAsExpectedTypeAtom ->
|
||||||
// analyzeLambda(
|
analyzeLambda(c, argument.transformToResolvedLambda(c.getBuilder()), candidate/*, diagnosticsHolder*/)
|
||||||
// c, resolutionCallbacks, argument.transformToResolvedLambda(c.getBuilder()), diagnosticsHolder
|
|
||||||
// )
|
|
||||||
|
|
||||||
is ResolvedCallableReferenceAtom -> processCallableReference(argument, candidate)
|
is ResolvedCallableReferenceAtom -> processCallableReference(argument, candidate)
|
||||||
//
|
|
||||||
// is ResolvedCollectionLiteralAtom -> TODO("Not supported")
|
// 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
|
||||||
|
}
|
||||||
+1
-2
@@ -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.types.builder.buildResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.visitors.*
|
import org.jetbrains.kotlin.fir.visitors.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
|
||||||
|
|
||||||
class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) {
|
class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) {
|
||||||
private var primaryConstructorParametersScope: FirLocalScope? = null
|
private var primaryConstructorParametersScope: FirLocalScope? = null
|
||||||
@@ -491,7 +490,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
|
|||||||
val expectedTypeRef = (data as? ResolutionMode.WithExpectedType)?.expectedTypeRef ?: buildImplicitTypeRef()
|
val expectedTypeRef = (data as? ResolutionMode.WithExpectedType)?.expectedTypeRef ?: buildImplicitTypeRef()
|
||||||
val resolvedLambdaAtom = (expectedTypeRef as? FirResolvedTypeRef)?.let {
|
val resolvedLambdaAtom = (expectedTypeRef as? FirResolvedTypeRef)?.let {
|
||||||
extractLambdaInfoFromFunctionalType(
|
extractLambdaInfoFromFunctionalType(
|
||||||
it.type, it, anonymousFunction, session, components
|
it.type, it, anonymousFunction, returnTypeVariable = null, components, candidate = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
var af = anonymousFunction
|
var af = anonymousFunction
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ digraph lambdaAsReturnOfLambda_kt {
|
|||||||
subgraph cluster_0 {
|
subgraph cluster_0 {
|
||||||
color=red
|
color=red
|
||||||
0 [label="Enter function anonymousFunction" style="filled" fillcolor=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|)
|
R|/bar|(R|<local>/foo|)
|
||||||
}
|
}
|
||||||
"];
|
"];
|
||||||
@@ -44,7 +44,7 @@ digraph lambdaAsReturnOfLambda_kt {
|
|||||||
10 [label="Enter property" style="filled" fillcolor=red];
|
10 [label="Enter property" style="filled" fillcolor=red];
|
||||||
11 [label="Postponed enter to lambda"];
|
11 [label="Postponed enter to lambda"];
|
||||||
12 [label="Postponed exit from 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];
|
14 [label="Exit property" style="filled" fillcolor=red];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// !DUMP_CFG
|
// !DUMP_CFG
|
||||||
|
|
||||||
val x4: (String) -> Unit = run {
|
val x4: (String) -> Unit = run {
|
||||||
return@run (lambda@{ foo ->
|
return@run (lambda@{ foo: String ->
|
||||||
bar(foo)
|
bar(foo)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
FILE: lambdaAsReturnOfLambda.kt
|
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| {
|
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|ERROR CLASS: No type for parameter|): R|kotlin/Unit| {
|
^@run lambda@fun <anonymous>(foo: R|kotlin/String|): R|kotlin/Unit| {
|
||||||
R|/bar|(R|<local>/foo|)
|
R|/bar|(R|<local>/foo|)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ fun case1(javaClass: JavaClass?) {
|
|||||||
|
|
||||||
validType.checkType { _<Function1<JavaClass, Boolean>>() } //ok
|
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?) {
|
class Case1(val javaClass: JavaClass?) {
|
||||||
@@ -55,9 +55,9 @@ fun case2(kotlinClass: KotlinClass?) {
|
|||||||
|
|
||||||
validType.checkType { _<Function1<KotlinClass, Boolean>>() } //ok
|
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?) {
|
class Case2(val kotlinClass: KotlinClass?) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ FILE: KotlinClass.kt
|
|||||||
public final fun case1(javaClass: R|JavaClass?|): R|kotlin/Unit| {
|
public final fun case1(javaClass: R|JavaClass?|): R|kotlin/Unit| {
|
||||||
lval validType: R|(JavaClass) -> kotlin/Boolean| = when () {
|
lval validType: R|(JavaClass) -> kotlin/Boolean| = when () {
|
||||||
!=(R|<local>/javaClass|, Null(null)) -> {
|
!=(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|)
|
^ ==(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)) -> {
|
!=(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|)
|
^ ==(R|<local>/it|, R|<local>/javaClass|)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,12 +28,12 @@ FILE: KotlinClass.kt
|
|||||||
this@R|special/anonymous|.R|tests/_checkType/_|<R|(JavaClass) -> kotlin/Boolean|>()
|
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| {
|
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| {
|
||||||
this@R|special/anonymous|.R|tests/_checkType/_|<R|(kotlin/Nothing) -> kotlin/Boolean|>()
|
^ <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| {
|
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| {
|
||||||
this@R|special/anonymous|.R|tests/_checkType/_|<R|(kotlin/Nothing) -> kotlin/Boolean|>()
|
^ <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 final val javaClass: R|JavaClass?| = R|<local>/javaClass|
|
||||||
public get(): R|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)) -> {
|
!=(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|)
|
^ ==(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| {
|
public final class BooCase1 : R|kotlin/Any| {
|
||||||
@@ -95,7 +95,7 @@ FILE: KotlinClass.kt
|
|||||||
public final fun case2(kotlinClass: R|KotlinClass?|): R|kotlin/Unit| {
|
public final fun case2(kotlinClass: R|KotlinClass?|): R|kotlin/Unit| {
|
||||||
lval validType: R|(KotlinClass) -> kotlin/Boolean| = when () {
|
lval validType: R|(KotlinClass) -> kotlin/Boolean| = when () {
|
||||||
!=(R|<local>/kotlinClass|, Null(null)) -> {
|
!=(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|)
|
^ ==(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)) -> {
|
!=(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|)
|
^ ==(R|<local>/it|, R|<local>/kotlinClass|)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,12 +121,12 @@ FILE: KotlinClass.kt
|
|||||||
this@R|special/anonymous|.R|tests/_checkType/_|<R|(KotlinClass) -> kotlin/Boolean|>()
|
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| {
|
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| {
|
||||||
this@R|special/anonymous|.R|tests/_checkType/_|<R|(kotlin/Nothing) -> kotlin/Boolean|>()
|
^ <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| {
|
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| {
|
||||||
this@R|special/anonymous|.R|tests/_checkType/_|<R|(kotlin/Nothing) -> kotlin/Boolean|>()
|
^ <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 final val kotlinClass: R|KotlinClass?| = R|<local>/kotlinClass|
|
||||||
public get(): R|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)) -> {
|
!=(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|)
|
^ ==(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| {
|
public final class BooCase2 : R|kotlin/Any| {
|
||||||
|
|||||||
+1
-1
@@ -22,5 +22,5 @@ class A(val isLocked: Boolean) {
|
|||||||
var classifierNamePolicy: ClassifierNamePolicy by property(ClassifierNamePolicy.SOURCE_CODE_QUALIFIED)
|
var classifierNamePolicy: ClassifierNamePolicy by property(ClassifierNamePolicy.SOURCE_CODE_QUALIFIED)
|
||||||
// getter has INAPPLICABLE diagnostic, see dump
|
// getter has INAPPLICABLE diagnostic, see dump
|
||||||
|
|
||||||
var typeNormalizer by <!INAPPLICABLE_CANDIDATE!>property<!><(KotlinType) -> KotlinType>({ <!UNRESOLVED_REFERENCE!>it<!> })
|
var typeNormalizer by property<(KotlinType) -> KotlinType>({ it })
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -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|)
|
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| {
|
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| {
|
||||||
^ <Unresolved name: it>#
|
^ R|<local>/it|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
public get(): <ERROR TYPE REF: Ambiguity: getValue, [kotlin/getValue, kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]> {
|
public get(): R|(KotlinType) -> KotlinType| {
|
||||||
^ D|/A.typeNormalizer|.<Ambiguity: getValue, [kotlin/getValue, kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>#(this@R|/A|, ::R|/A.typeNormalizer|)
|
^ 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| {
|
public set(<set-?>: R|(KotlinType) -> KotlinType|): R|kotlin/Unit| {
|
||||||
D|/A.typeNormalizer|.<Inapplicable(INAPPLICABLE): [kotlin/collections/setValue]>#(this@R|/A|, ::R|/A.typeNormalizer|, R|<local>/typeNormalizer|)
|
D|/A.typeNormalizer|.R|FakeOverride<kotlin/properties/ReadWriteProperty.setValue: R|kotlin/Unit|>|(this@R|/A|, ::R|/A.typeNormalizer|, R|<local>/typeNormalizer|)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -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 })
|
||||||
|
}
|
||||||
+35
@@ -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|)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Generated
+5
@@ -519,6 +519,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic
|
|||||||
runTest("compiler/fir/resolve/testData/resolveWithStdlib/delegates/delegateWithAnonymousObject.kt");
|
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")
|
@TestMetadata("simpleDelegateProvider.kt")
|
||||||
public void testSimpleDelegateProvider() throws Exception {
|
public void testSimpleDelegateProvider() throws Exception {
|
||||||
runTest("compiler/fir/resolve/testData/resolveWithStdlib/delegates/simpleDelegateProvider.kt");
|
runTest("compiler/fir/resolve/testData/resolveWithStdlib/delegates/simpleDelegateProvider.kt");
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val p: (String) -> Boolean = if (true) {
|
val p: (String) -> Boolean = if (true) {
|
||||||
{ true }
|
{ true }
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
val foo: ((String) -> String) = run {
|
val foo: ((String) -> String) = run {
|
||||||
{ it }
|
{ it }
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ fun testLambda() {
|
|||||||
if (x is String) return@myRun { it -> x.length <!AMBIGUITY!>+<!> it }
|
if (x is String) return@myRun { it -> x.length <!AMBIGUITY!>+<!> it }
|
||||||
if (x !is Int) return@myRun { it -> it }
|
if (x !is Int) return@myRun { it -> it }
|
||||||
|
|
||||||
{ it -> x <!AMBIGUITY!>+<!> it }
|
{ it -> x + it }
|
||||||
}
|
}
|
||||||
|
|
||||||
val twoLambda: (Int) -> Int = myRun {
|
val twoLambda: (Int) -> Int = myRun {
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
//KT-3184 Type inference seems partially broken
|
|
||||||
package a
|
|
||||||
|
|
||||||
import java.util.HashMap
|
|
||||||
|
|
||||||
private fun <T> test(value: T, extf: String.(value: T)->Unit) {
|
|
||||||
"".extf(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
test(1, {value -> println(value)})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun tests() {
|
|
||||||
val dict = HashMap<String, (String) -> Unit>()
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>dict["0"] = { str -> println(str) }<!>
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>dict["1"] = { println(<!UNRESOLVED_REFERENCE!>it<!>) }<!>
|
|
||||||
|
|
||||||
dict.<!INAPPLICABLE_CANDIDATE!>set<!>("1", { println(<!UNRESOLVED_REFERENCE!>it<!>) })
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>dict["1"] = { r -> println(r) }<!>
|
|
||||||
}
|
|
||||||
|
|
||||||
// from standard library
|
|
||||||
operator fun <K, V> MutableMap<K, V>.set(key : K, value : V) : V? = this.put(key, value)
|
|
||||||
|
|
||||||
fun println(message : Any?) = System.out.println(message)
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
//KT-3184 Type inference seems partially broken
|
//KT-3184 Type inference seems partially broken
|
||||||
package a
|
package a
|
||||||
|
|
||||||
|
|||||||
-37
@@ -1,37 +0,0 @@
|
|||||||
// !LANGUAGE: +NewInference
|
|
||||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
|
||||||
|
|
||||||
class B {
|
|
||||||
class Builder
|
|
||||||
}
|
|
||||||
|
|
||||||
typealias ApplyRestrictions = B.Builder.() -> B.Builder
|
|
||||||
|
|
||||||
fun applyRestrictions1(): ApplyRestrictions = TODO()
|
|
||||||
fun applyRestrictions2() = applyRestrictions1()
|
|
||||||
fun <K> applyRestrictions3(e: K) = applyRestrictions1()
|
|
||||||
|
|
||||||
fun buildB() {
|
|
||||||
val a1 = applyRestrictions1()
|
|
||||||
val a2 = applyRestrictions2()
|
|
||||||
val a3 = applyRestrictions3("foo")
|
|
||||||
|
|
||||||
B.Builder().a1()
|
|
||||||
B.Builder().a2()
|
|
||||||
B.Builder().a3()
|
|
||||||
}
|
|
||||||
|
|
||||||
// additional example from #KT-34820
|
|
||||||
|
|
||||||
class R
|
|
||||||
class P
|
|
||||||
|
|
||||||
typealias F = R.(P) -> Unit
|
|
||||||
|
|
||||||
fun guess(): F? = TODO()
|
|
||||||
fun consume(f: F) {}
|
|
||||||
|
|
||||||
fun problem() {
|
|
||||||
val p = guess()
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>consume<!>(p ?: {})
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !LANGUAGE: +NewInference
|
// !LANGUAGE: +NewInference
|
||||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
// See EA-76890 / KT-10843: NPE during analysis
|
// See EA-76890 / KT-10843: NPE during analysis
|
||||||
fun lambda(x : Int?) = x?.<!UNRESOLVED_REFERENCE!>let<!> <!UNRESOLVED_REFERENCE!>l<!> {
|
fun lambda(x : Int?) = x?.<!UNRESOLVED_REFERENCE!>let<!> <!UNRESOLVED_REFERENCE!>l<!> {
|
||||||
y ->
|
y ->
|
||||||
if (y <!UNRESOLVED_REFERENCE!>><!> 0) return@l x
|
if (y > 0) return@l x
|
||||||
y
|
y
|
||||||
}!!
|
}!!
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class W4(val f: L2) {
|
|||||||
fun test1() { // to extension lambda 0
|
fun test1() { // to extension lambda 0
|
||||||
val w10 = W1 { this } // oi+ ni+
|
val w10 = W1 { this } // oi+ ni+
|
||||||
val i10: E0 = id { this } // o1- ni+
|
val i10: E0 = id { this } // o1- ni+
|
||||||
val j10 = <!INAPPLICABLE_CANDIDATE!>id<!><E0> { this } // oi+ ni+
|
val j10 = id<E0> { this } // oi+ ni+
|
||||||
val f10 = W1(fun Int.(): Int = this) // oi+ ni+
|
val f10 = W1(fun Int.(): Int = this) // oi+ ni+
|
||||||
val g10: E0 = id(fun Int.(): Int = this) // oi+ ni+
|
val g10: E0 = id(fun Int.(): Int = this) // oi+ ni+
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ fun test1() { // to extension lambda 0
|
|||||||
val i11: E0 = id { i: Int -> i } // o1+ ni+
|
val i11: E0 = id { i: Int -> i } // o1+ ni+
|
||||||
val w12 = <!INAPPLICABLE_CANDIDATE!>W1<!> { i -> i } // oi- ni-
|
val w12 = <!INAPPLICABLE_CANDIDATE!>W1<!> { i -> i } // oi- ni-
|
||||||
val i12: E0 = id { i -> i } // oi- ni-
|
val i12: E0 = id { i -> i } // oi- ni-
|
||||||
val j12 = <!INAPPLICABLE_CANDIDATE!>id<!><E0> { i -> i } // oi- ni-
|
val j12 = id<E0> { i -> i } // oi- ni-
|
||||||
|
|
||||||
// yet unsupported cases - considering lambdas as extension ones unconditionally
|
// yet unsupported cases - considering lambdas as extension ones unconditionally
|
||||||
// val w13 = W1 { it } // this or it: oi- ni-
|
// val w13 = W1 { it } // this or it: oi- ni-
|
||||||
@@ -79,7 +79,7 @@ fun test2() { // to extension lambda 1
|
|||||||
// val i27: E1 = id { i, s: String -> i + s.length } // overload oi- ni-
|
// val i27: E1 = id { i, s: String -> i + s.length } // overload oi- ni-
|
||||||
|
|
||||||
val w28 = <!INAPPLICABLE_CANDIDATE!>W2<!> { i: Int, s -> i <!AMBIGUITY!>+<!> s.<!UNRESOLVED_REFERENCE!>length<!> } // oi- ni-
|
val w28 = <!INAPPLICABLE_CANDIDATE!>W2<!> { i: Int, s -> i <!AMBIGUITY!>+<!> s.<!UNRESOLVED_REFERENCE!>length<!> } // oi- ni-
|
||||||
val i28: E1 = id { i: Int, s -> i <!AMBIGUITY!>+<!> s.<!UNRESOLVED_REFERENCE!>length<!> } // oi- ni-
|
val i28: E1 = id { i: Int, s -> i + s.length } // oi- ni-
|
||||||
val w29 = <!INAPPLICABLE_CANDIDATE!>W2<!> { i: Int, s: String -> i + s.length } // oi- ni-
|
val w29 = <!INAPPLICABLE_CANDIDATE!>W2<!> { i: Int, s: String -> i + s.length } // oi- ni-
|
||||||
val i29: E1 = id { i: Int, s: String -> i + s.length } // oi+ ni+
|
val i29: E1 = id { i: Int, s: String -> i + s.length } // oi+ ni+
|
||||||
|
|
||||||
@@ -92,8 +92,8 @@ fun test3() { // to non-extension lambda 1
|
|||||||
val w30 = W3 { i -> i } // oi+ ni+
|
val w30 = W3 { i -> i } // oi+ ni+
|
||||||
val i30: L1 = id { i -> i } // oi+ ni+
|
val i30: L1 = id { i -> i } // oi+ ni+
|
||||||
val w31 = W3 { it } // oi+ ni+
|
val w31 = W3 { it } // oi+ ni+
|
||||||
val i31: L1 = id { <!UNRESOLVED_REFERENCE!>it<!> } // oi- ni+
|
val i31: L1 = id { it } // oi- ni+
|
||||||
val j31 = <!INAPPLICABLE_CANDIDATE!>id<!><L1> { <!UNRESOLVED_REFERENCE!>it<!> } // oi+ ni+
|
val j31 = id<L1> { it } // oi+ ni+
|
||||||
|
|
||||||
// yet unsupported cases - considering lambdas as extension ones unconditionally
|
// yet unsupported cases - considering lambdas as extension ones unconditionally
|
||||||
// val w32 = W3 { this } // this or it: oi- ni-
|
// val w32 = W3 { this } // this or it: oi- ni-
|
||||||
|
|||||||
-32
@@ -1,32 +0,0 @@
|
|||||||
//If this test hangs, it means something is broken.
|
|
||||||
object A {
|
|
||||||
val iii = 42
|
|
||||||
}
|
|
||||||
|
|
||||||
//inappropriate but participating in resolve functions
|
|
||||||
fun foo(s: String, a: Any) = s + a
|
|
||||||
fun foo(a: Any) = a
|
|
||||||
fun foo(i: Int) = i
|
|
||||||
fun foo(a: Any, i: Int, f: ()-> Int) = "$a$i${f()}"
|
|
||||||
fun foo(f: (Int)->Int, i: Int) = f(i)
|
|
||||||
fun foo(f: (String)->Int, s: String) = f(s)
|
|
||||||
fun foo(f: (Any)->Int, a: Any) = f(a)
|
|
||||||
fun foo(s: String, f: (String, String)->Int) = f(s, s)
|
|
||||||
//appropriate function
|
|
||||||
fun foo(i: Int, f: (Int)->Int) = f(i)
|
|
||||||
|
|
||||||
fun <T> id(t: T) = t
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, id { x1 ->
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(2, id { x2 ->
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(3, id { x3 ->
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(4, id { x4 ->
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(5, id { x5 ->
|
|
||||||
x1 + x2 + x3 + x4 + x5 + A.iii
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
//If this test hangs, it means something is broken.
|
//If this test hangs, it means something is broken.
|
||||||
object A {
|
object A {
|
||||||
val iii = 42
|
val iii = 42
|
||||||
|
|||||||
Vendored
+5
-5
@@ -22,11 +22,11 @@ fun foo(i: Int, f: (Int) -> Int) = f(i)
|
|||||||
fun <T> id(t: T) = t
|
fun <T> id(t: T) = t
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
foo(1, id(fun(x1: Int) =
|
<!AMBIGUITY!>foo<!>(1, id(fun(x1: Int) =
|
||||||
foo(2, id(fun(x2: Int) =
|
<!AMBIGUITY!>foo<!>(2, id(fun(x2: Int) =
|
||||||
foo(3, id(fun(x3: Int) =
|
<!AMBIGUITY!>foo<!>(3, id(fun(x3: Int) =
|
||||||
foo(4, id(fun(x4: Int) =
|
<!AMBIGUITY!>foo<!>(4, id(fun(x4: Int) =
|
||||||
foo(5, id(fun(x5: Int) =
|
<!AMBIGUITY!>foo<!>(5, id(fun(x5: Int) =
|
||||||
x1 + x2 + x3 + x4 + x5 + A.iii
|
x1 + x2 + x3 + x4 + x5 + A.iii
|
||||||
))
|
))
|
||||||
))
|
))
|
||||||
|
|||||||
Reference in New Issue
Block a user