From 11653c6800528e09aa18534a30b11b1ecf5f7bed Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 16 May 2018 18:02:26 +0200 Subject: [PATCH] Move checkTypePosition to VarianceChecker in frontend This is a partial revert of 279ff0b, which is no longer needed because of the previous commit --- .../jetbrains/kotlin/resolve/TypeBinding.kt | 14 ++-- .../kotlin/resolve/VarianceChecker.kt | 44 +++++++++--- .../kotlin/types/AbstractTypeBindingTest.kt | 2 +- .../jetbrains/kotlin/types/VarianceChecker.kt | 67 ------------------- 4 files changed, 43 insertions(+), 84 deletions(-) delete mode 100644 core/descriptors/src/org/jetbrains/kotlin/types/VarianceChecker.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeBinding.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeBinding.kt index 687aea4b095..cbecff90f79 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeBinding.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeBinding.kt @@ -25,14 +25,18 @@ import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.types.* - -interface TypeBinding : TypeHolder> { +interface TypeBinding { val psiElement: P + val type: KotlinType val isInAbbreviation: Boolean - override val arguments: List?> + val arguments: List?> } -interface TypeArgumentBinding : TypeHolderArgument> +interface TypeArgumentBinding { + val projection: TypeProjection + val typeParameter: TypeParameterDescriptor? + val binding: TypeBinding

+} fun KtTypeReference.createTypeBinding(trace: BindingContext): TypeBinding? { val type = trace[BindingContext.TYPE, this] @@ -64,7 +68,7 @@ fun KtCallableDeclaration.createTypeBindingForReturnType(trace: BindingContext): private class TypeArgumentBindingImpl( override val projection: TypeProjection, override val typeParameter: TypeParameterDescriptor?, - override val holder: TypeBinding

+ override val binding: TypeBinding

) : TypeArgumentBinding

private class ExplicitTypeBinding( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/VarianceChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/VarianceChecker.kt index d22e953e12d..41da5b642c7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/VarianceChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/VarianceChecker.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.resolve import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyAccessorDescriptorImpl @@ -34,7 +35,7 @@ import org.jetbrains.kotlin.resolve.typeBinding.createTypeBindingForReturnType import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance.* -import org.jetbrains.kotlin.types.checkTypePosition +import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure class ManualVariance(val descriptor: TypeParameterDescriptor, val variance: Variance) @@ -142,17 +143,38 @@ class VarianceCheckerCore( private fun TypeBinding.checkTypePosition(position: Variance) = checkTypePosition(type, position) - private fun TypeBinding.checkTypePosition(containingType: KotlinType, position: Variance): Boolean = - checkTypePosition( - position, - { typeParameterDescriptor, typeBinding, errorPosition -> - val varianceConflictDiagnosticData = VarianceConflictDiagnosticData(containingType, typeParameterDescriptor, errorPosition) + private fun TypeBinding.checkTypePosition(containingType: KotlinType, position: Variance): Boolean { + val classifierDescriptor = type.constructor.declarationDescriptor + if (classifierDescriptor is TypeParameterDescriptor) { + val declarationVariance = classifierDescriptor.varianceWithManual() + if (!declarationVariance.allowsPosition(position) + && !type.annotations.hasAnnotation(KotlinBuiltIns.FQ_NAMES.unsafeVariance) + ) { + val varianceConflictDiagnosticData = VarianceConflictDiagnosticData(containingType, classifierDescriptor, position) val diagnostic = - if (typeBinding.isInAbbreviation) Errors.TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE else Errors.TYPE_VARIANCE_CONFLICT - diagnosticSink.report(diagnostic.on(typeBinding.psiElement, varianceConflictDiagnosticData)) - }, - customVariance = { it.varianceWithManual() } - ) + if (isInAbbreviation) Errors.TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE else Errors.TYPE_VARIANCE_CONFLICT + diagnosticSink.report(diagnostic.on(psiElement, varianceConflictDiagnosticData)) + } + return declarationVariance.allowsPosition(position) + } + + var noError = true + for (argument in arguments) { + if (argument?.typeParameter == null || argument.projection.isStarProjection) continue + + val projectionKind = TypeCheckingProcedure.getEffectiveProjectionKind(argument.typeParameter!!, argument.projection)!! + val newPosition = when (projectionKind) { + TypeCheckingProcedure.EnrichedProjectionKind.OUT -> position + TypeCheckingProcedure.EnrichedProjectionKind.IN -> position.opposite() + TypeCheckingProcedure.EnrichedProjectionKind.INV -> Variance.INVARIANT + TypeCheckingProcedure.EnrichedProjectionKind.STAR -> null // CONFLICTING_PROJECTION error was reported + } + if (newPosition != null) { + noError = noError and argument.binding.checkTypePosition(containingType, newPosition) + } + } + return noError + } private fun isIrrelevant(descriptor: CallableDescriptor): Boolean { val containingClass = descriptor.containingDeclaration as? ClassDescriptor ?: return true diff --git a/compiler/tests/org/jetbrains/kotlin/types/AbstractTypeBindingTest.kt b/compiler/tests/org/jetbrains/kotlin/types/AbstractTypeBindingTest.kt index c125b8ce480..9005a8138fa 100644 --- a/compiler/tests/org/jetbrains/kotlin/types/AbstractTypeBindingTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/types/AbstractTypeBindingTest.kt @@ -88,7 +88,7 @@ abstract class AbstractTypeBindingTest : KotlinTestWithEnvironment() { if (argument.projection.isStarProjection) printlnWithNoIndent("*") else printlnWithNoIndent("${projection}${argument.projection.type.render()}") - print(argument.holder) + print(argument.binding) return this } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/VarianceChecker.kt b/core/descriptors/src/org/jetbrains/kotlin/types/VarianceChecker.kt deleted file mode 100644 index d760ef9c3e5..00000000000 --- a/core/descriptors/src/org/jetbrains/kotlin/types/VarianceChecker.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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.types - -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure -import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure.EnrichedProjectionKind -import org.jetbrains.kotlin.utils.DO_NOTHING_3 - -interface TypeHolder> { - val type: KotlinType - val arguments: List?> -} - -interface TypeHolderArgument> { - val projection: TypeProjection - val typeParameter: TypeParameterDescriptor? - val holder: D -} - -fun > D.checkTypePosition( - position: Variance, - reportError: (TypeParameterDescriptor, D, Variance) -> Unit = DO_NOTHING_3, - customVariance: (TypeParameterDescriptor) -> Variance? = { null } -): Boolean { - val classifierDescriptor = type.constructor.declarationDescriptor - if (classifierDescriptor is TypeParameterDescriptor) { - val declarationVariance = customVariance(classifierDescriptor) ?: classifierDescriptor.variance - if (!declarationVariance.allowsPosition(position) - && !type.annotations.hasAnnotation(org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES.unsafeVariance) - ) { - reportError(classifierDescriptor, this, position) - } - return declarationVariance.allowsPosition(position) - } - - var noError = true - for (argument in arguments) { - if (argument?.typeParameter == null || argument.projection.isStarProjection) continue - - val projectionKind = TypeCheckingProcedure.getEffectiveProjectionKind(argument.typeParameter!!, argument.projection)!! - val newPosition = when (projectionKind) { - EnrichedProjectionKind.OUT -> position - EnrichedProjectionKind.IN -> position.opposite() - EnrichedProjectionKind.INV -> Variance.INVARIANT - EnrichedProjectionKind.STAR -> null // CONFLICTING_PROJECTION error was reported - } - if (newPosition != null) { - noError = noError and argument.holder.checkTypePosition(newPosition, reportError, customVariance) - } - } - return noError -}