[NI] Implement NewTypeSubstitutor
This commit is contained in:
+8
-8
@@ -21,19 +21,19 @@ import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.FixationOrderCalculator
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.LambdaTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NotEnoughInformationForTypeParameter
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.returnTypeOrNothing
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateStatus
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
@@ -45,8 +45,8 @@ class KotlinCallCompleter(
|
||||
interface Context {
|
||||
val innerCalls: List<ResolvedKotlinCall.OnlyResolvedKotlinCall>
|
||||
val hasContradiction: Boolean
|
||||
fun buildCurrentSubstitutor(): TypeSubstitutor
|
||||
fun buildResultingSubstitutor(): TypeSubstitutor
|
||||
fun buildCurrentSubstitutor(): NewTypeSubstitutor
|
||||
fun buildResultingSubstitutor(): NewTypeSubstitutor
|
||||
val lambdaArguments: List<ResolvedLambdaArgument>
|
||||
|
||||
// type can be proper if it not contains not fixed type variables
|
||||
@@ -100,7 +100,7 @@ class KotlinCallCompleter(
|
||||
return ResolvedKotlinCall.CompletedResolvedKotlinCall(completedCall, competedCalls)
|
||||
}
|
||||
|
||||
private fun KotlinResolutionCandidate.toCompletedCall(substitutor: TypeSubstitutor): CompletedKotlinCall {
|
||||
private fun KotlinResolutionCandidate.toCompletedCall(substitutor: NewTypeSubstitutor): CompletedKotlinCall {
|
||||
if (this is VariableAsFunctionKotlinResolutionCandidate) {
|
||||
val variable = resolvedVariable.toCompletedCall(substitutor)
|
||||
val invoke = invokeCandidate.toCompletedCall(substitutor)
|
||||
@@ -110,10 +110,10 @@ class KotlinCallCompleter(
|
||||
return (this as SimpleKotlinResolutionCandidate).toCompletedCall(substitutor)
|
||||
}
|
||||
|
||||
private fun SimpleKotlinResolutionCandidate.toCompletedCall(substitutor: TypeSubstitutor): CompletedKotlinCall.Simple {
|
||||
private fun SimpleKotlinResolutionCandidate.toCompletedCall(substitutor: NewTypeSubstitutor): CompletedKotlinCall.Simple {
|
||||
val resultingDescriptor = if (descriptorWithFreshTypes.typeParameters.isNotEmpty()) descriptorWithFreshTypes.substitute(substitutor)!! else descriptorWithFreshTypes
|
||||
|
||||
val typeArguments = descriptorWithFreshTypes.typeParameters.map { substitutor.safeSubstitute(it.defaultType, Variance.INVARIANT).unwrap() }
|
||||
val typeArguments = descriptorWithFreshTypes.typeParameters.map { substitutor.safeSubstitute(it.defaultType) }
|
||||
|
||||
val status = computeStatus(this, resultingDescriptor)
|
||||
return CompletedKotlinCall.Simple(kotlinCall, candidateDescriptor, resultingDescriptor, status, explicitReceiverKind,
|
||||
@@ -226,7 +226,7 @@ class KotlinCallCompleter(
|
||||
|
||||
private fun analyzeLambda(c: Context, lambdaAnalyzer: LambdaAnalyzer, topLevelCallContext: KotlinCallContext, topLevelCall: KotlinCall, lambda: ResolvedLambdaArgument) {
|
||||
val currentSubstitutor = c.buildCurrentSubstitutor()
|
||||
fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type, Variance.INVARIANT).unwrap()
|
||||
fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type)
|
||||
|
||||
val receiver = lambda.receiver?.let(::substitute)
|
||||
val parameters = lambda.parameters.map(::substitute)
|
||||
|
||||
+2
-1
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMa
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.DeclaredUpperBoundConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ExplicitTypeParameterConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||
@@ -164,7 +165,7 @@ internal object CreteDescriptorWithFreshTypeVariables : ResolutionPart {
|
||||
*/
|
||||
val toFixedTypeParameters = csBuilder.simplify()
|
||||
// todo optimize -- composite substitutions before run safeSubstitute
|
||||
descriptorWithFreshTypes = candidateDescriptor.safeSubstitute(toFreshVariables).safeSubstitute(toFixedTypeParameters)
|
||||
descriptorWithFreshTypes = candidateDescriptor.substitute(toFreshVariables)!!.substitute(toFixedTypeParameters)!!
|
||||
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
+2
-2
@@ -16,11 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
|
||||
@@ -43,5 +43,5 @@ interface ConstraintSystemBuilder {
|
||||
* This function removes variables for which we know exact type.
|
||||
* @return substitutor from typeVariable to result
|
||||
*/
|
||||
fun simplify(): TypeSubstitutor
|
||||
fun simplify(): NewTypeSubstitutor
|
||||
}
|
||||
|
||||
+14
-8
@@ -17,17 +17,15 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.inference
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.*
|
||||
|
||||
fun ConstraintStorage.buildCurrentSubstitutor() = TypeConstructorSubstitution.createByConstructorsMap(fixedTypeVariables.entries.associate {
|
||||
it.key to it.value.asTypeProjection()
|
||||
}).buildSubstitutor()
|
||||
fun ConstraintStorage.buildCurrentSubstitutor() = NewTypeSubstitutorByConstructorMap(fixedTypeVariables.entries.associate {
|
||||
it.key to it.value
|
||||
})
|
||||
|
||||
val CallableDescriptor.returnTypeOrNothing: UnwrappedType
|
||||
get() {
|
||||
@@ -38,3 +36,11 @@ val CallableDescriptor.returnTypeOrNothing: UnwrappedType
|
||||
|
||||
fun TypeSubstitutor.substitute(type: UnwrappedType): UnwrappedType = safeSubstitute(type, Variance.INVARIANT).unwrap()
|
||||
|
||||
fun CallableDescriptor.substitute(substitutor: NewTypeSubstitutor): CallableDescriptor? {
|
||||
val wrappedSubstitution = object : TypeSubstitution() {
|
||||
override fun get(key: KotlinType): TypeProjection? = null
|
||||
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = substitutor.safeSubstitute(topLevelType.unwrap())
|
||||
}
|
||||
return substitute(TypeSubstitutor.create(wrappedSubstitution))
|
||||
}
|
||||
|
||||
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
|
||||
import org.jetbrains.kotlin.types.checker.intersectTypes
|
||||
|
||||
interface NewTypeSubstitutor {
|
||||
fun substituteNotNullTypeWithConstructor(constructor: TypeConstructor): UnwrappedType?
|
||||
val isEmpty: Boolean
|
||||
|
||||
fun safeSubstitute(type: UnwrappedType): UnwrappedType = substitute(type) ?: type
|
||||
|
||||
// null means that this type isn't changed
|
||||
fun substitute(type: UnwrappedType): UnwrappedType? =
|
||||
when (type) {
|
||||
is SimpleType -> substitute(type)
|
||||
is FlexibleType -> if (type is DynamicType || type is RawType) {
|
||||
null
|
||||
}
|
||||
else {
|
||||
val lowerBound = substitute(type.lowerBound)
|
||||
val upperBound = substitute(type.upperBound)
|
||||
if (lowerBound == null && upperBound == null) {
|
||||
null
|
||||
}
|
||||
else {
|
||||
// todo discuss lowerIfFlexible and upperIfFlexible
|
||||
FlexibleTypeImpl(lowerBound?.lowerIfFlexible() ?: type.lowerBound, upperBound?.upperIfFlexible() ?: type.upperBound)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun substitute(type: SimpleType): UnwrappedType? {
|
||||
if (type.isError) return null
|
||||
|
||||
if (type.arguments.isNotEmpty()) {
|
||||
return substituteParametrizedType(type)
|
||||
}
|
||||
|
||||
val typeConstructor = type.constructor
|
||||
|
||||
if (typeConstructor is NewCapturedTypeConstructor) {
|
||||
assert(type is NewCapturedType) { // KT-16147
|
||||
"Type is inconsistent -- somewhere we create type with typeConstructor = $typeConstructor " +
|
||||
"and class: ${type::class.java.canonicalName}. type.toString() = $type"
|
||||
}
|
||||
val lower = (type as NewCapturedType).lowerType?.let { substitute(it) }
|
||||
if (lower != null) throw IllegalStateException("Illegal type substitutor: $this, " +
|
||||
"because for captured type '$type' lower type approximation should be null, but it is: '$lower'," +
|
||||
"original lower type: '${type.lowerType}")
|
||||
|
||||
type.constructor.supertypes.forEach { supertype ->
|
||||
substitute(supertype)?.let {
|
||||
throw IllegalStateException("Illegal type substitutor: $this, " +
|
||||
"because for captured type '$type' supertype approximation should be null, but it is: '$supertype'," +
|
||||
"original supertype: '$supertype'")
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
if (typeConstructor is IntersectionTypeConstructor) {
|
||||
var thereIsChanges = false
|
||||
val newTypes = typeConstructor.supertypes.map {
|
||||
substitute(it.unwrap())?.apply { thereIsChanges = true } ?: it.unwrap()
|
||||
}
|
||||
if (!thereIsChanges) return null
|
||||
return intersectTypes(newTypes).let { if (type.isMarkedNullable) it.makeNullableAsSpecified(true) else it }
|
||||
}
|
||||
|
||||
// simple classifier type
|
||||
val replacement = substituteNotNullTypeWithConstructor(typeConstructor) ?: return null
|
||||
|
||||
return if (type.isMarkedNullable) replacement.makeNullableAsSpecified(true) else replacement
|
||||
}
|
||||
|
||||
private fun substituteParametrizedType(type: SimpleType): UnwrappedType? {
|
||||
val parameters = type.constructor.parameters
|
||||
val arguments = type.arguments
|
||||
if (parameters.size != arguments.size) {
|
||||
// todo error type or exception?
|
||||
return ErrorUtils.createErrorType("Inconsistent type: $type (parameters.size = ${parameters.size}, arguments.size = ${arguments.size})")
|
||||
}
|
||||
val newArguments = arrayOfNulls<TypeProjection?>(arguments.size)
|
||||
|
||||
for (index in arguments.indices) {
|
||||
val argument = arguments[index]
|
||||
|
||||
if (argument.isStarProjection) continue
|
||||
val substitutedArgumentType = substitute(argument.type.unwrap()) ?: continue
|
||||
|
||||
newArguments[index] = TypeProjectionImpl(argument.projectionKind, substitutedArgumentType)
|
||||
}
|
||||
|
||||
if (newArguments.all { it == null }) return null
|
||||
|
||||
val newArgumentsList = arguments.mapIndexed { index, oldArgument -> newArguments[index] ?: oldArgument }
|
||||
return type.replace(newArgumentsList)
|
||||
}
|
||||
}
|
||||
|
||||
class NewTypeSubstitutorByConstructorMap(val map: Map<TypeConstructor, UnwrappedType>) : NewTypeSubstitutor {
|
||||
override val isEmpty get() = map.isEmpty()
|
||||
override fun substituteNotNullTypeWithConstructor(constructor: TypeConstructor): UnwrappedType? = map[constructor]
|
||||
}
|
||||
+10
-11
@@ -20,15 +20,14 @@ import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.buildCurrentSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.FixationOrderCalculator
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import java.util.*
|
||||
|
||||
@@ -125,7 +124,7 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
|
||||
return fixedVariables
|
||||
}
|
||||
|
||||
override fun simplify(): TypeSubstitutor {
|
||||
override fun simplify(): NewTypeSubstitutor {
|
||||
checkState(State.BUILDING)
|
||||
|
||||
var fixedVariables = getVariablesForFixation()
|
||||
@@ -235,20 +234,20 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
|
||||
return !type.contains { storage.notFixedTypeVariables.containsKey(it.constructor) }
|
||||
}
|
||||
|
||||
override fun buildCurrentSubstitutor(): TypeSubstitutor {
|
||||
override fun buildCurrentSubstitutor(): NewTypeSubstitutor {
|
||||
checkState(State.COMPLETION)
|
||||
return storage.buildCurrentSubstitutor()
|
||||
}
|
||||
|
||||
override fun buildResultingSubstitutor(): TypeSubstitutor {
|
||||
override fun buildResultingSubstitutor(): NewTypeSubstitutor {
|
||||
checkState(State.COMPLETION)
|
||||
val currentSubstitutorMap = storage.fixedTypeVariables.entries.associate {
|
||||
it.key to it.value.asTypeProjection()
|
||||
it.key to it.value
|
||||
}
|
||||
val uninferredSubstitutorMap = storage.notFixedTypeVariables.entries.associate { (freshTypeConstructor, typeVariable) ->
|
||||
freshTypeConstructor to ErrorUtils.createErrorTypeWithCustomConstructor("Uninferred type", typeVariable.typeVariable.freshTypeConstructor).asTypeProjection()
|
||||
freshTypeConstructor to ErrorUtils.createErrorTypeWithCustomConstructor("Uninferred type", typeVariable.typeVariable.freshTypeConstructor)
|
||||
}
|
||||
|
||||
return TypeConstructorSubstitution.createByConstructorsMap(currentSubstitutorMap + uninferredSubstitutorMap).buildSubstitutor()
|
||||
return NewTypeSubstitutorByConstructorMap(currentSubstitutorMap + uninferredSubstitutorMap)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user