Refactor: extract TypeAliasExpander as a separate class.
This commit is contained in:
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 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
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
|
import org.jetbrains.kotlin.types.*
|
||||||
|
|
||||||
|
class TypeAliasExpander(
|
||||||
|
private val reportStrategy: TypeAliasExpansionReportStrategy
|
||||||
|
) {
|
||||||
|
fun expand(typeAliasExpansion: TypeAliasExpansion, annotations: Annotations) =
|
||||||
|
expandRecursively(typeAliasExpansion, annotations, 0, true)
|
||||||
|
|
||||||
|
fun expandWithoutAbbreviation(typeAliasExpansion: TypeAliasExpansion, annotations: Annotations) =
|
||||||
|
expandRecursively(typeAliasExpansion, annotations, 0, false)
|
||||||
|
|
||||||
|
private fun expandRecursively(
|
||||||
|
typeAliasExpansion: TypeAliasExpansion,
|
||||||
|
annotations: Annotations,
|
||||||
|
recursionDepth: Int,
|
||||||
|
withAbbreviatedType: Boolean
|
||||||
|
): KotlinType {
|
||||||
|
val originalProjection = TypeProjectionImpl(Variance.INVARIANT, typeAliasExpansion.descriptor.underlyingType)
|
||||||
|
val expandedProjection = expandTypeProjection(originalProjection, typeAliasExpansion, null, recursionDepth)
|
||||||
|
val expandedType = expandedProjection.type
|
||||||
|
|
||||||
|
if (expandedType.isError) return expandedType
|
||||||
|
|
||||||
|
assert(expandedProjection.projectionKind == Variance.INVARIANT) {
|
||||||
|
"Type alias expansion: result for ${typeAliasExpansion.descriptor} is ${expandedProjection.projectionKind}, should be invariant"
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (withAbbreviatedType) {
|
||||||
|
val abbreviatedType = KotlinTypeImpl.create(annotations,
|
||||||
|
typeAliasExpansion.descriptor.typeConstructor,
|
||||||
|
originalProjection.type.isMarkedNullable,
|
||||||
|
typeAliasExpansion.arguments,
|
||||||
|
MemberScope.Empty)
|
||||||
|
|
||||||
|
expandedType.withAbbreviatedType(abbreviatedType)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
expandedType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun expandTypeProjection(
|
||||||
|
originalProjection: TypeProjection,
|
||||||
|
typeAliasExpansion: TypeAliasExpansion,
|
||||||
|
typeParameterDescriptor: TypeParameterDescriptor?,
|
||||||
|
recursionDepth: Int
|
||||||
|
): TypeProjection {
|
||||||
|
assertRecursionDepth(recursionDepth, typeAliasExpansion.descriptor)
|
||||||
|
|
||||||
|
val originalType = originalProjection.type
|
||||||
|
|
||||||
|
val typeAliasArgument = typeAliasExpansion.getReplacement(originalType.constructor)
|
||||||
|
|
||||||
|
if (typeAliasArgument == null) {
|
||||||
|
return expandNonArgumentTypeProjection(originalProjection, typeAliasExpansion, recursionDepth)
|
||||||
|
}
|
||||||
|
|
||||||
|
val originalVariance =
|
||||||
|
if (originalProjection.projectionKind != Variance.INVARIANT)
|
||||||
|
originalProjection.projectionKind
|
||||||
|
else if (typeParameterDescriptor != null)
|
||||||
|
typeParameterDescriptor.variance
|
||||||
|
else
|
||||||
|
Variance.INVARIANT
|
||||||
|
|
||||||
|
val argumentVariance = typeAliasArgument.projectionKind
|
||||||
|
|
||||||
|
val substitutedVariance =
|
||||||
|
if (argumentVariance == Variance.INVARIANT)
|
||||||
|
originalVariance
|
||||||
|
else if (originalVariance == Variance.INVARIANT || originalVariance == argumentVariance)
|
||||||
|
argumentVariance
|
||||||
|
else if (typeAliasArgument.isStarProjection)
|
||||||
|
argumentVariance
|
||||||
|
else {
|
||||||
|
if (originalVariance != argumentVariance && !typeAliasArgument.isStarProjection) {
|
||||||
|
reportStrategy.conflictingProjection(typeAliasExpansion.descriptor, typeParameterDescriptor, originalType)
|
||||||
|
}
|
||||||
|
argumentVariance
|
||||||
|
}
|
||||||
|
|
||||||
|
val substitutedType = TypeUtils.makeNullableIfNeeded(typeAliasArgument.type, originalType.isMarkedNullable)
|
||||||
|
|
||||||
|
return TypeProjectionImpl(substitutedVariance, substitutedType)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun expandNonArgumentTypeProjection(
|
||||||
|
originalProjection: TypeProjection,
|
||||||
|
typeAliasExpansion: TypeAliasExpansion,
|
||||||
|
recursionDepth: Int
|
||||||
|
): TypeProjection {
|
||||||
|
val type = originalProjection.type
|
||||||
|
val typeConstructor = type.constructor
|
||||||
|
val typeDescriptor = typeConstructor.declarationDescriptor
|
||||||
|
|
||||||
|
when (typeDescriptor) {
|
||||||
|
is TypeParameterDescriptor -> {
|
||||||
|
return originalProjection
|
||||||
|
}
|
||||||
|
is TypeAliasDescriptor -> {
|
||||||
|
if (typeAliasExpansion.isRecursion(typeDescriptor)) {
|
||||||
|
reportStrategy.recursiveTypeAlias(typeDescriptor)
|
||||||
|
return TypeProjectionImpl(Variance.INVARIANT, ErrorUtils.createErrorType("Recursive type alias: ${typeDescriptor.name}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
val expandedArguments = type.arguments.mapIndexed { i, typeAliasArgument ->
|
||||||
|
expandTypeProjection(typeAliasArgument, typeAliasExpansion, typeConstructor.parameters[i], recursionDepth + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
val nestedExpansion = TypeAliasExpansion.create(typeAliasExpansion, typeDescriptor, expandedArguments)
|
||||||
|
|
||||||
|
val expandedType = expandRecursively(nestedExpansion, type.annotations, recursionDepth + 1, false)
|
||||||
|
|
||||||
|
return TypeProjectionImpl(originalProjection.projectionKind, expandedType.withAbbreviatedType(type))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val substitutedArguments = type.arguments.mapIndexed { i, originalArgument ->
|
||||||
|
expandTypeProjection(originalArgument, typeAliasExpansion, typeConstructor.parameters[i], recursionDepth + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
val substitutedType = type.replace(newArguments = substitutedArguments)
|
||||||
|
|
||||||
|
checkTypeArgumentsSubstitution(type, substitutedType)
|
||||||
|
|
||||||
|
return TypeProjectionImpl(originalProjection.projectionKind, substitutedType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkTypeArgumentsSubstitution(unsubstitutedType: KotlinType, substitutedType: KotlinType) {
|
||||||
|
val typeSubstitutor = TypeSubstitutor.create(substitutedType)
|
||||||
|
|
||||||
|
substitutedType.arguments.forEachIndexed { i, substitutedArgument ->
|
||||||
|
if (!substitutedArgument.type.dependsOnTypeAliasParameters()) {
|
||||||
|
val unsubstitutedArgument = unsubstitutedType.arguments[i]
|
||||||
|
val typeParameter = unsubstitutedType.constructor.parameters[i]
|
||||||
|
DescriptorResolver.checkBoundsInTypeAlias(reportStrategy, unsubstitutedArgument.type, substitutedArgument.type, typeParameter, typeSubstitutor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val MAX_RECURSION_DEPTH = 100
|
||||||
|
|
||||||
|
private fun assertRecursionDepth(recursionDepth: Int, typeAliasDescriptor: TypeAliasDescriptor) {
|
||||||
|
if (recursionDepth > MAX_RECURSION_DEPTH) {
|
||||||
|
throw AssertionError("Too deep recursion while expanding type alias ${typeAliasDescriptor.name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val NON_REPORTING = TypeAliasExpander(TypeAliasExpansionReportStrategy.DO_NOTHING)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 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
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjection
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
|
||||||
|
class TypeAliasExpansion private constructor(
|
||||||
|
val parent: TypeAliasExpansion?,
|
||||||
|
val descriptor: TypeAliasDescriptor,
|
||||||
|
val arguments: List<TypeProjection>,
|
||||||
|
val mapping: Map<TypeParameterDescriptor, TypeProjection>
|
||||||
|
) {
|
||||||
|
fun getReplacement(constructor: TypeConstructor): TypeProjection? {
|
||||||
|
val descriptor = constructor.declarationDescriptor
|
||||||
|
return if (descriptor is TypeParameterDescriptor)
|
||||||
|
mapping[descriptor]
|
||||||
|
else
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isRecursion(descriptor: TypeAliasDescriptor): Boolean =
|
||||||
|
this.descriptor == descriptor || (parent?.isRecursion(descriptor) ?: false)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun create(
|
||||||
|
parent: TypeAliasExpansion?,
|
||||||
|
typeAliasDescriptor: TypeAliasDescriptor,
|
||||||
|
arguments: List<TypeProjection>
|
||||||
|
): TypeAliasExpansion {
|
||||||
|
val typeParameters = typeAliasDescriptor.typeConstructor.parameters.map { it.original as TypeParameterDescriptor }
|
||||||
|
val mappedArguments = typeParameters.zip(arguments).toMap()
|
||||||
|
return TypeAliasExpansion(parent, typeAliasDescriptor, arguments, mappedArguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createWithFormalArguments(typeAliasDescriptor: TypeAliasDescriptor) =
|
||||||
|
create(null, typeAliasDescriptor, emptyList())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KotlinType.dependsOnTypeAliasParameters(): Boolean =
|
||||||
|
TypeUtils.contains(this) { type ->
|
||||||
|
val constructorDeclaration = type.constructor.declarationDescriptor
|
||||||
|
constructorDeclaration is TypeParameterDescriptor && constructorDeclaration.containingDeclaration is TypeAliasDescriptor
|
||||||
|
}
|
||||||
+1
-1
@@ -26,7 +26,7 @@ interface TypeAliasExpansionReportStrategy {
|
|||||||
fun recursiveTypeAlias(typeAlias: TypeAliasDescriptor)
|
fun recursiveTypeAlias(typeAlias: TypeAliasDescriptor)
|
||||||
fun boundsViolationInSubstitution(bound: KotlinType, unsubstitutedArgument: KotlinType, argument: KotlinType, typeParameter: TypeParameterDescriptor)
|
fun boundsViolationInSubstitution(bound: KotlinType, unsubstitutedArgument: KotlinType, argument: KotlinType, typeParameter: TypeParameterDescriptor)
|
||||||
|
|
||||||
object DEFAULT : TypeAliasExpansionReportStrategy {
|
object DO_NOTHING : TypeAliasExpansionReportStrategy {
|
||||||
override fun wrongNumberOfTypeArguments(typeAlias: TypeAliasDescriptor, numberOfParameters: Int) {}
|
override fun wrongNumberOfTypeArguments(typeAlias: TypeAliasDescriptor, numberOfParameters: Int) {}
|
||||||
override fun conflictingProjection(typeAlias: TypeAliasDescriptor, typeParameter: TypeParameterDescriptor?, expandingType: KotlinType) {}
|
override fun conflictingProjection(typeAlias: TypeAliasDescriptor, typeParameter: TypeParameterDescriptor?, expandingType: KotlinType) {}
|
||||||
override fun recursiveTypeAlias(typeAlias: TypeAliasDescriptor) {}
|
override fun recursiveTypeAlias(typeAlias: TypeAliasDescriptor) {}
|
||||||
|
|||||||
@@ -75,9 +75,8 @@ class TypeResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun resolveExpandedTypeForTypeAlias(typeAliasDescriptor: TypeAliasDescriptor): KotlinType {
|
fun resolveExpandedTypeForTypeAlias(typeAliasDescriptor: TypeAliasDescriptor): KotlinType {
|
||||||
val typeAliasExpansion = createTypeAliasExpansion(null, typeAliasDescriptor, emptyList())
|
val typeAliasExpansion = TypeAliasExpansion.createWithFormalArguments(typeAliasDescriptor)
|
||||||
val expandedType = expandTypeAlias(typeAliasExpansion, TypeAliasExpansionReportStrategy.DEFAULT, Annotations.EMPTY, 0,
|
val expandedType = TypeAliasExpander.NON_REPORTING.expandWithoutAbbreviation(typeAliasExpansion, Annotations.EMPTY)
|
||||||
withAbbreviatedType = false)
|
|
||||||
return expandedType
|
return expandedType
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,12 +423,6 @@ class TypeResolver(
|
|||||||
return type(resultingType)
|
return type(resultingType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinType.dependsOnTypeAliasParameters(): Boolean =
|
|
||||||
TypeUtils.contains(this) { type ->
|
|
||||||
val constructorDeclaration = type.constructor.declarationDescriptor
|
|
||||||
constructorDeclaration is TypeParameterDescriptor && constructorDeclaration.containingDeclaration is TypeAliasDescriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resolveTypeForTypeAlias(
|
private fun resolveTypeForTypeAlias(
|
||||||
c: TypeResolutionContext,
|
c: TypeResolutionContext,
|
||||||
annotations: Annotations,
|
annotations: Annotations,
|
||||||
@@ -479,8 +472,8 @@ class TypeResolver(
|
|||||||
type(abbreviatedType)
|
type(abbreviatedType)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val typeAliasExpansion = createTypeAliasExpansion(null, descriptor, arguments)
|
val typeAliasExpansion = TypeAliasExpansion.create(null, descriptor, arguments)
|
||||||
val expandedType = expandTypeAlias(typeAliasExpansion, reportStrategy, annotations, 0)
|
val expandedType = TypeAliasExpander(reportStrategy).expand(typeAliasExpansion, annotations)
|
||||||
type(expandedType)
|
type(expandedType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -493,7 +486,6 @@ class TypeResolver(
|
|||||||
typeParameters: List<TypeParameterDescriptor>,
|
typeParameters: List<TypeParameterDescriptor>,
|
||||||
typeArguments: List<KtTypeProjection>
|
typeArguments: List<KtTypeProjection>
|
||||||
) : TypeAliasExpansionReportStrategy {
|
) : TypeAliasExpansionReportStrategy {
|
||||||
constructor (trace: BindingTrace, typeAliasDescriptor: TypeAliasDescriptor) : this(trace, null, null, typeAliasDescriptor, emptyList(), emptyList())
|
|
||||||
|
|
||||||
private val mappedArguments = typeParameters.zip(typeArguments).toMap()
|
private val mappedArguments = typeParameters.zip(typeArguments).toMap()
|
||||||
|
|
||||||
@@ -532,172 +524,7 @@ class TypeResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TypeAliasExpansion(
|
|
||||||
val parent: TypeAliasExpansion?,
|
|
||||||
val descriptor: TypeAliasDescriptor,
|
|
||||||
val arguments: List<TypeProjection>,
|
|
||||||
val mapping: Map<TypeParameterDescriptor, TypeProjection>
|
|
||||||
) {
|
|
||||||
fun getReplacement(constructor: TypeConstructor): TypeProjection? {
|
|
||||||
val descriptor = constructor.declarationDescriptor
|
|
||||||
return if (descriptor is TypeParameterDescriptor)
|
|
||||||
mapping[descriptor]
|
|
||||||
else
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isRecursion(descriptor: TypeAliasDescriptor): Boolean =
|
|
||||||
this.descriptor == descriptor || (parent?.isRecursion(descriptor) ?: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createTypeAliasExpansion(
|
|
||||||
parent: TypeAliasExpansion?,
|
|
||||||
typeAliasDescriptor: TypeAliasDescriptor,
|
|
||||||
arguments: List<TypeProjection>
|
|
||||||
): TypeAliasExpansion {
|
|
||||||
val typeParameters = typeAliasDescriptor.typeConstructor.parameters.map { it.original as TypeParameterDescriptor }
|
|
||||||
val mappedArguments = typeParameters.zip(arguments).toMap()
|
|
||||||
return TypeAliasExpansion(parent, typeAliasDescriptor, arguments, mappedArguments)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun expandTypeAlias(
|
|
||||||
typeAliasExpansion: TypeAliasExpansion,
|
|
||||||
reportStrategy: TypeAliasExpansionReportStrategy,
|
|
||||||
annotations: Annotations,
|
|
||||||
recursionDepth: Int,
|
|
||||||
withAbbreviatedType: Boolean = true
|
|
||||||
): KotlinType {
|
|
||||||
val originalProjection = TypeProjectionImpl(Variance.INVARIANT, typeAliasExpansion.descriptor.underlyingType)
|
|
||||||
val expandedProjection = expandTypeProjectionForTypeAlias(originalProjection, typeAliasExpansion, null, reportStrategy, recursionDepth)
|
|
||||||
val expandedType = expandedProjection.type
|
|
||||||
|
|
||||||
if (expandedType.isError) return expandedType
|
|
||||||
|
|
||||||
assert(expandedProjection.projectionKind == Variance.INVARIANT) {
|
|
||||||
"Type alias expansion: result for ${typeAliasExpansion.descriptor} is ${expandedProjection.projectionKind}, should be invariant"
|
|
||||||
}
|
|
||||||
|
|
||||||
return if (withAbbreviatedType) {
|
|
||||||
val abbreviatedType = KotlinTypeImpl.create(annotations,
|
|
||||||
typeAliasExpansion.descriptor.typeConstructor,
|
|
||||||
originalProjection.type.isMarkedNullable,
|
|
||||||
typeAliasExpansion.arguments,
|
|
||||||
MemberScope.Empty)
|
|
||||||
|
|
||||||
expandedType.withAbbreviatedType(abbreviatedType)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
expandedType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun expandTypeProjectionForTypeAlias(
|
|
||||||
originalProjection: TypeProjection,
|
|
||||||
typeAliasExpansion: TypeAliasExpansion,
|
|
||||||
typeParameterDescriptor: TypeParameterDescriptor?,
|
|
||||||
reportStrategy: TypeAliasExpansionReportStrategy,
|
|
||||||
recursionDepth: Int
|
|
||||||
): TypeProjection {
|
|
||||||
assertRecursionDepth(recursionDepth) {
|
|
||||||
"Too deep recursion while expanding type alias ${typeAliasExpansion.descriptor}"
|
|
||||||
}
|
|
||||||
|
|
||||||
val originalType = originalProjection.type
|
|
||||||
|
|
||||||
val typeAliasArgument = typeAliasExpansion.getReplacement(originalType.constructor)
|
|
||||||
|
|
||||||
if (typeAliasArgument == null) {
|
|
||||||
return substituteNonArgumentTypeForTypeAlias(originalProjection, typeAliasExpansion, reportStrategy, recursionDepth)
|
|
||||||
}
|
|
||||||
|
|
||||||
val originalVariance =
|
|
||||||
if (originalProjection.projectionKind != Variance.INVARIANT)
|
|
||||||
originalProjection.projectionKind
|
|
||||||
else if (typeParameterDescriptor != null)
|
|
||||||
typeParameterDescriptor.variance
|
|
||||||
else
|
|
||||||
Variance.INVARIANT
|
|
||||||
|
|
||||||
val argumentVariance = typeAliasArgument.projectionKind
|
|
||||||
|
|
||||||
val substitutedVariance =
|
|
||||||
if (argumentVariance == Variance.INVARIANT)
|
|
||||||
originalVariance
|
|
||||||
else if (originalVariance == Variance.INVARIANT || originalVariance == argumentVariance)
|
|
||||||
argumentVariance
|
|
||||||
else if (typeAliasArgument.isStarProjection)
|
|
||||||
argumentVariance
|
|
||||||
else {
|
|
||||||
if (originalVariance != argumentVariance && !typeAliasArgument.isStarProjection) {
|
|
||||||
reportStrategy.conflictingProjection(typeAliasExpansion.descriptor, typeParameterDescriptor, originalType)
|
|
||||||
}
|
|
||||||
argumentVariance
|
|
||||||
}
|
|
||||||
|
|
||||||
val substitutedType = TypeUtils.makeNullableIfNeeded(typeAliasArgument.type, originalType.isMarkedNullable)
|
|
||||||
|
|
||||||
return TypeProjectionImpl(substitutedVariance, substitutedType)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun substituteNonArgumentTypeForTypeAlias(
|
|
||||||
originalProjection: TypeProjection,
|
|
||||||
typeAliasExpansion: TypeAliasExpansion,
|
|
||||||
reportStrategy: TypeAliasExpansionReportStrategy,
|
|
||||||
recursionDepth: Int
|
|
||||||
): TypeProjection {
|
|
||||||
val type = originalProjection.type
|
|
||||||
val typeConstructor = type.constructor
|
|
||||||
val typeDescriptor = typeConstructor.declarationDescriptor
|
|
||||||
|
|
||||||
when (typeDescriptor) {
|
|
||||||
is TypeParameterDescriptor -> {
|
|
||||||
return originalProjection
|
|
||||||
}
|
|
||||||
is TypeAliasDescriptor -> {
|
|
||||||
if (typeAliasExpansion.isRecursion(typeDescriptor)) {
|
|
||||||
reportStrategy.recursiveTypeAlias(typeDescriptor)
|
|
||||||
return TypeProjectionImpl(Variance.INVARIANT, ErrorUtils.createErrorType("Recursive type alias: ${typeDescriptor.name}"))
|
|
||||||
}
|
|
||||||
|
|
||||||
val expandedArguments = type.arguments.mapIndexed { i, typeAliasArgument ->
|
|
||||||
expandTypeProjectionForTypeAlias(typeAliasArgument, typeAliasExpansion, typeConstructor.parameters[i], reportStrategy, recursionDepth + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
val nestedExpansion = createTypeAliasExpansion(typeAliasExpansion, typeDescriptor, expandedArguments)
|
|
||||||
|
|
||||||
val expandedType = expandTypeAlias(nestedExpansion, reportStrategy, type.annotations, recursionDepth + 1)
|
|
||||||
|
|
||||||
return TypeProjectionImpl(originalProjection.projectionKind, expandedType.withAbbreviatedType(type))
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
val substitutedArguments = type.arguments.mapIndexed { i, originalArgument ->
|
|
||||||
expandTypeProjectionForTypeAlias(originalArgument, typeAliasExpansion, typeConstructor.parameters[i], reportStrategy, recursionDepth + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
val substitutedType = type.replace(newArguments = substitutedArguments)
|
|
||||||
|
|
||||||
checkTypeArgumentsSubstitutionInTypeAliasExpansion(type, substitutedType, reportStrategy)
|
|
||||||
|
|
||||||
return TypeProjectionImpl(originalProjection.projectionKind, substitutedType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkTypeArgumentsSubstitutionInTypeAliasExpansion(
|
|
||||||
unsubstitutedType: KotlinType,
|
|
||||||
substitutedType: KotlinType,
|
|
||||||
reportStrategy: TypeAliasExpansionReportStrategy
|
|
||||||
) {
|
|
||||||
val typeSubstitutor = TypeSubstitutor.create(substitutedType)
|
|
||||||
|
|
||||||
substitutedType.arguments.forEachIndexed { i, substitutedArgument ->
|
|
||||||
if (!substitutedArgument.type.dependsOnTypeAliasParameters()) {
|
|
||||||
val unsubstitutedArgument = unsubstitutedType.arguments[i]
|
|
||||||
val typeParameter = unsubstitutedType.constructor.parameters[i]
|
|
||||||
DescriptorResolver.checkBoundsInTypeAlias(reportStrategy, unsubstitutedArgument.type, substitutedArgument.type, typeParameter, typeSubstitutor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createErrorTypeForTypeConstructor(
|
private fun createErrorTypeForTypeConstructor(
|
||||||
c: TypeResolutionContext,
|
c: TypeResolutionContext,
|
||||||
@@ -901,14 +728,6 @@ class TypeResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val MAX_RECURSION_DEPTH = 100
|
|
||||||
|
|
||||||
private inline fun assertRecursionDepth(recursionDepth: Int, lazyMessage: () -> String) {
|
|
||||||
if (recursionDepth > MAX_RECURSION_DEPTH) {
|
|
||||||
throw AssertionError(lazyMessage())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic fun resolveProjectionKind(projectionKind: KtProjectionKind): Variance {
|
@JvmStatic fun resolveProjectionKind(projectionKind: KtProjectionKind): Variance {
|
||||||
return when (projectionKind) {
|
return when (projectionKind) {
|
||||||
KtProjectionKind.IN -> IN_VARIANCE
|
KtProjectionKind.IN -> IN_VARIANCE
|
||||||
|
|||||||
Reference in New Issue
Block a user