From 4f834cb16b462965f6ff7cffb08ec1bd472ea14a Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 4 Feb 2020 16:23:29 +0300 Subject: [PATCH] FIR: Get rid of replacements map during calls completion Otherwise, it's complicated to work with nested lambdas: outer/inner ones may be replaced independently and still refer to the old one instances. So in the changed test, if we don't apply the commit, will remain implicit return and receiver types for the nested lambda Anyway, once we decided to leave immutable semantics, replacements are not necessary anymore --- .../calls/PostponedArgumentsAnalyzer.kt | 3 -- .../fir/resolve/inference/FirCallCompleter.kt | 44 ++++++++--------- .../testData/resolve/cfg/postponedLambdas.txt | 4 +- .../resolve/inference/nestedLambdas.kt | 2 +- .../resolve/inference/nestedLambdas.txt | 2 +- .../functionExpression/insideGenericLambda.kt | 1 - .../samConversionInVarargs.fir.txt | 48 +++++++++---------- 7 files changed, 47 insertions(+), 57 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArgumentsAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArgumentsAnalyzer.kt index bce310a4013..eac6efab7d2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArgumentsAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArgumentsAnalyzer.kt @@ -40,7 +40,6 @@ class PostponedArgumentsAnalyzer( private val lambdaAnalyzer: LambdaAnalyzer, private val components: InferenceComponents, private val candidate: Candidate, - private val replacements: MutableMap, private val callResolver: FirCallResolver ) { @@ -94,8 +93,6 @@ class PostponedArgumentsAnalyzer( replaceTypeRef(FirResolvedTypeRefImpl(null, candidate.resultingTypeForCallableReference!!)) } } - - replacements[callableReferenceAccess] = transformedCalleeReference } private fun analyzeLambda( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt index 87503ed28be..6badbcc363d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.fir.resolve.inference -import org.jetbrains.kotlin.fir.copy import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.fir.expressions.FirExpression @@ -16,8 +15,8 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor -import org.jetbrains.kotlin.fir.resolve.transformers.* -import org.jetbrains.kotlin.fir.resolve.transformers.MapArguments +import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer +import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType @@ -75,11 +74,10 @@ class FirCallCompleter( } val completionMode = candidate.computeCompletionMode(inferenceComponents, expectedTypeRef, initialType) - val replacements = mutableMapOf() val analyzer = PostponedArgumentsAnalyzer( - LambdaAnalyzerImpl(replacements), inferenceComponents, candidate, replacements, + LambdaAnalyzerImpl(), inferenceComponents, candidate, transformer.components.callResolver ) @@ -88,8 +86,6 @@ class FirCallCompleter( analyzer.analyze(candidate.system.asPostponedArgumentsAnalyzerContext(), it) } - call.transformChildren(MapArguments, replacements.toMap()) - if (completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL) { val finalSubstitutor = candidate.system.asReadOnlyStorage().buildAbstractResultingSubstitutor(inferenceComponents.ctx) as ConeSubstitutor @@ -106,9 +102,7 @@ class FirCallCompleter( return call.transformSingle(integerOperatorsTypeUpdater, null) } - private inner class LambdaAnalyzerImpl( - val replacements: MutableMap - ) : LambdaAnalyzer { + private inner class LambdaAnalyzerImpl : LambdaAnalyzer { override fun analyzeAndGetLambdaReturnArguments( lambdaArgument: FirAnonymousFunction, isSuspend: Boolean, @@ -142,24 +136,24 @@ class FirCallCompleter( val expectedReturnTypeRef = expectedReturnType?.let { lambdaArgument.returnTypeRef.resolvedTypeFromPrototype(it) } - val newLambdaExpression = lambdaArgument.copy( - receiverTypeRef = receiverType?.let { - lambdaArgument.receiverTypeRef?.resolvedTypeFromPrototype(it.approximateLambdaInputType()) - }, - valueParameters = lambdaArgument.valueParameters.mapIndexed { index, parameter -> - parameter.transformReturnTypeRef( - StoreType, - parameter.returnTypeRef.resolvedTypeFromPrototype(parameters[index].approximateLambdaInputType()) - ) - parameter - } + listOfNotNull(itParam), - returnTypeRef = expectedReturnTypeRef ?: noExpectedType + lambdaArgument.replaceReceiverTypeRef( + receiverType?.approximateLambdaInputType()?.let { + lambdaArgument.receiverTypeRef?.resolvedTypeFromPrototype(it) + } ) - replacements[lambdaArgument] = - newLambdaExpression.transformSingle(transformer, ResolutionMode.LambdaResolution(expectedReturnTypeRef)) + lambdaArgument.valueParameters.forEachIndexed { index, parameter -> + parameter.replaceReturnTypeRef( + parameter.returnTypeRef.resolvedTypeFromPrototype(parameters[index].approximateLambdaInputType()) + ) + } - val returnArguments = dataFlowAnalyzer.returnExpressionsOfAnonymousFunction(newLambdaExpression) + lambdaArgument.replaceValueParameters(lambdaArgument.valueParameters + listOfNotNull(itParam)) + lambdaArgument.replaceReturnTypeRef(expectedReturnTypeRef ?: noExpectedType) + + lambdaArgument.transformSingle(transformer, ResolutionMode.LambdaResolution(expectedReturnTypeRef)) + + val returnArguments = dataFlowAnalyzer.returnExpressionsOfAnonymousFunction(lambdaArgument) return returnArguments to InferenceSession.default } } diff --git a/compiler/fir/resolve/testData/resolve/cfg/postponedLambdas.txt b/compiler/fir/resolve/testData/resolve/cfg/postponedLambdas.txt index 74cadd80d45..f3c5aac694f 100644 --- a/compiler/fir/resolve/testData/resolve/cfg/postponedLambdas.txt +++ b/compiler/fir/resolve/testData/resolve/cfg/postponedLambdas.txt @@ -2,8 +2,8 @@ FILE: postponedLambdas.kt public final inline fun foo(vararg x: R|kotlin/Array|): R|kotlin/Unit| { } public final fun test(a: R|kotlin/Any|, b: R|kotlin/Any|, c: R|kotlin/Any|): R|kotlin/Unit| { - R|/foo|(vararg(R|/a|, R|/b|), foo@fun (): R|kotlin/String| { + R|/foo|(vararg(R|/a|, foo@fun (): R|kotlin/String| { String() } - ) + , R|/b|)) } diff --git a/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.kt b/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.kt index ad82790b423..7150e1fa7d1 100644 --- a/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.kt +++ b/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.kt @@ -8,7 +8,7 @@ interface MyMap { val w: Inv = TODO() -public fun Inv.associateBy1(keySelector: (X) -> K): MyMap = TODO() +public fun Inv.associateBy1(keySelector: (X) -> K): MyMap = TODO() val x = myRun { w.associateBy1 { f -> f.length } diff --git a/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.txt b/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.txt index bd313b4538d..b707158b645 100644 --- a/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.txt +++ b/compiler/fir/resolve/testData/resolve/inference/nestedLambdas.txt @@ -14,7 +14,7 @@ FILE: nestedLambdas.kt } public final val w: R|Inv| = R|kotlin/TODO|() public get(): R|Inv| - public final fun R|Inv|.associateBy1(keySelector: R|(X) -> K|): R|MyMap| { + public final fun R|Inv|.associateBy1(keySelector: R|(X) -> K|): R|MyMap| { ^associateBy1 R|kotlin/TODO|() } public final val x: R|MyMap| = R|/myRun||>( = myRun@fun (): R|MyMap| { diff --git a/compiler/testData/codegen/box/functions/functionExpression/insideGenericLambda.kt b/compiler/testData/codegen/box/functions/functionExpression/insideGenericLambda.kt index 8de98310966..b1cc8d2e895 100644 --- a/compiler/testData/codegen/box/functions/functionExpression/insideGenericLambda.kt +++ b/compiler/testData/codegen/box/functions/functionExpression/insideGenericLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun block(block: () -> T): T = block() fun foo() {} diff --git a/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.txt b/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.txt index 5234f4673c7..9c98efc9e6f 100644 --- a/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.txt +++ b/compiler/testData/ir/irText/expressions/funInterface/samConversionInVarargs.fir.txt @@ -22,32 +22,32 @@ FILE fqName: fileName:/samConversionInVarargs.kt BLOCK_BODY FUN name:testLambda visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY - ERROR_CALL 'Cannot bind 2 arguments to useVararg call with 1 parameters' type=kotlin.Unit - FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Unit - VALUE_PARAMETER name:it index:0 type:kotlin.Int - BLOCK_BODY - GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit - VARARG type=kotlin.Array<.IFoo> varargElementType=.IFoo + CALL 'public final fun useVararg (vararg foos: .IFoo): kotlin.Unit declared in ' type=kotlin.Unit origin=null + foos: VARARG type=kotlin.Array<.IFoo> varargElementType=.IFoo + FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Unit + VALUE_PARAMETER name:it index:0 type:kotlin.Int + BLOCK_BODY + GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit FUN name:testSeveralLambdas visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY - ERROR_CALL 'Cannot bind 4 arguments to useVararg call with 1 parameters' type=kotlin.Unit - FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Unit - VALUE_PARAMETER name:it index:0 type:kotlin.Int - BLOCK_BODY - GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit - FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Unit - VALUE_PARAMETER name:it index:0 type:kotlin.Int - BLOCK_BODY - GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit - FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Unit - VALUE_PARAMETER name:it index:0 type:kotlin.Int - BLOCK_BODY - GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit - VARARG type=kotlin.Array<.IFoo> varargElementType=.IFoo + CALL 'public final fun useVararg (vararg foos: .IFoo): kotlin.Unit declared in ' type=kotlin.Unit origin=null + foos: VARARG type=kotlin.Array<.IFoo> varargElementType=.IFoo + FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Unit + VALUE_PARAMETER name:it index:0 type:kotlin.Int + BLOCK_BODY + GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit + FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Unit + VALUE_PARAMETER name:it index:0 type:kotlin.Int + BLOCK_BODY + GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit + FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Unit + VALUE_PARAMETER name:it index:0 type:kotlin.Int + BLOCK_BODY + GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit FUN name:withVarargOfInt visibility:public modality:FINAL <> (xs:kotlin.IntArray) returnType:kotlin.String VALUE_PARAMETER name:xs index:0 type:kotlin.IntArray varargElementType:kotlin.Int [vararg] BLOCK_BODY