Combine type annotations for arguments of type aliases.

This commit is contained in:
Dmitry Petrov
2016-11-21 13:59:10 +03:00
parent 063bce23d2
commit 67fe28b8d8
7 changed files with 55 additions and 13 deletions
@@ -50,7 +50,7 @@ class TypeAliasExpander(
"Type alias expansion: result for ${typeAliasExpansion.descriptor} is ${expandedProjection.projectionKind}, should be invariant" "Type alias expansion: result for ${typeAliasExpansion.descriptor} is ${expandedProjection.projectionKind}, should be invariant"
} }
val expandedTypeWithExtraAnnotations = combineAnnotations(expandedType, annotations) val expandedTypeWithExtraAnnotations = expandedType.combineAnnotations(annotations)
return if (withAbbreviatedType) return if (withAbbreviatedType)
expandedTypeWithExtraAnnotations.withAbbreviation(typeAliasExpansion.createAbbreviation(underlyingProjection, annotations)) expandedTypeWithExtraAnnotations.withAbbreviation(typeAliasExpansion.createAbbreviation(underlyingProjection, annotations))
@@ -58,8 +58,8 @@ class TypeAliasExpander(
expandedTypeWithExtraAnnotations expandedTypeWithExtraAnnotations
} }
private fun combineAnnotations(type: SimpleType, annotations: Annotations): SimpleType { private fun SimpleType.combineAnnotations(annotations: Annotations): SimpleType {
val existingAnnotationTypes = type.annotations.getAllAnnotations().mapTo(hashSetOf<KotlinType>()) { it.annotation.type } val existingAnnotationTypes = this.annotations.getAllAnnotations().mapTo(hashSetOf<KotlinType>()) { it.annotation.type }
for (annotation in annotations) { for (annotation in annotations) {
if (annotation.type in existingAnnotationTypes) { if (annotation.type in existingAnnotationTypes) {
@@ -67,7 +67,7 @@ class TypeAliasExpander(
} }
} }
return type.replace(newAnnotations = CompositeAnnotations(listOf(annotations, type.annotations))) return replace(newAnnotations = CompositeAnnotations(listOf(annotations, this.annotations)))
} }
private fun TypeAliasExpansion.createAbbreviation(originalProjection: TypeProjection, annotations: Annotations) = private fun TypeAliasExpansion.createAbbreviation(originalProjection: TypeProjection, annotations: Annotations) =
@@ -85,6 +85,7 @@ class TypeAliasExpander(
typeParameterDescriptor: TypeParameterDescriptor?, typeParameterDescriptor: TypeParameterDescriptor?,
recursionDepth: Int recursionDepth: Int
): TypeProjection { ): TypeProjection {
// TODO refactor TypeSubstitutor to introduce custom diagnostics
assertRecursionDepth(recursionDepth, typeAliasExpansion.descriptor) assertRecursionDepth(recursionDepth, typeAliasExpansion.descriptor)
if (underlyingProjection.isStarProjection) return TypeUtils.makeStarProjection(typeParameterDescriptor!!) if (underlyingProjection.isStarProjection) return TypeUtils.makeStarProjection(typeParameterDescriptor!!)
@@ -100,13 +101,15 @@ class TypeAliasExpander(
val argumentVariance = argument.projectionKind val argumentVariance = argument.projectionKind
val underlyingVariance = underlyingProjection.projectionKind val underlyingVariance = underlyingProjection.projectionKind
val argumentType = argument.type as? SimpleType ?: throw AssertionError("Non-simple type in type alias argument: $argument")
val substitutionVariance = val substitutionVariance =
when { when {
underlyingVariance == argumentVariance -> argumentVariance underlyingVariance == argumentVariance -> argumentVariance
underlyingVariance == Variance.INVARIANT -> argumentVariance underlyingVariance == Variance.INVARIANT -> argumentVariance
argumentVariance == Variance.INVARIANT -> underlyingVariance argumentVariance == Variance.INVARIANT -> underlyingVariance
else -> { else -> {
reportStrategy.conflictingProjection(typeAliasExpansion.descriptor, typeParameterDescriptor, argument.type) reportStrategy.conflictingProjection(typeAliasExpansion.descriptor, typeParameterDescriptor, argumentType)
argumentVariance argumentVariance
} }
} }
@@ -118,12 +121,13 @@ class TypeAliasExpander(
parameterVariance == Variance.INVARIANT -> substitutionVariance parameterVariance == Variance.INVARIANT -> substitutionVariance
substitutionVariance == Variance.INVARIANT -> Variance.INVARIANT substitutionVariance == Variance.INVARIANT -> Variance.INVARIANT
else -> { else -> {
reportStrategy.conflictingProjection(typeAliasExpansion.descriptor, typeParameterDescriptor, argument.type) reportStrategy.conflictingProjection(typeAliasExpansion.descriptor, typeParameterDescriptor, argumentType)
substitutionVariance substitutionVariance
} }
} }
val substitutedType = TypeUtils.makeNullableIfNeeded(argument.type, underlyingType.isMarkedNullable) val substitutedType = TypeUtils.makeNullableIfNeeded(argumentType, underlyingType.isMarkedNullable)
.combineAnnotations(underlyingType.annotations)
return TypeProjectionImpl(resultingVariance, substitutedType) return TypeProjectionImpl(resultingVariance, substitutedType)
} }
@@ -16,14 +16,10 @@
package org.jetbrains.kotlin.resolve package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.TypeProjection import org.jetbrains.kotlin.types.TypeProjection
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.typeUtil.contains
class TypeAliasExpansion private constructor( class TypeAliasExpansion private constructor(
val parent: TypeAliasExpansion?, val parent: TypeAliasExpansion?,
@@ -1,7 +1,7 @@
package package
public val ca1: CA<kotlin.Int> /* = C<kotlin.Int> */ public val ca1: CA<kotlin.Int> /* = C<kotlin.Int> */
public val ca2: CA<CA<kotlin.Int> /* = C<kotlin.Int> */> /* = C<CA<kotlin.Int> /* = C<kotlin.Int> */> */ public val ca2: CA<CA<kotlin.Int> /* = C<kotlin.Int> */> /* = C<C<kotlin.Int>> */
public val ca3: CA<C<kotlin.Int>> /* = C<C<kotlin.Int>> */ public val ca3: CA<C<kotlin.Int>> /* = C<C<kotlin.Int>> */
public val ca4: CA<kotlin.Int?> /* = C<kotlin.Int?> */ public val ca4: CA<kotlin.Int?> /* = C<kotlin.Int?> */
@@ -34,7 +34,7 @@ public final class Test4 : IT<*> /* = I<*> */ {
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
public final class Test5 : IT<IT<*> /* = I<*> */> /* = I<IT<*> /* = I<*> */> */ { public final class Test5 : IT<IT<*> /* = I<*> */> /* = I<I<*>> */ {
public constructor Test5() public constructor Test5()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
@@ -0,0 +1,11 @@
@Target(AnnotationTarget.TYPE)
annotation class Ann1
@Target(AnnotationTarget.TYPE)
annotation class Ann2
class C<T>
typealias CA<T> = C<@Ann1 T>
fun test(x: CA<@Ann2 Int>) = x
@@ -0,0 +1,25 @@
package
public fun test(/*0*/ x: CA<@Ann2 kotlin.Int> /* = C<@Ann1 @Ann2 kotlin.Int> */): CA<@Ann2 kotlin.Int> /* = C<@Ann1 @Ann2 kotlin.Int> */
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class Ann1 : kotlin.Annotation {
public constructor Ann1()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class Ann2 : kotlin.Annotation {
public constructor Ann2()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class C</*0*/ T> {
public constructor C</*0*/ T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public typealias CA</*0*/ T> = C<@Ann1 T>
@@ -21286,6 +21286,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("typealiasRhsAnnotationsInArguments.kt")
public void testTypealiasRhsAnnotationsInArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typealiasRhsAnnotationsInArguments.kt");
doTest(fileName);
}
@TestMetadata("typealiasRhsRepeatedAnnotations.kt") @TestMetadata("typealiasRhsRepeatedAnnotations.kt")
public void testTypealiasRhsRepeatedAnnotations() throws Exception { public void testTypealiasRhsRepeatedAnnotations() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typealiasRhsRepeatedAnnotations.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typealiasRhsRepeatedAnnotations.kt");