diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirSinceKotlinHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirSinceKotlinHelpers.kt index 601a749cabf..f7fcb29f27b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirSinceKotlinHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirSinceKotlinHelpers.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.coneType -import org.jetbrains.kotlin.resolve.SINCE_KOTLIN_FQ_NAME +import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.resolve.checkers.OptInNames sealed class FirSinceKotlinAccessibility { @@ -65,7 +65,7 @@ private fun FirAnnotatedDeclaration.getOwnSinceKotlinVersion(session: FirSession // TODO: use-site targeted annotations fun FirAnnotatedDeclaration.consider() { - val sinceKotlinSingleArgument = getAnnotationByFqName(SINCE_KOTLIN_FQ_NAME)?.arguments?.singleOrNull() + val sinceKotlinSingleArgument = getAnnotationByClassId(StandardClassIds.SinceKotlin)?.arguments?.singleOrNull() val apiVersion = ((sinceKotlinSingleArgument as? FirConstExpression<*>)?.value as? String)?.let(ApiVersion.Companion::parse) if (apiVersion != null) { // TODO: combine wasExperimentalMarkerClasses in case of several associated declarations with the same maximal API version diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirClassVarianceChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirClassVarianceChecker.kt index 231030ca886..a1b843ea8ae 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirClassVarianceChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirClassVarianceChecker.kt @@ -18,8 +18,8 @@ import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.types.EnrichedProjectionKind import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure object FirClassVarianceChecker : FirClassChecker() { override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { @@ -148,11 +148,11 @@ object FirClassVarianceChecker : FirClassChecker() { val typeArgumentType = typeArgument.type ?: continue - val newVariance = when (TypeCheckingProcedure.getEffectiveProjectionKind(paramVariance, argVariance)!!) { - TypeCheckingProcedure.EnrichedProjectionKind.OUT -> variance - TypeCheckingProcedure.EnrichedProjectionKind.IN -> variance.opposite() - TypeCheckingProcedure.EnrichedProjectionKind.INV -> Variance.INVARIANT - TypeCheckingProcedure.EnrichedProjectionKind.STAR -> null // CONFLICTING_PROJECTION error was reported + val newVariance = when (EnrichedProjectionKind.getEffectiveProjectionKind(paramVariance, argVariance)) { + EnrichedProjectionKind.OUT -> variance + EnrichedProjectionKind.IN -> variance.opposite() + EnrichedProjectionKind.INV -> Variance.INVARIANT + EnrichedProjectionKind.STAR -> null // CONFLICTING_PROJECTION error was reported } if (newVariance != null) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOperatorModifierChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOperatorModifierChecker.kt index 50686eec512..a8bedd0f8c2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOperatorModifierChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOperatorModifierChecker.kt @@ -10,7 +10,6 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration -import javaslang.Function2 import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.declaration.Checks.Returns @@ -83,12 +82,15 @@ object FirOperatorModifierChecker : FirSimpleFunctionChecker() { } -interface Check : Function2 { - override fun apply(t1: CheckerContext, t2: FirSimpleFunction): String? = check(t1, t2) +private interface Check : (CheckerContext, FirSimpleFunction) -> String? { + override fun invoke(p1: CheckerContext, p2: FirSimpleFunction): String? { + return check(p1, p2) + } + fun check(context: CheckerContext, function: FirSimpleFunction): String? } -object Checks { +private object Checks { fun simple(message: String, predicate: (FirSimpleFunction) -> Boolean) = object : Check { override fun check(context: CheckerContext, function: FirSimpleFunction): String? = message.takeIf { !predicate(function) } } @@ -156,10 +158,10 @@ object Checks { } @OptIn(ExperimentalStdlibApi::class) -object OperatorFunctionChecks { +private object OperatorFunctionChecks { //reimplementation of org.jetbrains.kotlin.util.OperatorChecks for FIR - val checksByName: Map> = buildMap> { + val checksByName: Map> = buildMap { checkFor(GET, memberOrExtension, ValueParametersCount.atLeast(1)) checkFor( SET, @@ -218,4 +220,4 @@ object OperatorFunctionChecks { private fun MutableList>>.checkFor(regex: Regex, vararg checks: Check) { add(regex to checks.asList()) } -} \ No newline at end of file +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSuspendCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSuspendCallChecker.kt index 727b54d6e66..4c18ebcd542 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSuspendCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSuspendCallChecker.kt @@ -33,15 +33,13 @@ import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.StandardClassIds -import org.jetbrains.kotlin.resolve.calls.checkers.COROUTINE_CONTEXT_FQ_NAME -import org.jetbrains.kotlin.serialization.deserialization.KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME import org.jetbrains.kotlin.utils.addToStdlib.lastIsInstanceOrNull object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() { private val RESTRICTS_SUSPENSION_CLASS_ID = ClassId(StandardNames.COROUTINES_PACKAGE_FQ_NAME, Name.identifier("RestrictsSuspension")) - private val BUILTIN_SUSPEND_NAME = KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME.shortName() + private val BUILTIN_SUSPEND_NAME = StandardClassIds.suspend.callableName internal val KOTLIN_SUSPEND_BUILT_IN_FUNCTION_CALLABLE_ID = CallableId(StandardClassIds.BASE_KOTLIN_PACKAGE, BUILTIN_SUSPEND_NAME) @@ -56,7 +54,7 @@ object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() { if (reference is FirResolvedCallableReference) return when (symbol) { is FirNamedFunctionSymbol -> if (!symbol.isSuspend) return - is FirPropertySymbol -> if (symbol.callableId.asSingleFqName() != COROUTINE_CONTEXT_FQ_NAME) return + is FirPropertySymbol -> if (symbol.callableId != StandardClassIds.coroutineContext) return else -> return } val enclosingSuspendFunction = findEnclosingSuspendFunction(context) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/VarianceChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/VarianceChecker.kt index c0b258ba51f..af779ddb474 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/VarianceChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/VarianceChecker.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.typeBinding.TypeBinding import org.jetbrains.kotlin.resolve.typeBinding.createTypeBinding import org.jetbrains.kotlin.resolve.typeBinding.createTypeBindingForReturnType +import org.jetbrains.kotlin.types.EnrichedProjectionKind import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance.* @@ -164,10 +165,10 @@ class VarianceCheckerCore( 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 + 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.binding.checkTypePosition(containingType, newPosition) diff --git a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt index 970cc85e0c4..206cf0fa6e1 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt @@ -109,6 +109,11 @@ object StandardClassIds { val EnhancedNullability = ClassId(FqName("kotlin.jvm.internal"), Name.identifier("EnhancedNullability")) val PublishedApi = "PublishedApi".baseId() + + val SinceKotlin = "SinceKotlin".baseId() + + val coroutineContext = CallableId(StandardNames.COROUTINES_PACKAGE_FQ_NAME, Name.identifier("coroutineContext")) + val suspend = CallableId(BASE_KOTLIN_PACKAGE, Name.identifier("suspend")) } private fun Map.inverseMap() = entries.associate { (k, v) -> v to k } diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/EnrichedProjectionKind.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/EnrichedProjectionKind.kt new file mode 100644 index 00000000000..6df2756c453 --- /dev/null +++ b/core/compiler.common/src/org/jetbrains/kotlin/types/EnrichedProjectionKind.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2021 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 + +enum class EnrichedProjectionKind { + IN, OUT, INV, STAR; + + companion object { + @JvmStatic + fun fromVariance(variance: Variance): EnrichedProjectionKind { + return when (variance) { + Variance.INVARIANT -> INV + Variance.IN_VARIANCE -> IN + Variance.OUT_VARIANCE -> OUT + } + } + + // If class C then C and C mean the same + // out * out = out + // out * in = * + // out * inv = out + // + // in * out = * + // in * in = in + // in * inv = in + // + // inv * out = out + // inv * in = out + // inv * inv = inv + fun getEffectiveProjectionKind( + typeParameterVariance: Variance, + typeArgumentVariance: Variance + ): EnrichedProjectionKind { + var a = typeParameterVariance + var b = typeArgumentVariance + + // If they are not both invariant, let's make b not invariant for sure + if (b === Variance.INVARIANT) { + val t = a + a = b + b = t + } + + // Opposites yield STAR + if (a === Variance.IN_VARIANCE && b === Variance.OUT_VARIANCE) { + return STAR + } + return if (a === Variance.OUT_VARIANCE && b === Variance.IN_VARIANCE) { + STAR + } else fromVariance(b) + + // If they are not opposite, return b, because b is either equal to a or b is in/out and a is inv + } + } +} + + diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/TypeCheckingProcedure.java b/core/descriptors/src/org/jetbrains/kotlin/types/checker/TypeCheckingProcedure.java index c7851c09328..454c26b0aec 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/TypeCheckingProcedure.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/TypeCheckingProcedure.java @@ -126,23 +126,6 @@ public class TypeCheckingProcedure { && isSubtypeOf(inflexibleType, FlexibleTypesKt.asFlexibleType(flexibleType).getUpperBound()); } - public enum EnrichedProjectionKind { - IN, OUT, INV, STAR; - - @NotNull - public static EnrichedProjectionKind fromVariance(@NotNull Variance variance) { - switch (variance) { - case INVARIANT: - return INV; - case IN_VARIANCE: - return IN; - case OUT_VARIANCE: - return OUT; - } - throw new IllegalStateException("Unknown variance"); - } - } - public static EnrichedProjectionKind getEffectiveProjectionKind( @NotNull TypeParameterDescriptor typeParameter, @NotNull TypeProjection typeArgument @@ -166,26 +149,7 @@ public class TypeCheckingProcedure { @NotNull Variance typeParameterVariance, @NotNull Variance typeArgumentVariance ) { - Variance a = typeParameterVariance; - Variance b = typeArgumentVariance; - - // If they are not both invariant, let's make b not invariant for sure - if (b == INVARIANT) { - Variance t = a; - a = b; - b = t; - } - - // Opposites yield STAR - if (a == IN_VARIANCE && b == OUT_VARIANCE) { - return EnrichedProjectionKind.STAR; - } - if (a == OUT_VARIANCE && b == IN_VARIANCE) { - return EnrichedProjectionKind.STAR; - } - - // If they are not opposite, return b, because b is either equal to a or b is in/out and a is inv - return EnrichedProjectionKind.fromVariance(b); + return EnrichedProjectionKind.Companion.getEffectiveProjectionKind(typeParameterVariance, typeArgumentVariance); } public boolean isSubtypeOf(@NotNull KotlinType subtype, @NotNull KotlinType supertype) {