From c27d9c4546c71e6ff2b23542e51a78114105059d Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 21 Jun 2019 13:41:43 +0200 Subject: [PATCH] Use TypeSystemCommonBackendContext in KotlinTypeMapper.writeGenericArguments --- .../kotlin/codegen/state/KotlinTypeMapper.kt | 54 ++++++++++++------- .../kotlin/codegen/state/typeMappingUtil.kt | 35 +++++++----- .../types/TypeSystemCommonBackendContext.kt | 14 +++++ .../types/checker/ClassicTypeSystemContext.kt | 10 ++++ .../kotlin/kapt3/stubs/ErrorTypeCorrector.kt | 3 +- 5 files changed, 81 insertions(+), 35 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt index 59f3f4a6c38..b6f2bc524f3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt @@ -352,26 +352,9 @@ class KotlinTypeMapper @JvmOverloads constructor( parameters: List, mode: TypeMappingMode ) { - for ((parameter, argument) in parameters.zip(arguments)) { - if (argument.isStarProjection || - // In == In<*, Foo> -> In - KotlinBuiltIns.isNothing(argument.type) && parameter.variance === Variance.IN_VARIANCE - ) { - signatureVisitor.writeUnboundedWildcard() - } else { - val argumentMode = mode.updateArgumentModeFromAnnotations(argument.type) - val projectionKind = getVarianceForWildcard(parameter, argument, argumentMode) - - signatureVisitor.writeTypeArgument(projectionKind) - - mapType( - argument.type, signatureVisitor, - argumentMode.toGenericArgumentMode( - getEffectiveVariance(parameter.variance, argument.projectionKind) - ) - ) - - signatureVisitor.writeTypeArgumentEnd() + with(SimpleClassicTypeSystemContext) { + writeGenericArguments(signatureVisitor, arguments, parameters, mode) { type, sw, mode -> + mapType(type as KotlinType, sw, mode) } } } @@ -1502,6 +1485,37 @@ class KotlinTypeMapper @JvmOverloads constructor( return Variance.OUT_VARIANCE } + fun TypeSystemCommonBackendContext.writeGenericArguments( + signatureVisitor: JvmSignatureWriter, + arguments: List, + parameters: List, + mode: TypeMappingMode, + mapType: (KotlinTypeMarker, JvmSignatureWriter, TypeMappingMode) -> Type + ) { + for ((parameter, argument) in parameters.zip(arguments)) { + if (argument.isStarProjection() || + // In == In<*, Foo> -> In + argument.getType().isNothing() && parameter.getVariance() == TypeVariance.IN + ) { + signatureVisitor.writeUnboundedWildcard() + } else { + val argumentMode = mode.updateArgumentModeFromAnnotations(argument.getType(), this) + val projectionKind = getVarianceForWildcard(parameter, argument, argumentMode) + + signatureVisitor.writeTypeArgument(projectionKind) + + mapType( + argument.getType(), signatureVisitor, + argumentMode.toGenericArgumentMode( + getEffectiveVariance(parameter.getVariance().convertVariance(), argument.getVariance().convertVariance()) + ) + ) + + signatureVisitor.writeTypeArgumentEnd() + } + } + } + //NB: similar platform agnostic code in DescriptorUtils.unwrapFakeOverride private fun findSuperDeclaration(descriptor: FunctionDescriptor, isSuperCall: Boolean): FunctionDescriptor { var current = descriptor diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt index 1934c35a434..6d8676caf8f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt @@ -15,6 +15,7 @@ */ @file:JvmName("TypeMappingUtil") + package org.jetbrains.kotlin.codegen.state import org.jetbrains.kotlin.descriptors.CallableDescriptor @@ -32,6 +33,7 @@ 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.SimpleClassicTypeSystemContext import org.jetbrains.kotlin.types.checker.convertVariance import org.jetbrains.kotlin.types.getEffectiveVariance import org.jetbrains.kotlin.types.model.KotlinTypeMarker @@ -82,8 +84,10 @@ private val METHODS_WITH_DECLARATION_SITE_WILDCARDS = setOf( BUILTIN_NAMES.mutableMap.child("putAll") ) -fun TypeMappingMode.updateArgumentModeFromAnnotations(type: KotlinType): TypeMappingMode { - type.suppressWildcardsMode()?.let { +fun TypeMappingMode.updateArgumentModeFromAnnotations( + type: KotlinTypeMarker, typeSystem: TypeSystemCommonBackendContext +): TypeMappingMode { + type.suppressWildcardsMode(typeSystem)?.let { return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode( skipDeclarationSiteWildcards = it, isForAnnotationParameter = isForAnnotationParameter, @@ -91,12 +95,12 @@ fun TypeMappingMode.updateArgumentModeFromAnnotations(type: KotlinType): TypeMap ) } - if (type.annotations.hasAnnotation(JVM_WILDCARD_ANNOTATION_FQ_NAME)) { + if (with(typeSystem) { type.hasAnnotation(JVM_WILDCARD_ANNOTATION_FQ_NAME) }) { return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode( - skipDeclarationSiteWildcards = false, - isForAnnotationParameter = isForAnnotationParameter, - fallbackMode = this, - needInlineClassWrapping = needInlineClassWrapping + skipDeclarationSiteWildcards = false, + isForAnnotationParameter = isForAnnotationParameter, + fallbackMode = this, + needInlineClassWrapping = needInlineClassWrapping ) } @@ -108,7 +112,7 @@ internal fun extractTypeMappingModeFromAnnotation( outerType: KotlinType, isForAnnotationParameter: Boolean ): TypeMappingMode? = - (outerType.suppressWildcardsMode() ?: callableDescriptor?.suppressWildcardsMode())?.let { + (outerType.suppressWildcardsMode(SimpleClassicTypeSystemContext) ?: callableDescriptor?.suppressWildcardsMode())?.let { if (outerType.arguments.isNotEmpty()) TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode( skipDeclarationSiteWildcards = it, @@ -122,14 +126,17 @@ internal fun extractTypeMappingModeFromAnnotation( private fun DeclarationDescriptor.suppressWildcardsMode(): Boolean? = parentsWithSelf.mapNotNull { it.annotations.findAnnotation(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME) - }.firstOrNull().suppressWildcardsMode() + }.firstOrNull()?.suppressWildcardsMode() -private fun KotlinType.suppressWildcardsMode(): Boolean? = - annotations.findAnnotation(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME).suppressWildcardsMode() +private fun KotlinTypeMarker.suppressWildcardsMode(typeSystem: TypeSystemCommonBackendContext): Boolean? = + with(typeSystem) { + if (hasAnnotation(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME)) + getAnnotationFirstArgumentValue(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME) as? Boolean ?: true + else null + } -private fun AnnotationDescriptor?.suppressWildcardsMode(): Boolean? { - return (this ?: return null).allValueArguments.values.firstOrNull()?.value as? Boolean ?: true -} +private fun AnnotationDescriptor.suppressWildcardsMode(): Boolean? = + allValueArguments.values.firstOrNull()?.value as? Boolean ?: true val JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmSuppressWildcards") val JVM_WILDCARD_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmWildcard") diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt index 6f602f12512..d432711796f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt @@ -5,9 +5,23 @@ package org.jetbrains.kotlin.types +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.TypeConstructorMarker import org.jetbrains.kotlin.types.model.TypeSystemContext interface TypeSystemCommonBackendContext : TypeSystemContext { fun TypeConstructorMarker.isFinalClassOrEnumEntryOrAnnotationClassConstructor(): Boolean + + fun KotlinTypeMarker.hasAnnotation(fqName: FqName): Boolean + + /** + * @return value of the first argument of the annotation with the given [fqName], if the annotation is present and + * the argument is of a primitive type or a String, or null otherwise. + * + * Note that this method returns null if no arguments are provided, even if the corresponding annotation parameter has a default value. + * + * TODO: provide a more granular & elaborate API here to reduce confusion + */ + fun KotlinTypeMarker.getAnnotationFirstArgumentValue(fqName: FqName): Any? } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt index 94a235cae49..ab8b9d2dfe6 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.calls.inference.CapturedType import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation @@ -485,6 +486,15 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy return this is NewCapturedTypeConstructor } + override fun KotlinTypeMarker.hasAnnotation(fqName: FqName): Boolean { + require(this is KotlinType, this::errorMessage) + return annotations.hasAnnotation(fqName) + } + + override fun KotlinTypeMarker.getAnnotationFirstArgumentValue(fqName: FqName): Any? { + require(this is KotlinType, this::errorMessage) + return annotations.findAnnotation(fqName)?.allValueArguments?.values?.firstOrNull()?.value + } } fun TypeVariance.convertVariance(): Variance { diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ErrorTypeCorrector.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ErrorTypeCorrector.kt index c4fdaf190e8..124c9371d1e 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ErrorTypeCorrector.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ErrorTypeCorrector.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext private typealias SubstitutionMap = Map> @@ -145,7 +146,7 @@ class ErrorTypeCorrector( RETURN_TYPE -> TypeMappingMode.getOptimalModeForReturnType(kotlinType, false) METHOD_PARAMETER_TYPE -> TypeMappingMode.getOptimalModeForValueParameter(kotlinType) SUPER_TYPE -> TypeMappingMode.SUPER_TYPE - }.updateArgumentModeFromAnnotations(kotlinType) + }.updateArgumentModeFromAnnotations(kotlinType, SimpleClassicTypeSystemContext) val typeParameters = (target as? ClassifierDescriptor)?.typeConstructor?.parameters return treeMaker.TypeApply(baseExpression, mapJListIndexed(arguments) { index, projection ->