[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
@@ -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