[NI] Add missing substitution of known type parameters
Known type parameters appear after inheriting from class with type parameters. Their substitution matters for inner class constructor, because without substitution it's parameters will be type checked against incorrect (original) parameter descriptor with unsubstituted type parameters. Skip creation of composite substitutor, if old substitutor is empty. New substitutors return null in case they don't substitute a type, but old type substitutors have explicit isEmpty method. Composite substitutor with empty old substitutor leads to creation of incorrect descriptor copies.
This commit is contained in:
+10
@@ -9823,6 +9823,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
|
||||
runTest("compiler/testData/diagnostics/tests/inference/invokeLambdaAsFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("knownTypeParameters.kt")
|
||||
public void testKnownTypeParameters() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/knownTypeParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt11963.kt")
|
||||
public void testKt11963() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt11963.kt");
|
||||
@@ -9858,6 +9863,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt3184.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt32415.kt")
|
||||
public void testKt32415() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt32415.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt32434.kt")
|
||||
public void testKt32434() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt32434.kt");
|
||||
|
||||
+8
-4
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.calls.context.CallPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.buildResultingSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.composeWith
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateTypes
|
||||
@@ -728,10 +729,13 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
}
|
||||
|
||||
private fun CallableDescriptor.substituteInferredVariablesAndApproximate(substitutor: NewTypeSubstitutor?): CallableDescriptor {
|
||||
return substitute(resolvedCallAtom.freshVariablesSubstitutor)
|
||||
.substituteAndApproximateTypes(
|
||||
substitutor ?: FreshVariableNewTypeSubstitutor.Empty, typeApproximator
|
||||
)
|
||||
val inferredTypeVariablesSubstitutor = substitutor ?: FreshVariableNewTypeSubstitutor.Empty
|
||||
|
||||
val compositeSubstitutor = resolvedCallAtom.freshVariablesSubstitutor
|
||||
.composeWith(resolvedCallAtom.knownParametersSubstitutor)
|
||||
.composeWith(inferredTypeVariablesSubstitutor)
|
||||
|
||||
return substituteAndApproximateTypes(compositeSubstitutor, typeApproximator)
|
||||
}
|
||||
|
||||
fun getExpectedTypeForSamConvertedArgument(valueArgument: ValueArgument): UnwrappedType? =
|
||||
|
||||
+4
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.InvokeConventionCallNoOperatorMo
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -124,6 +125,8 @@ internal object NoArguments : ResolutionPart() {
|
||||
|
||||
internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
|
||||
override fun KotlinResolutionCandidate.process(workIndex: Int) {
|
||||
resolvedCall.knownParametersSubstitutor = knownTypeParametersResultingSubstitutor ?: TypeSubstitutor.EMPTY
|
||||
|
||||
if (candidateDescriptor.typeParameters.isEmpty()) {
|
||||
resolvedCall.freshVariablesSubstitutor = FreshVariableNewTypeSubstitutor.Empty
|
||||
return
|
||||
@@ -415,6 +418,7 @@ internal object ErrorDescriptorResolutionPart : ResolutionPart() {
|
||||
resolvedCall.typeArgumentMappingByOriginal = TypeArgumentsToParametersMapper.TypeArgumentsMapping.NoExplicitArguments
|
||||
resolvedCall.argumentMappingByOriginal = emptyMap()
|
||||
resolvedCall.freshVariablesSubstitutor = FreshVariableNewTypeSubstitutor.Empty
|
||||
resolvedCall.knownParametersSubstitutor = TypeSubstitutor.EMPTY
|
||||
resolvedCall.argumentToCandidateParameter = emptyMap()
|
||||
|
||||
kotlinCall.explicitReceiver?.safeAs<SimpleKotlinCallArgument>()?.let {
|
||||
|
||||
+19
-4
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
|
||||
@@ -190,7 +190,22 @@ class FreshVariableNewTypeSubstitutor(val freshVariables: List<TypeVariableFromC
|
||||
}
|
||||
}
|
||||
|
||||
fun UnwrappedType.substituteTypeVariable(typeVariable: NewTypeVariable, value: UnwrappedType): UnwrappedType {
|
||||
val substitutor = NewTypeSubstitutorByConstructorMap(mapOf(typeVariable.freshTypeConstructor to value))
|
||||
return substitutor.safeSubstitute(this)
|
||||
fun createCompositeSubstitutor(appliedFirst: NewTypeSubstitutor, appliedLast: TypeSubstitutor): NewTypeSubstitutor {
|
||||
if (appliedLast.isEmpty) return appliedFirst
|
||||
|
||||
return object : NewTypeSubstitutor {
|
||||
override fun substituteNotNullTypeWithConstructor(constructor: TypeConstructor): UnwrappedType? {
|
||||
val substitutedOnce = appliedFirst.substituteNotNullTypeWithConstructor(constructor)
|
||||
|
||||
return if (substitutedOnce != null) {
|
||||
appliedLast.substitute(substitutedOnce.unwrap())
|
||||
} else {
|
||||
constructor.declarationDescriptor?.defaultType?.let {
|
||||
appliedLast.substitute(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun NewTypeSubstitutor.composeWith(appliedAfter: TypeSubstitutor) = createCompositeSubstitutor(this, appliedAfter)
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintError
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.typeUtil.unCapture
|
||||
@@ -64,7 +65,7 @@ abstract class ResolvedCallAtom : ResolvedAtom() {
|
||||
abstract val typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping
|
||||
abstract val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||
abstract val freshVariablesSubstitutor: FreshVariableNewTypeSubstitutor
|
||||
|
||||
abstract val knownParametersSubstitutor: TypeSubstitutor
|
||||
abstract val argumentsWithConversion: Map<KotlinCallArgument, SamConversionDescription>
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -179,6 +179,7 @@ class MutableResolvedCallAtom(
|
||||
override lateinit var typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping
|
||||
override lateinit var argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||
override lateinit var freshVariablesSubstitutor: FreshVariableNewTypeSubstitutor
|
||||
override lateinit var knownParametersSubstitutor: TypeSubstitutor
|
||||
lateinit var argumentToCandidateParameter: Map<KotlinCallArgument, ValueParameterDescriptor>
|
||||
private var samAdapterMap: HashMap<KotlinCallArgument, SamConversionDescription>? = null
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
|
||||
open class A<T1, T2> {
|
||||
open inner class A1(val a1: T1)
|
||||
open inner class A2(val a2: T2)
|
||||
|
||||
open fun f1(arg: T1) = arg
|
||||
open fun f2(arg: T2) = arg
|
||||
}
|
||||
|
||||
open class B<T> : A<T, Int>() {
|
||||
open inner class B1(b1: T) : A1(b1)
|
||||
open inner class B2(b2: Int) : A2(b2)
|
||||
|
||||
fun variableToKnownParameter(p: T): Int =
|
||||
p as? Int ?: 0
|
||||
|
||||
inner class B3(b3: T) : A2(variableToKnownParameter(b3))
|
||||
|
||||
override fun f1(arg: T) = arg
|
||||
override fun f2(arg: Int) = arg
|
||||
}
|
||||
|
||||
class C : B<String>() {
|
||||
inner class C1(c1: String): B1(c1)
|
||||
inner class C2 : B2(15)
|
||||
|
||||
override fun f1(arg: String) = arg
|
||||
override fun f2(arg: Int) = arg
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package
|
||||
|
||||
public open class A</*0*/ T1, /*1*/ T2> {
|
||||
public constructor A</*0*/ T1, /*1*/ T2>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun f1(/*0*/ arg: T1): T1
|
||||
public open fun f2(/*0*/ arg: T2): T2
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public open inner class A1 /*captured type parameters: /*0*/ T1, /*1*/ T2*/ {
|
||||
public constructor A1(/*0*/ a1: T1)
|
||||
public final val a1: T1
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open inner class A2 /*captured type parameters: /*0*/ T1, /*1*/ T2*/ {
|
||||
public constructor A2(/*0*/ a2: T2)
|
||||
public final val a2: T2
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
public open class B</*0*/ T> : A<T, kotlin.Int> {
|
||||
public constructor B</*0*/ T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ fun f1(/*0*/ arg: T): T
|
||||
public open override /*1*/ fun f2(/*0*/ arg: kotlin.Int): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
public final fun variableToKnownParameter(/*0*/ p: T): kotlin.Int
|
||||
|
||||
public open inner class B1 /*captured type parameters: /*0*/ T*/ : A<T, kotlin.Int>.A1 {
|
||||
public constructor B1(/*0*/ b1: T)
|
||||
public final override /*1*/ /*fake_override*/ val a1: T
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open inner class B2 /*captured type parameters: /*0*/ T*/ : A<T, kotlin.Int>.A2 {
|
||||
public constructor B2(/*0*/ b2: kotlin.Int)
|
||||
public final override /*1*/ /*fake_override*/ val a2: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final inner class B3 /*captured type parameters: /*0*/ T*/ : A<T, kotlin.Int>.A2 {
|
||||
public constructor B3(/*0*/ b3: T)
|
||||
public final override /*1*/ /*fake_override*/ val a2: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
public final class C : B<kotlin.String> {
|
||||
public constructor C()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ fun f1(/*0*/ arg: kotlin.String): kotlin.String
|
||||
public open override /*1*/ fun f2(/*0*/ arg: kotlin.Int): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ fun variableToKnownParameter(/*0*/ p: kotlin.String): kotlin.Int
|
||||
|
||||
public final inner class C1 : B<kotlin.String>.B1 {
|
||||
public constructor C1(/*0*/ c1: kotlin.String)
|
||||
public final override /*1*/ /*fake_override*/ val a1: kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final inner class C2 : B<kotlin.String>.B2 {
|
||||
public constructor C2()
|
||||
public final override /*1*/ /*fake_override*/ val a2: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
|
||||
abstract class TestType<V: Any> {
|
||||
open inner class Inner(val item: V)
|
||||
}
|
||||
|
||||
class Derived: TestType<Long>() {
|
||||
inner class DerivedInner(item: Long): Inner(item)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package
|
||||
|
||||
public final class Derived : TestType<kotlin.Long> {
|
||||
public constructor Derived()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public final inner class DerivedInner : TestType<kotlin.Long>.Inner {
|
||||
public constructor DerivedInner(/*0*/ item: kotlin.Long)
|
||||
public final override /*1*/ /*fake_override*/ val item: kotlin.Long
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class TestType</*0*/ V : kotlin.Any> {
|
||||
public constructor TestType</*0*/ V : kotlin.Any>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public open inner class Inner /*captured type parameters: /*0*/ V : kotlin.Any*/ {
|
||||
public constructor Inner(/*0*/ item: V)
|
||||
public final val item: V
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
@@ -9830,6 +9830,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/invokeLambdaAsFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("knownTypeParameters.kt")
|
||||
public void testKnownTypeParameters() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/knownTypeParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt11963.kt")
|
||||
public void testKt11963() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt11963.kt");
|
||||
@@ -9865,6 +9870,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt3184.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt32415.kt")
|
||||
public void testKt32415() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt32415.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt32434.kt")
|
||||
public void testKt32434() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt32434.kt");
|
||||
|
||||
Generated
+10
@@ -9825,6 +9825,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/inference/invokeLambdaAsFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("knownTypeParameters.kt")
|
||||
public void testKnownTypeParameters() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/knownTypeParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt11963.kt")
|
||||
public void testKt11963() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt11963.kt");
|
||||
@@ -9860,6 +9865,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt3184.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt32415.kt")
|
||||
public void testKt32415() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt32415.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt32434.kt")
|
||||
public void testKt32434() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt32434.kt");
|
||||
|
||||
Reference in New Issue
Block a user