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.types.*
|
||||
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.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemContext
|
||||
import org.jetbrains.kotlin.types.model.TypeVariance
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -1468,9 +1467,14 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
return false
|
||||
}
|
||||
|
||||
fun getVarianceForWildcard(parameter: TypeParameterDescriptor, projection: TypeProjection, mode: TypeMappingMode): Variance {
|
||||
val projectionKind = projection.projectionKind
|
||||
val parameterVariance = parameter.variance
|
||||
fun getVarianceForWildcard(parameter: TypeParameterDescriptor, projection: TypeProjection, mode: TypeMappingMode): Variance =
|
||||
SimpleClassicTypeSystemContext.getVarianceForWildcard(parameter, projection, mode)
|
||||
|
||||
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) {
|
||||
return projectionKind
|
||||
@@ -1481,12 +1485,12 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
if (projectionKind == Variance.INVARIANT || projectionKind == parameterVariance) {
|
||||
if (mode.skipDeclarationSiteWildcardsIfPossible && !projection.isStarProjection) {
|
||||
if (parameterVariance == Variance.OUT_VARIANCE && projection.type.isMostPreciseCovariantArgument()) {
|
||||
if (mode.skipDeclarationSiteWildcardsIfPossible && !projection.isStarProjection()) {
|
||||
if (parameterVariance == Variance.OUT_VARIANCE && isMostPreciseCovariantArgument(projection.getType())) {
|
||||
return Variance.INVARIANT
|
||||
}
|
||||
|
||||
if (parameterVariance == Variance.IN_VARIANCE && projection.type.isMostPreciseContravariantArgument(parameter)) {
|
||||
if (parameterVariance == Variance.IN_VARIANCE && isMostPreciseContravariantArgument(projection.getType(), parameter)) {
|
||||
return Variance.INVARIANT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
@file:JvmName("TypeMappingUtil")
|
||||
package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
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.isInlineClassType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.checker.convertVariance
|
||||
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
|
||||
|
||||
fun KotlinType.isMostPreciseContravariantArgument(parameter: TypeParameterDescriptor): Boolean =
|
||||
// TODO: probably class upper bound should be used
|
||||
KotlinBuiltIns.isAnyOrNullableAny(this)
|
||||
// TODO: probably class upper bound should be used
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
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 {
|
||||
val constructor = constructor
|
||||
val descriptor = constructor.declarationDescriptor
|
||||
private fun TypeSystemCommonBackendContext.canHaveSubtypesIgnoringNullability(kotlinType: KotlinTypeMarker): Boolean {
|
||||
val constructor = kotlinType.typeConstructor()
|
||||
|
||||
when (descriptor) {
|
||||
is TypeParameterDescriptor -> return true
|
||||
is ClassDescriptor -> if (!descriptor.isFinalClass) return true
|
||||
}
|
||||
if (!constructor.isClassTypeConstructor() || !constructor.isFinalClassOrEnumEntryOrAnnotationClassConstructor()) return true
|
||||
|
||||
for ((parameter, argument) in constructor.parameters.zip(arguments)) {
|
||||
if (argument.isStarProjection) return true
|
||||
val projectionKind = argument.projectionKind
|
||||
val type = argument.type
|
||||
for (i in 0 until constructor.parametersCount()) {
|
||||
val parameter = constructor.getParameter(i)
|
||||
val argument = kotlinType.getArgument(i)
|
||||
if (argument.isStarProjection()) return true
|
||||
|
||||
val effectiveVariance = getEffectiveVariance(parameter.variance, projectionKind)
|
||||
if (effectiveVariance == Variance.OUT_VARIANCE && !type.isMostPreciseCovariantArgument()) return true
|
||||
if (effectiveVariance == Variance.IN_VARIANCE && !type.isMostPreciseContravariantArgument(parameter)) return true
|
||||
val projectionKind = argument.getVariance().convertVariance()
|
||||
val type = argument.getType()
|
||||
|
||||
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
|
||||
|
||||
@@ -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.contract
|
||||
|
||||
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext {
|
||||
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext {
|
||||
override fun TypeConstructorMarker.isDenotable(): Boolean {
|
||||
require(this is TypeConstructor, this::errorMessage)
|
||||
return this.isDenotable
|
||||
@@ -145,15 +145,6 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext {
|
||||
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 {
|
||||
require(this is TypeProjection, this::errorMessage)
|
||||
return this.type.unwrap()
|
||||
@@ -214,6 +205,12 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext {
|
||||
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 {
|
||||
require(this is SimpleType, this::errorMessage)
|
||||
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 hasNoInferInternal(type: UnwrappedType): Boolean {
|
||||
|
||||
Reference in New Issue
Block a user