[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:
Pavel Kirpichenkov
2019-11-08 12:47:54 +03:00
parent 3122f2704c
commit b6af13f18d
12 changed files with 220 additions and 9 deletions
@@ -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");
@@ -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? =
@@ -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 {
@@ -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>
}
@@ -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");
@@ -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");