diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirBuilderInferenceSession.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirBuilderInferenceSession.kt index 1f995e9b6d6..1a923125c2d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirBuilderInferenceSession.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirBuilderInferenceSession.kt @@ -5,14 +5,15 @@ package org.jetbrains.kotlin.fir.resolve.inference -import org.jetbrains.kotlin.fir.expressions.FirFunctionCall +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.expressions.FirArgumentList import org.jetbrains.kotlin.fir.expressions.FirResolvable import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.fir.visitors.transformSingle +import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind @@ -196,21 +197,16 @@ class FirBuilderInferenceSession( return introducedConstraint } + // TODO: besides calls, perhaps use the stub type substitutor for all top-level expressions inside the lambda private fun updateCalls(commonSystem: NewConstraintSystemImpl) { val nonFixedToVariablesSubstitutor = createNonFixedTypeToVariableSubstitutor() val commonSystemSubstitutor = commonSystem.buildCurrentSubstitutor() as ConeSubstitutor val nonFixedTypesToResultSubstitutor = ConeComposedSubstitutor(commonSystemSubstitutor, nonFixedToVariablesSubstitutor) val completionResultsWriter = components.callCompleter.createCompletionResultsWriter(nonFixedTypesToResultSubstitutor) + val stubTypeSubstitutor = FirStubTypeTransformer(nonFixedTypesToResultSubstitutor) for ((completedCall, _) in commonCalls) { - // TODO: Only update return type? Should we need to visit all appearances of unsubstituted postponed variables in types? - // [transformSingle] bails out very early since the completed call is literally completed, and not a named reference. - (completedCall as? FirFunctionCall)?.let { call -> - val resultType = call.typeRef.substituteTypeRef(nonFixedTypesToResultSubstitutor) - if (resultType != call.typeRef) { - call.replaceTypeRef(resultType) - } - } + completedCall.transformSingle(stubTypeSubstitutor, null) // TODO: support diagnostics, see [CoroutineInferenceSession#updateCalls] } @@ -219,15 +215,6 @@ class FirBuilderInferenceSession( // TODO: support diagnostics, see [CoroutineInferenceSession#updateCalls] } } - - private fun FirTypeRef.substituteTypeRef( - substitutor: ConeSubstitutor, - ): FirTypeRef = - (this as? FirResolvedTypeRef)?.let { - substitutor.substituteOrNull(this.type)?.let { - this.withReplacedConeType(it) - } - } ?: this } class ConeComposedSubstitutor(val left: ConeSubstitutor, val right: ConeSubstitutor) : ConeSubstitutor() { @@ -236,3 +223,21 @@ class ConeComposedSubstitutor(val left: ConeSubstitutor, val right: ConeSubstitu return left.substituteOrNull(rightSubstitution ?: type) } } + +class FirStubTypeTransformer( + private val substitutor: ConeSubstitutor +) : FirDefaultTransformer() { + + override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { + @Suppress("UNCHECKED_CAST") + return (element.transformChildren(this, data) as E).compose() + } + + override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: Nothing?): CompositeTransformResult = + substitutor.substituteOrNull(resolvedTypeRef.type)?.let { + resolvedTypeRef.withReplacedConeType(it).compose() + } ?: resolvedTypeRef.compose() + + override fun transformArgumentList(argumentList: FirArgumentList, data: Nothing?): CompositeTransformResult = + argumentList.transformArguments(this, data).compose() +} diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirResolvedArgumentList.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirResolvedArgumentList.kt index f3d8cefb5ba..caf5e50a2ce 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirResolvedArgumentList.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirResolvedArgumentList.kt @@ -7,12 +7,19 @@ package org.jetbrains.kotlin.fir.expressions.impl import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.expressions.FirAbstractArgumentList +import org.jetbrains.kotlin.fir.expressions.FirArgumentList import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.FirVisitor +import org.jetbrains.kotlin.fir.visitors.transformSingle class FirResolvedArgumentList internal constructor( - val mapping: LinkedHashMap + mapping: LinkedHashMap ) : FirAbstractArgumentList() { + + var mapping: LinkedHashMap = mapping + private set + override val arguments: List get() = mapping.keys.toList() @@ -21,4 +28,9 @@ class FirResolvedArgumentList internal constructor( argument.accept(visitor, data) } } + + override fun transformArguments(transformer: FirTransformer, data: D): FirArgumentList { + mapping = mapping.mapKeys { (k, _) -> k.transformSingle(transformer, data) } as LinkedHashMap + return this + } } diff --git a/compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt b/compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt index c0a0d42b12c..6dc61506d08 100644 --- a/compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt +++ b/compiler/testData/codegen/box/builderInference/lackOfNullCheckOnNullableInsideBuild.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +NewInference // WITH_RUNTIME -// IGNORE_BACKEND_FIR: JVM_IR // Issue: KT-36371 import kotlin.experimental.ExperimentalTypeInference diff --git a/compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt b/compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt index e719bf80692..c1aee44c2fe 100644 --- a/compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt +++ b/compiler/testData/codegen/box/builderInference/substituteStubTypeIntoCR.kt @@ -1,6 +1,5 @@ // DONT_TARGET_EXACT_BACKEND: WASM // WASM_MUTE_REASON: COROUTINES -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JVM_IR // IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: NATIVE diff --git a/compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt b/compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt index b4c5fea00ff..302659e526a 100644 --- a/compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt +++ b/compiler/testData/codegen/box/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // WITH_RUNTIME import kotlin.experimental.ExperimentalTypeInference diff --git a/compiler/testData/codegen/box/builderInference/substituteTypeVariableIntolambdaParameterDescriptor.kt b/compiler/testData/codegen/box/builderInference/substituteTypeVariableIntolambdaParameterDescriptor.kt index bd4304c16c5..36c7836fc25 100644 --- a/compiler/testData/codegen/box/builderInference/substituteTypeVariableIntolambdaParameterDescriptor.kt +++ b/compiler/testData/codegen/box/builderInference/substituteTypeVariableIntolambdaParameterDescriptor.kt @@ -1,5 +1,4 @@ // TARGET_BACKEND: JVM -// IGNORE_BACKEND_FIR: JVM_IR // WITH_RUNTIME class Foo diff --git a/compiler/testData/ir/irText/firProblems/typeVariableAfterBuildMap.fir.txt b/compiler/testData/ir/irText/firProblems/typeVariableAfterBuildMap.fir.txt index 58910843129..102f6689c32 100644 --- a/compiler/testData/ir/irText/firProblems/typeVariableAfterBuildMap.fir.txt +++ b/compiler/testData/ir/irText/firProblems/typeVariableAfterBuildMap.fir.txt @@ -554,28 +554,28 @@ FILE fqName: fileName:/typeVariableAfterBuildMap.kt BLOCK_BODY TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit CALL 'public abstract fun put (key: K of kotlin.collections.MutableMap, value: V of kotlin.collections.MutableMap): V of kotlin.collections.MutableMap? declared in kotlin.collections.MutableMap' type=kotlin.Int? origin=null - $this: GET_VAR ': kotlin.collections.MutableMap<.Visibility, kotlin.Int> declared in .Visibilities.ORDERED_VISIBILITIES.' type=kotlin.collections.MutableMap origin=null + $this: GET_VAR ': kotlin.collections.MutableMap<.Visibility, kotlin.Int> declared in .Visibilities.ORDERED_VISIBILITIES.' type=kotlin.collections.MutableMap<.Visibility, kotlin.Int> origin=null key: GET_OBJECT 'CLASS OBJECT name:PrivateToThis modality:FINAL visibility:public superTypes:[.Visibility]' type=.Visibilities.PrivateToThis value: CONST Int type=kotlin.Int value=0 TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit CALL 'public abstract fun put (key: K of kotlin.collections.MutableMap, value: V of kotlin.collections.MutableMap): V of kotlin.collections.MutableMap? declared in kotlin.collections.MutableMap' type=kotlin.Int? origin=null - $this: GET_VAR ': kotlin.collections.MutableMap<.Visibility, kotlin.Int> declared in .Visibilities.ORDERED_VISIBILITIES.' type=kotlin.collections.MutableMap origin=null + $this: GET_VAR ': kotlin.collections.MutableMap<.Visibility, kotlin.Int> declared in .Visibilities.ORDERED_VISIBILITIES.' type=kotlin.collections.MutableMap<.Visibility, kotlin.Int> origin=null key: GET_OBJECT 'CLASS OBJECT name:Private modality:FINAL visibility:public superTypes:[.Visibility]' type=.Visibilities.Private value: CONST Int type=kotlin.Int value=0 TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit CALL 'public abstract fun put (key: K of kotlin.collections.MutableMap, value: V of kotlin.collections.MutableMap): V of kotlin.collections.MutableMap? declared in kotlin.collections.MutableMap' type=kotlin.Int? origin=null - $this: GET_VAR ': kotlin.collections.MutableMap<.Visibility, kotlin.Int> declared in .Visibilities.ORDERED_VISIBILITIES.' type=kotlin.collections.MutableMap origin=null + $this: GET_VAR ': kotlin.collections.MutableMap<.Visibility, kotlin.Int> declared in .Visibilities.ORDERED_VISIBILITIES.' type=kotlin.collections.MutableMap<.Visibility, kotlin.Int> origin=null key: GET_OBJECT 'CLASS OBJECT name:Internal modality:FINAL visibility:public superTypes:[.Visibility]' type=.Visibilities.Internal value: CONST Int type=kotlin.Int value=1 TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit CALL 'public abstract fun put (key: K of kotlin.collections.MutableMap, value: V of kotlin.collections.MutableMap): V of kotlin.collections.MutableMap? declared in kotlin.collections.MutableMap' type=kotlin.Int? origin=null - $this: GET_VAR ': kotlin.collections.MutableMap<.Visibility, kotlin.Int> declared in .Visibilities.ORDERED_VISIBILITIES.' type=kotlin.collections.MutableMap origin=null + $this: GET_VAR ': kotlin.collections.MutableMap<.Visibility, kotlin.Int> declared in .Visibilities.ORDERED_VISIBILITIES.' type=kotlin.collections.MutableMap<.Visibility, kotlin.Int> origin=null key: GET_OBJECT 'CLASS OBJECT name:Protected modality:FINAL visibility:public superTypes:[.Visibility]' type=.Visibilities.Protected value: CONST Int type=kotlin.Int value=1 RETURN type=kotlin.Nothing from='local final fun (): kotlin.Unit declared in .Visibilities.ORDERED_VISIBILITIES' TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit CALL 'public abstract fun put (key: K of kotlin.collections.MutableMap, value: V of kotlin.collections.MutableMap): V of kotlin.collections.MutableMap? declared in kotlin.collections.MutableMap' type=kotlin.Int? origin=null - $this: GET_VAR ': kotlin.collections.MutableMap<.Visibility, kotlin.Int> declared in .Visibilities.ORDERED_VISIBILITIES.' type=kotlin.collections.MutableMap origin=null + $this: GET_VAR ': kotlin.collections.MutableMap<.Visibility, kotlin.Int> declared in .Visibilities.ORDERED_VISIBILITIES.' type=kotlin.collections.MutableMap<.Visibility, kotlin.Int> origin=null key: GET_OBJECT 'CLASS OBJECT name:Public modality:FINAL visibility:public superTypes:[.Visibility]' type=.Visibilities.Public value: CONST Int type=kotlin.Int value=2 FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:private modality:FINAL <> ($this:.Visibilities) returnType:kotlin.collections.Map<.Visibility, kotlin.Int> diff --git a/compiler/testData/ir/irText/types/castsInsideCoroutineInference.fir.txt b/compiler/testData/ir/irText/types/castsInsideCoroutineInference.fir.txt index a804528e851..bc4273f3b70 100644 --- a/compiler/testData/ir/irText/types/castsInsideCoroutineInference.fir.txt +++ b/compiler/testData/ir/irText/types/castsInsideCoroutineInference.fir.txt @@ -25,7 +25,8 @@ FILE fqName: fileName:/castsInsideCoroutineInference.kt CALL 'public abstract fun invoke (p1: P1 of kotlin.coroutines.SuspendFunction2, p2: P2 of kotlin.coroutines.SuspendFunction2): R of kotlin.coroutines.SuspendFunction2 [suspend,operator] declared in kotlin.coroutines.SuspendFunction2' type=kotlin.Unit origin=null $this: GET_VAR 'block: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<.CoroutineScope, .FlowCollector.scopedFlow>, kotlin.Unit> declared in .scopedFlow' type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<.CoroutineScope, .FlowCollector.scopedFlow>, kotlin.Unit> origin=VARIABLE_AS_FUNCTION p1: GET_VAR ': .CoroutineScope declared in .scopedFlow..' type=.CoroutineScope origin=null - p2: GET_VAR 'val collector: .FlowCollector [val] declared in .scopedFlow.' type=.FlowCollector origin=null + p2: TYPE_OP type=.FlowCollector origin=IMPLICIT_CAST typeOperand=.FlowCollector + GET_VAR 'val collector: .FlowCollector [val] declared in .scopedFlow.' type=.FlowCollector.scopedFlow> origin=null FUN name:onCompletion visibility:public modality:FINAL ($receiver:.Flow.onCompletion>, action:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<.FlowCollector.onCompletion>, kotlin.Throwable?, kotlin.Unit>) returnType:.Flow.onCompletion> TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] $receiver: VALUE_PARAMETER name: type:.Flow.onCompletion> @@ -40,11 +41,11 @@ FILE fqName: fileName:/castsInsideCoroutineInference.kt BLOCK_BODY VAR name:safeCollector type:.SafeCollector [val] CONSTRUCTOR_CALL 'public constructor (collector: .FlowCollector.SafeCollector>) [primary] declared in .SafeCollector' type=.SafeCollector.onCompletion> origin=null - : IrErrorType - collector: GET_VAR ': .FlowCollector.onCompletion> declared in .onCompletion.' type=.FlowCollector origin=null + : T of .onCompletion + collector: GET_VAR ': .FlowCollector.onCompletion> declared in .onCompletion.' type=.FlowCollector.onCompletion> origin=null CALL 'public final fun invokeSafely (action: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<.FlowCollector.invokeSafely>, kotlin.Throwable?, kotlin.Unit>): kotlin.Unit [suspend] declared in ' type=kotlin.Unit origin=null : T of .onCompletion - $receiver: GET_VAR 'val safeCollector: .SafeCollector [val] declared in .onCompletion.' type=.SafeCollector origin=null + $receiver: GET_VAR 'val safeCollector: .SafeCollector [val] declared in .onCompletion.' type=.SafeCollector.onCompletion> origin=null action: GET_VAR 'action: @[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<.FlowCollector.onCompletion>, kotlin.Throwable?, kotlin.Unit> declared in .onCompletion' type=@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<.FlowCollector.onCompletion>, kotlin.Throwable?, kotlin.Unit> origin=null FUN name:invokeSafely visibility:public modality:FINAL ($receiver:.FlowCollector.invokeSafely>, action:@[ExtensionFunctionType] @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<.FlowCollector.invokeSafely>, kotlin.Throwable?, kotlin.Unit>) returnType:kotlin.Unit [suspend] TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] @@ -136,8 +137,8 @@ FILE fqName: fileName:/castsInsideCoroutineInference.kt BLOCK_BODY RETURN type=kotlin.Nothing from='local final fun (value: kotlin.Any?): kotlin.Unit [suspend] declared in .asChannel.' CALL 'public abstract fun send (e: E of .SendChannel): kotlin.Unit [suspend] declared in .SendChannel' type=kotlin.Unit origin=null - $this: CALL 'public abstract fun (): .SendChannel.ProducerScope> declared in .ProducerScope' type=.SendChannel origin=GET_PROPERTY - $this: GET_VAR ': .ProducerScope declared in .asChannel.' type=.ProducerScope origin=null + $this: CALL 'public abstract fun (): .SendChannel.ProducerScope> declared in .ProducerScope' type=.SendChannel origin=GET_PROPERTY + $this: GET_VAR ': .ProducerScope declared in .asChannel.' type=.ProducerScope origin=null e: BLOCK type=kotlin.Any origin=ELVIS VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Any? [val] GET_VAR 'value: kotlin.Any? declared in .asChannel..' type=kotlin.Any? origin=null