Introduce TypeSystemCommonBackendContext, use in KotlinTypeMapper.getVarianceForWildcard
This commit is contained in:
@@ -67,10 +67,9 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Descriptor
|
|||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext
|
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext
|
||||||
|
import org.jetbrains.kotlin.types.checker.convertVariance
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*
|
||||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
import org.jetbrains.kotlin.types.model.*
|
||||||
import org.jetbrains.kotlin.types.model.TypeSystemContext
|
|
||||||
import org.jetbrains.kotlin.types.model.TypeVariance
|
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
@@ -1468,9 +1467,14 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getVarianceForWildcard(parameter: TypeParameterDescriptor, projection: TypeProjection, mode: TypeMappingMode): Variance {
|
fun getVarianceForWildcard(parameter: TypeParameterDescriptor, projection: TypeProjection, mode: TypeMappingMode): Variance =
|
||||||
val projectionKind = projection.projectionKind
|
SimpleClassicTypeSystemContext.getVarianceForWildcard(parameter, projection, mode)
|
||||||
val parameterVariance = parameter.variance
|
|
||||||
|
private fun TypeSystemCommonBackendContext.getVarianceForWildcard(
|
||||||
|
parameter: TypeParameterMarker, projection: TypeArgumentMarker, mode: TypeMappingMode
|
||||||
|
): Variance {
|
||||||
|
val projectionKind = projection.getVariance().convertVariance()
|
||||||
|
val parameterVariance = parameter.getVariance().convertVariance()
|
||||||
|
|
||||||
if (parameterVariance == Variance.INVARIANT) {
|
if (parameterVariance == Variance.INVARIANT) {
|
||||||
return projectionKind
|
return projectionKind
|
||||||
@@ -1481,12 +1485,12 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (projectionKind == Variance.INVARIANT || projectionKind == parameterVariance) {
|
if (projectionKind == Variance.INVARIANT || projectionKind == parameterVariance) {
|
||||||
if (mode.skipDeclarationSiteWildcardsIfPossible && !projection.isStarProjection) {
|
if (mode.skipDeclarationSiteWildcardsIfPossible && !projection.isStarProjection()) {
|
||||||
if (parameterVariance == Variance.OUT_VARIANCE && projection.type.isMostPreciseCovariantArgument()) {
|
if (parameterVariance == Variance.OUT_VARIANCE && isMostPreciseCovariantArgument(projection.getType())) {
|
||||||
return Variance.INVARIANT
|
return Variance.INVARIANT
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameterVariance == Variance.IN_VARIANCE && projection.type.isMostPreciseContravariantArgument(parameter)) {
|
if (parameterVariance == Variance.IN_VARIANCE && isMostPreciseContravariantArgument(projection.getType(), parameter)) {
|
||||||
return Variance.INVARIANT
|
return Variance.INVARIANT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
@file:JvmName("TypeMappingUtil")
|
@file:JvmName("TypeMappingUtil")
|
||||||
package org.jetbrains.kotlin.codegen.state
|
package org.jetbrains.kotlin.codegen.state
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -29,33 +30,38 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
|
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
|
||||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
import org.jetbrains.kotlin.types.checker.convertVariance
|
||||||
import org.jetbrains.kotlin.types.getEffectiveVariance
|
import org.jetbrains.kotlin.types.getEffectiveVariance
|
||||||
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeParameterMarker
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES as BUILTIN_NAMES
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES as BUILTIN_NAMES
|
||||||
|
|
||||||
fun KotlinType.isMostPreciseContravariantArgument(parameter: TypeParameterDescriptor): Boolean =
|
// TODO: probably class upper bound should be used
|
||||||
// TODO: probably class upper bound should be used
|
@Suppress("UNUSED_PARAMETER")
|
||||||
KotlinBuiltIns.isAnyOrNullableAny(this)
|
fun TypeSystemCommonBackendContext.isMostPreciseContravariantArgument(type: KotlinTypeMarker, parameter: TypeParameterMarker): Boolean =
|
||||||
|
type.typeConstructor().isAnyConstructor()
|
||||||
|
|
||||||
fun KotlinType.isMostPreciseCovariantArgument(): Boolean = !canHaveSubtypesIgnoringNullability()
|
fun TypeSystemCommonBackendContext.isMostPreciseCovariantArgument(type: KotlinTypeMarker): Boolean =
|
||||||
|
!canHaveSubtypesIgnoringNullability(type)
|
||||||
|
|
||||||
private fun KotlinType.canHaveSubtypesIgnoringNullability(): Boolean {
|
private fun TypeSystemCommonBackendContext.canHaveSubtypesIgnoringNullability(kotlinType: KotlinTypeMarker): Boolean {
|
||||||
val constructor = constructor
|
val constructor = kotlinType.typeConstructor()
|
||||||
val descriptor = constructor.declarationDescriptor
|
|
||||||
|
|
||||||
when (descriptor) {
|
if (!constructor.isClassTypeConstructor() || !constructor.isFinalClassOrEnumEntryOrAnnotationClassConstructor()) return true
|
||||||
is TypeParameterDescriptor -> return true
|
|
||||||
is ClassDescriptor -> if (!descriptor.isFinalClass) return true
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((parameter, argument) in constructor.parameters.zip(arguments)) {
|
for (i in 0 until constructor.parametersCount()) {
|
||||||
if (argument.isStarProjection) return true
|
val parameter = constructor.getParameter(i)
|
||||||
val projectionKind = argument.projectionKind
|
val argument = kotlinType.getArgument(i)
|
||||||
val type = argument.type
|
if (argument.isStarProjection()) return true
|
||||||
|
|
||||||
val effectiveVariance = getEffectiveVariance(parameter.variance, projectionKind)
|
val projectionKind = argument.getVariance().convertVariance()
|
||||||
if (effectiveVariance == Variance.OUT_VARIANCE && !type.isMostPreciseCovariantArgument()) return true
|
val type = argument.getType()
|
||||||
if (effectiveVariance == Variance.IN_VARIANCE && !type.isMostPreciseContravariantArgument(parameter)) return true
|
|
||||||
|
val effectiveVariance = getEffectiveVariance(parameter.getVariance().convertVariance(), projectionKind)
|
||||||
|
if (effectiveVariance == Variance.OUT_VARIANCE && !isMostPreciseCovariantArgument(type)) return true
|
||||||
|
if (effectiveVariance == Variance.IN_VARIANCE && !isMostPreciseContravariantArgument(type, parameter)) return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.types
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeSystemContext
|
||||||
|
|
||||||
|
interface TypeSystemCommonBackendContext : TypeSystemContext {
|
||||||
|
fun TypeConstructorMarker.isFinalClassOrEnumEntryOrAnnotationClassConstructor(): Boolean
|
||||||
|
}
|
||||||
+15
-10
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.types.typeUtil.contains
|
|||||||
import kotlin.contracts.ExperimentalContracts
|
import kotlin.contracts.ExperimentalContracts
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext {
|
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext {
|
||||||
override fun TypeConstructorMarker.isDenotable(): Boolean {
|
override fun TypeConstructorMarker.isDenotable(): Boolean {
|
||||||
require(this is TypeConstructor, this::errorMessage)
|
require(this is TypeConstructor, this::errorMessage)
|
||||||
return this.isDenotable
|
return this.isDenotable
|
||||||
@@ -145,15 +145,6 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext {
|
|||||||
return this.projectionKind.convertVariance()
|
return this.projectionKind.convertVariance()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun TypeVariance.convertVariance(): Variance {
|
|
||||||
return when (this) {
|
|
||||||
TypeVariance.INV -> Variance.INVARIANT
|
|
||||||
TypeVariance.IN -> Variance.IN_VARIANCE
|
|
||||||
TypeVariance.OUT -> Variance.OUT_VARIANCE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun TypeArgumentMarker.getType(): KotlinTypeMarker {
|
override fun TypeArgumentMarker.getType(): KotlinTypeMarker {
|
||||||
require(this is TypeProjection, this::errorMessage)
|
require(this is TypeProjection, this::errorMessage)
|
||||||
return this.type.unwrap()
|
return this.type.unwrap()
|
||||||
@@ -214,6 +205,12 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext {
|
|||||||
classDescriptor.kind != ClassKind.ANNOTATION_CLASS
|
classDescriptor.kind != ClassKind.ANNOTATION_CLASS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun TypeConstructorMarker.isFinalClassOrEnumEntryOrAnnotationClassConstructor(): Boolean {
|
||||||
|
require(this is TypeConstructor, this::errorMessage)
|
||||||
|
val classDescriptor = declarationDescriptor
|
||||||
|
return classDescriptor is ClassDescriptor && classDescriptor.isFinalClass
|
||||||
|
}
|
||||||
|
|
||||||
override fun SimpleTypeMarker.asArgumentList(): TypeArgumentListMarker {
|
override fun SimpleTypeMarker.asArgumentList(): TypeArgumentListMarker {
|
||||||
require(this is SimpleType, this::errorMessage)
|
require(this is SimpleType, this::errorMessage)
|
||||||
return this
|
return this
|
||||||
@@ -490,6 +487,14 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun TypeVariance.convertVariance(): Variance {
|
||||||
|
return when (this) {
|
||||||
|
TypeVariance.INV -> Variance.INVARIANT
|
||||||
|
TypeVariance.IN -> Variance.IN_VARIANCE
|
||||||
|
TypeVariance.OUT -> Variance.OUT_VARIANCE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun captureFromExpressionInternal(type: UnwrappedType) = captureFromExpression(type)
|
private fun captureFromExpressionInternal(type: UnwrappedType) = captureFromExpression(type)
|
||||||
|
|
||||||
private fun hasNoInferInternal(type: UnwrappedType): Boolean {
|
private fun hasNoInferInternal(type: UnwrappedType): Boolean {
|
||||||
|
|||||||
Reference in New Issue
Block a user