[NI] Add feature for choosing candidate by lambda return type

This commit is contained in:
Dmitriy Novozhilov
2020-04-22 13:15:49 +03:00
parent f243b8946f
commit 865ddac07a
19 changed files with 429 additions and 23 deletions
@@ -1788,6 +1788,29 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/factoryPattern")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class FactoryPattern extends AbstractFirOldFrontendDiagnosticsTestWithStdlib {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInFactoryPattern() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/factoryPattern"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("overloadByLambdaReturnType_disabled.kt")
public void testOverloadByLambdaReturnType_disabled() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/factoryPattern/overloadByLambdaReturnType_disabled.kt");
}
@TestMetadata("overloadByLambdaReturnType_enabled.kt")
public void testOverloadByLambdaReturnType_enabled() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/factoryPattern/overloadByLambdaReturnType_enabled.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/forInArrayLoop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -119,6 +119,8 @@ class FirCallCompleter(
inferenceSession.addPartiallyResolvedCall(approximatedCall)
CompletionResult(approximatedCall, false)
}
ConstraintSystemCompletionMode.UNTIL_FIRST_LAMBDA -> throw IllegalStateException()
}
}
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveTypeOrNullablePri
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isUnderKotlinPackage
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.builtins.createFunctionType
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -196,8 +197,10 @@ class KotlinResolutionCallbacksImpl(
val functionTypeInfo = expressionTypingServices.getTypeInfo(psiCallArgument.expression, actualContext)
(temporaryTrace ?: trace).record(BindingContext.NEW_INFERENCE_LAMBDA_INFO, psiCallArgument.ktFunction, LambdaInfo.STUB_EMPTY)
val inferedReturnType = functionTypeInfo.type?.arguments?.last()?.type?.takeIf { functionTypeInfo.type?.isFunctionTypeOrSubtype == true }
if (coroutineSession?.hasInapplicableCall() == true) {
return ReturnArgumentsAnalysisResult(ReturnArgumentsInfo.empty, coroutineSession, hasInapplicableCallForBuilderInference = true)
return ReturnArgumentsAnalysisResult(ReturnArgumentsInfo.empty, coroutineSession, inferedReturnType, hasInapplicableCallForBuilderInference = true)
} else {
temporaryTrace?.commit()
}
@@ -244,7 +247,8 @@ class KotlinResolutionCallbacksImpl(
lastExpressionCoercedToUnit,
returnArgumentFound
),
coroutineSession
coroutineSession,
inferedReturnType
)
}
@@ -18,15 +18,14 @@ package org.jetbrains.kotlin.resolve.calls
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver
import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
import org.jetbrains.kotlin.resolve.calls.components.NewOverloadingConflictResolver
import org.jetbrains.kotlin.resolve.calls.components.*
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.model.safeSubstitute
import org.jetbrains.kotlin.utils.addToStdlib.same
import java.lang.UnsupportedOperationException
@@ -142,13 +141,19 @@ class KotlinCallResolver(
}
}
val maximallySpecificCandidates = overloadingConflictResolver.chooseMaximallySpecificCandidates(
var maximallySpecificCandidates = overloadingConflictResolver.chooseMaximallySpecificCandidates(
refinedCandidates,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = true // todo
)
if (maximallySpecificCandidates.size > 1 && callComponents.languageVersionSettings.supportsFeature(LanguageFeature.FactoryPatternResolution)) {
maximallySpecificCandidates = kotlinCallCompleter.chooseCandidateRegardingFactoryPatternResolution(maximallySpecificCandidates, resolutionCallbacks)
}
return kotlinCallCompleter.runCompletion(candidateFactory, maximallySpecificCandidates, expectedType, resolutionCallbacks)
}
}
@@ -59,6 +59,7 @@ data class ReturnArgumentsInfo(
data class ReturnArgumentsAnalysisResult(
val returnArgumentsInfo: ReturnArgumentsInfo,
val inferenceSession: InferenceSession?,
val lambdaReturnType: KotlinType? = null,
val hasInapplicableCallForBuilderInference: Boolean = false
)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
@@ -15,11 +16,15 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintS
import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraintTypeInferenceOracle
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage.Empty.hasContradiction
import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.LambdaArgumentConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.forceResolution
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.model.safeSubstitute
import org.jetbrains.kotlin.utils.addToStdlib.same
class KotlinCallCompleter(
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
@@ -66,10 +71,89 @@ class KotlinCallCompleter(
candidate.runCompletion(completionMode, diagnosticHolder, resolutionCallbacks)
candidate.asCallResolutionResult(completionMode, diagnosticHolder)
}
ConstraintSystemCompletionMode.UNTIL_FIRST_LAMBDA -> throw IllegalStateException("Should not be here")
}
}
fun chooseCandidateRegardingFactoryPatternResolution(
candidates: Set<KotlinResolutionCandidate>,
resolutionCallbacks: KotlinResolutionCallbacks
): Set<KotlinResolutionCandidate> {
val lambdas = candidates.flatMap { candidate ->
candidate.getSubResolvedAtoms()
.filter { it is ResolvedLambdaAtom && !it.analyzed }
.map { candidate to it as ResolvedLambdaAtom }
}.groupBy { (_, atom) -> atom.atom }
.values
.singleOrNull()
?.toMap() ?: return candidates
if (!lambdas.values.same { it.parameters.size }) return candidates
if (!lambdas.values.all { it.expectedType?.isFunctionTypeOrSubtype == true }) return candidates
for (candidate in lambdas.keys) {
candidate.runCompletion(
ConstraintSystemCompletionMode.UNTIL_FIRST_LAMBDA,
candidate,
resolutionCallbacks
)
}
if (!lambdas.entries.same { (candidate, atom) -> candidate.getInputTypesOfLambdaAtom(atom) }) {
return candidates
}
val newAtoms = mutableMapOf<KotlinResolutionCandidate, ResolvedLambdaAtom>()
for ((candidate, atom) in lambdas.entries) {
newAtoms[candidate] = kotlinConstraintSystemCompleter.prepareLambdaAtomForFactoryPattern(atom, candidate, candidate)
}
val diagnosticHolderForLambda = KotlinDiagnosticsHolder.SimpleHolder()
val iterator = newAtoms.entries.iterator()
val (firstCandidate, firstAtom) = iterator.next()
val results = postponedArgumentsAnalyzer.analyzeLambda(
firstCandidate.getSystem().asPostponedArgumentsAnalyzerContext(),
resolutionCallbacks,
firstAtom,
diagnosticHolderForLambda
)
lambdas.getValue(firstCandidate).setAnalyzedResults(results.returnArgumentsInfo, listOf(firstAtom))
val lambdaReturnType = results.lambdaReturnType ?: return candidates
while (iterator.hasNext()) {
val (candidate, atom) = iterator.next()
atom.setAnalyzedResults(results.returnArgumentsInfo, firstAtom.subResolvedAtoms!!)
lambdas.getValue(candidate).setAnalyzedResults(results.returnArgumentsInfo, listOf(atom))
candidate.csBuilder.addSubtypeConstraint(lambdaReturnType, atom.returnType, LambdaArgumentConstraintPosition(atom))
}
val errorCandidates = mutableSetOf<KotlinResolutionCandidate>()
val successfulCandidates = mutableSetOf<KotlinResolutionCandidate>()
for (candidate in candidates) {
if (candidate.isSuccessful) {
successfulCandidates += candidate
} else {
errorCandidates += candidate
}
}
return when {
successfulCandidates.isNotEmpty() -> successfulCandidates
else -> errorCandidates
}
}
private fun KotlinResolutionCandidate.getInputTypesOfLambdaAtom(atom: ResolvedLambdaAtom): List<UnwrappedType> {
val result = mutableListOf<UnwrappedType>()
val substitutor = csBuilder.buildCurrentSubstitutor()
val ctx = getSystem().asConstraintSystemCompleterContext()
for (inputType in atom.inputTypes) {
result += substitutor.safeSubstitute(ctx, inputType) as UnwrappedType
}
return result
}
private fun KotlinResolutionCandidate.checkSamWithVararg(diagnosticHolder: KotlinDiagnosticsHolder.SimpleHolder) {
val samConversionPerArgumentWithWarningsForVarargAfterSam =
callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument) &&
@@ -220,6 +220,24 @@ fun LambdaWithTypeVariableAsExpectedTypeAtom.transformToResolvedLambda(
return resolvedLambdaAtom
}
fun ResolvedLambdaAtom.transformToResolvedLambda(
csBuilder: ConstraintSystemBuilder,
diagnosticsHolder: KotlinDiagnosticsHolder,
expectedType: UnwrappedType,
returnTypeVariable: TypeVariableForLambdaReturnType? = null
): ResolvedLambdaAtom {
val resolvedLambdaAtom = preprocessLambdaArgument(
csBuilder,
atom,
expectedType,
diagnosticsHolder,
forceResolution = true,
returnTypeVariable = returnTypeVariable
) as ResolvedLambdaAtom
return resolvedLambdaAtom
}
private fun preprocessCallableReference(
csBuilder: ConstraintSystemBuilder,
argument: CallableReferenceKotlinCallArgument,
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.CoroutinePosition
import org.jetbrains.kotlin.resolve.calls.inference.model.LambdaArgumentConstraintPosition
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.types.typeUtil.builtIns
@@ -65,12 +66,12 @@ class PostponedArgumentsAnalyzer(
}
}
private fun analyzeLambda(
fun analyzeLambda(
c: Context,
resolutionCallbacks: KotlinResolutionCallbacks,
lambda: ResolvedLambdaAtom,
diagnosticHolder: KotlinDiagnosticsHolder
) {
): ReturnArgumentsAnalysisResult {
val stubsForPostponedVariables = c.bindingStubsForPostponedVariables()
val currentSubstitutor = c.buildCurrentSubstitutor(stubsForPostponedVariables.mapKeys { it.key.freshTypeConstructor(c) })
@@ -120,20 +121,21 @@ class PostponedArgumentsAnalyzer(
else FilteredAnnotations(annotations, true) { it != KotlinBuiltIns.FQ_NAMES.extensionFunctionType }
}
val (returnArgumentsInfo, inferenceSession, hasInapplicableCallForBuilderInference) =
resolutionCallbacks.analyzeAndGetLambdaReturnArguments(
lambda.atom,
lambda.isSuspend,
receiver,
parameters,
expectedTypeForReturnArguments,
convertedAnnotations ?: Annotations.EMPTY,
stubsForPostponedVariables.cast()
)
val returnArgumentsAnalysisResult = resolutionCallbacks.analyzeAndGetLambdaReturnArguments(
lambda.atom,
lambda.isSuspend,
receiver,
parameters,
expectedTypeForReturnArguments,
convertedAnnotations ?: Annotations.EMPTY,
stubsForPostponedVariables.cast()
)
val (returnArgumentsInfo, inferenceSession, inferedReturnType, hasInapplicableCallForBuilderInference) =
returnArgumentsAnalysisResult
if (hasInapplicableCallForBuilderInference) {
c.getBuilder().removePostponedVariables()
return
return returnArgumentsAnalysisResult
}
val returnArguments = returnArgumentsInfo.nonErrorArguments
@@ -169,7 +171,7 @@ class PostponedArgumentsAnalyzer(
val postponedVariables = inferenceSession.inferPostponedVariables(lambda, storageSnapshot, diagnosticHolder)
if (postponedVariables == null) {
c.getBuilder().removePostponedVariables()
return
return returnArgumentsAnalysisResult
}
for ((constructor, resultType) in postponedVariables) {
@@ -180,6 +182,8 @@ class PostponedArgumentsAnalyzer(
c.getBuilder().addEqualityConstraint(variable.defaultType(c), resultType, CoroutinePosition())
}
}
return returnArgumentsAnalysisResult
}
private fun UnwrappedType?.receiver(): UnwrappedType? {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.resolve.calls.components.transformToResolvedLambda
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.model.*
@@ -12,6 +13,8 @@ import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
import org.jetbrains.kotlin.types.model.safeSubstitute
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import kotlin.collections.LinkedHashSet
@@ -24,7 +27,8 @@ class KotlinConstraintSystemCompleter(
enum class ConstraintSystemCompletionMode {
FULL,
PARTIAL
PARTIAL,
UNTIL_FIRST_LAMBDA
}
interface Context : VariableFixationFinder.Context, ResultTypeResolver.Context {
@@ -91,7 +95,9 @@ class KotlinConstraintSystemCompleter(
analyze: (PostponedResolvedAtom) -> Unit
) {
completion@ while (true) {
// TODO
val postponedArguments = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
if (completionMode == ConstraintSystemCompletionMode.UNTIL_FIRST_LAMBDA && hasLambdaToAnalyze(postponedArguments)) return
// Stage 1: analyze postponed arguments with fixed parameter types
if (analyzeArgumentWithFixedParameterTypes(postponedArguments, analyze))
@@ -210,6 +216,35 @@ class KotlinConstraintSystemCompleter(
return false
}
fun prepareLambdaAtomForFactoryPattern(
atom: ResolvedLambdaAtom,
candidate: KotlinResolutionCandidate,
diagnosticsHolder: KotlinDiagnosticsHolder,
): ResolvedLambdaAtom {
val returnVariable = TypeVariableForLambdaReturnType(candidate.callComponents.builtIns, "_R")
val csBuilder = candidate.csBuilder
csBuilder.registerVariable(returnVariable)
val functionalType: KotlinType = csBuilder.buildCurrentSubstitutor().safeSubstitute(candidate.getSystem().asConstraintSystemCompleterContext(), atom.expectedType!!) as KotlinType
val expectedType = KotlinTypeFactory.simpleType(
functionalType.annotations,
functionalType.constructor,
functionalType.arguments.dropLast(1) + returnVariable.defaultType.asTypeProjection(),
functionalType.isMarkedNullable
)
csBuilder.addSubtypeConstraint(
expectedType,
functionalType,
ArgumentConstraintPosition(atom.atom)
)
return atom.transformToResolvedLambda(csBuilder, diagnosticsHolder, expectedType, returnVariable)
}
private fun Context.hasLambdaToAnalyze(
postponedArguments: List<PostponedResolvedAtom>
): Boolean {
return analyzeArgumentWithFixedParameterTypes(postponedArguments) {}
}
private fun findPostponedArgumentWithRevisableExpectedType(postponedArguments: List<PostponedResolvedAtom>) =
postponedArguments.firstOrNull { argument -> argument is PostponedAtomWithRevisableExpectedType }
@@ -0,0 +1,36 @@
// !LANGUAGE: +NewInference -FactoryPatternResolution
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_EXPRESSION
// ISSUE: KT-11265
fun create(f: (Int) -> Int): Int = 1
fun create(f: (Int) -> String): String = ""
fun takeString(s: String) {}
fun takeInt(s: Int) {}
fun test_1() {
val x = <!AMBIGUITY!>create<!> { "" }
takeString(x)
}
fun test_2() {
val x = <!AMBIGUITY!>create<!> { 1 }
takeInt(x)
}
fun test_3() {
val x = <!AMBIGUITY!>create<!> { 1.0 }
}
fun <K> create(x: K, f: (K) -> Int): Int = 1
fun <T> create(x: T, f: (T) -> String): String = ""
fun test_4() {
val x = <!AMBIGUITY!>create<!>("") { "" }
takeString(x)
}
fun test_5() {
val x = <!AMBIGUITY!>create<!>("") { 1 }
takeInt(x)
}
@@ -0,0 +1,36 @@
// !LANGUAGE: +NewInference -FactoryPatternResolution
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_EXPRESSION
// ISSUE: KT-11265
fun create(f: (Int) -> Int): Int = 1
fun create(f: (Int) -> String): String = ""
fun takeString(s: String) {}
fun takeInt(s: Int) {}
fun test_1() {
val x = <!OVERLOAD_RESOLUTION_AMBIGUITY!>create<!> { "" }
takeString(<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>)
}
fun test_2() {
val x = <!OVERLOAD_RESOLUTION_AMBIGUITY!>create<!> { 1 }
takeInt(<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>)
}
fun test_3() {
val x = <!OVERLOAD_RESOLUTION_AMBIGUITY!>create<!> { 1.0 }
}
fun <K> create(x: K, f: (K) -> Int): Int = 1
fun <T> create(x: T, f: (T) -> String): String = ""
fun test_4() {
val x = <!OVERLOAD_RESOLUTION_AMBIGUITY!>create<!>("") { "" }
takeString(<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>)
}
fun test_5() {
val x = <!OVERLOAD_RESOLUTION_AMBIGUITY!>create<!>("") { 1 }
takeInt(<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>)
}
@@ -0,0 +1,13 @@
package
public fun create(/*0*/ f: (kotlin.Int) -> kotlin.Int): kotlin.Int
public fun create(/*0*/ f: (kotlin.Int) -> kotlin.String): kotlin.String
public fun </*0*/ K> create(/*0*/ x: K, /*1*/ f: (K) -> kotlin.Int): kotlin.Int
public fun </*0*/ T> create(/*0*/ x: T, /*1*/ f: (T) -> kotlin.String): kotlin.String
public fun takeInt(/*0*/ s: kotlin.Int): kotlin.Unit
public fun takeString(/*0*/ s: kotlin.String): kotlin.Unit
public fun test_1(): kotlin.Unit
public fun test_2(): kotlin.Unit
public fun test_3(): kotlin.Unit
public fun test_4(): kotlin.Unit
public fun test_5(): kotlin.Unit
@@ -0,0 +1,36 @@
// !LANGUAGE: +NewInference +FactoryPatternResolution
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_EXPRESSION
// ISSUE: KT-11265
fun create(f: (Int) -> Int): Int = 1
fun create(f: (Int) -> String): String = ""
fun takeString(s: String) {}
fun takeInt(s: Int) {}
fun test_1() {
val x = <!AMBIGUITY!>create<!> { "" }
takeString(x)
}
fun test_2() {
val x = <!AMBIGUITY!>create<!> { 1 }
takeInt(x)
}
fun test_3() {
val x = <!AMBIGUITY!>create<!> { 1.0 }
}
fun <K> create(x: K, f: (K) -> Int): Int = 1
fun <T> create(x: T, f: (T) -> String): String = ""
fun test_4() {
val x = <!AMBIGUITY!>create<!>("") { "" }
takeString(x)
}
fun test_5() {
val x = <!AMBIGUITY!>create<!>("") { 1 }
takeInt(x)
}
@@ -0,0 +1,36 @@
// !LANGUAGE: +NewInference +FactoryPatternResolution
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_EXPRESSION
// ISSUE: KT-11265
fun create(f: (Int) -> Int): Int = 1
fun create(f: (Int) -> String): String = ""
fun takeString(s: String) {}
fun takeInt(s: Int) {}
fun test_1() {
val x = create { "" }
takeString(x)
}
fun test_2() {
val x = create { 1 }
takeInt(x)
}
fun test_3() {
val x = <!NONE_APPLICABLE!>create<!> { 1.0 }
}
fun <K> create(x: K, f: (K) -> Int): Int = 1
fun <T> create(x: T, f: (T) -> String): String = ""
fun test_4() {
val x = create("") { "" }
takeString(x)
}
fun test_5() {
val x = create("") { 1 }
takeInt(x)
}
@@ -0,0 +1,13 @@
package
public fun create(/*0*/ f: (kotlin.Int) -> kotlin.Int): kotlin.Int
public fun create(/*0*/ f: (kotlin.Int) -> kotlin.String): kotlin.String
public fun </*0*/ K> create(/*0*/ x: K, /*1*/ f: (K) -> kotlin.Int): kotlin.Int
public fun </*0*/ T> create(/*0*/ x: T, /*1*/ f: (T) -> kotlin.String): kotlin.String
public fun takeInt(/*0*/ s: kotlin.Int): kotlin.Unit
public fun takeString(/*0*/ s: kotlin.String): kotlin.Unit
public fun test_1(): kotlin.Unit
public fun test_2(): kotlin.Unit
public fun test_3(): kotlin.Unit
public fun test_4(): kotlin.Unit
public fun test_5(): kotlin.Unit
@@ -2803,6 +2803,29 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/factoryPattern")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class FactoryPattern extends AbstractDiagnosticsTestWithStdLib {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInFactoryPattern() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/factoryPattern"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("overloadByLambdaReturnType_disabled.kt")
public void testOverloadByLambdaReturnType_disabled() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/factoryPattern/overloadByLambdaReturnType_disabled.kt");
}
@TestMetadata("overloadByLambdaReturnType_enabled.kt")
public void testOverloadByLambdaReturnType_enabled() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/factoryPattern/overloadByLambdaReturnType_enabled.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/forInArrayLoop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -2803,6 +2803,29 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/factoryPattern")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class FactoryPattern extends AbstractDiagnosticsTestWithStdLibUsingJavac {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInFactoryPattern() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/factoryPattern"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("overloadByLambdaReturnType_disabled.kt")
public void testOverloadByLambdaReturnType_disabled() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/factoryPattern/overloadByLambdaReturnType_disabled.kt");
}
@TestMetadata("overloadByLambdaReturnType_enabled.kt")
public void testOverloadByLambdaReturnType_enabled() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/factoryPattern/overloadByLambdaReturnType_enabled.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/forInArrayLoop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -153,6 +153,7 @@ enum class LanguageFeature(
FunctionReferenceWithDefaultValueAsOtherType(sinceVersion = KOTLIN_1_4),
NonStrictOnlyInputTypesChecks(sinceVersion = KOTLIN_1_4),
SuspendConversion(sinceVersion = KOTLIN_1_4, defaultState = State.DISABLED),
FactoryPatternResolution(sinceVersion = KOTLIN_1_4),
BooleanElvisBoundSmartCasts(sinceVersion = KOTLIN_1_3, defaultState = State.DISABLED), // see KT-26357 for details
NewDataFlowForTryExpressions(sinceVersion = KOTLIN_1_4, defaultState = State.DISABLED),
@@ -148,4 +148,17 @@ inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapToNullable(des
}
fun <E : Enum<E>> min(a: E, b: E): E = if (a < b) a else b
fun <E : Comparable<E>> min(a: E, b: E): E = if (a < b) a else b
fun <E : Comparable<E>> min(a: E, b: E): E = if (a < b) a else b
inline fun <T, R> Iterable<T>.same(extractor: (T) -> R): Boolean {
val iterator = iterator()
val firstValue = extractor(iterator.next())
while (iterator.hasNext()) {
val item = iterator.next()
val value = extractor(item)
if (value != firstValue) {
return false
}
}
return true
}