From 0d40022d6de4de1d8dfbdb9b470f0acb35506d9d Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Thu, 4 Feb 2021 11:42:52 +0300 Subject: [PATCH] Add reporting of the warnings based on Java annotations for expanded type aliases Before that, such warnings weren't reported as the corresponding errors were reported during type inference (only original types took part there) --- .../src/org/jetbrains/kotlin/container/Dsl.kt | 4 ++ .../kotlin/resolve/PlatformConfigurator.kt | 3 +- .../jvm/checkers/JavaNullabilityChecker.kt | 13 +++-- ...er.kt => WarningAwareUpperBoundChecker.kt} | 43 ++++++++++---- .../jvm/platform/JvmPlatformConfigurator.kt | 17 +++--- .../kotlin/analyzer/common/CommonPlatform.kt | 3 +- .../jetbrains/kotlin/frontend/di/injection.kt | 2 +- .../kotlin/resolve/UpperBoundChecker.kt | 58 ++++++++++--------- .../DiagnosticReporterByTrackingStrategy.kt | 6 +- .../boundViolationInTypeAliasConstructor.kt | 6 +- ...peArgumentsInferenceWithNestedCalls.fir.kt | 14 ++++- ...orTypeArgumentsInferenceWithNestedCalls.kt | 16 ++++- ...peArgumentsInferenceWithNestedCalls.ni.txt | 14 ----- ...rTypeArgumentsInferenceWithNestedCalls.txt | 13 ++++- .../java/checkEnhancedUpperBounds.fir.kt | 16 ++--- .../java/checkEnhancedUpperBounds.kt | 6 +- ...dUpperBoundsWithEnabledImprovements.fir.kt | 16 ++--- .../ClassTypeParameterBoundWithWarnings.kt | 4 +- .../kotlin/types/TypeWithEnhancement.kt | 31 ++++++++-- .../CompositeResolverForModuleFactory.kt | 9 ++- .../js/resolve/JsPlatformConfigurator.kt | 3 +- .../platform/NativePlatformConfigurator.kt | 3 +- 22 files changed, 186 insertions(+), 114 deletions(-) rename compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/{EnhancedUpperBoundChecker.kt => WarningAwareUpperBoundChecker.kt} (58%) delete mode 100644 compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.ni.txt diff --git a/compiler/container/src/org/jetbrains/kotlin/container/Dsl.kt b/compiler/container/src/org/jetbrains/kotlin/container/Dsl.kt index 3f90482fdce..ab2015861d2 100644 --- a/compiler/container/src/org/jetbrains/kotlin/container/Dsl.kt +++ b/compiler/container/src/org/jetbrains/kotlin/container/Dsl.kt @@ -29,6 +29,10 @@ inline fun StorageComponentContainer.useImpl() { registerSingleton(T::class.java) } +inline fun StorageComponentContainer.useImplIf(cond: Boolean) { + if (cond) useImpl() +} + inline fun ComponentProvider.get(): T { return getService(T::class.java) } diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/resolve/PlatformConfigurator.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/resolve/PlatformConfigurator.kt index a7342ed3ac7..5ce1dd39146 100644 --- a/compiler/frontend.common/src/org/jetbrains/kotlin/resolve/PlatformConfigurator.kt +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/resolve/PlatformConfigurator.kt @@ -5,10 +5,11 @@ package org.jetbrains.kotlin.resolve +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.container.StorageComponentContainer interface PlatformConfigurator { val platformSpecificContainer: StorageComponentContainer - fun configureModuleComponents(container: StorageComponentContainer) + fun configureModuleComponents(container: StorageComponentContainer, languageVersionSettings: LanguageVersionSettings) fun configureModuleDependentCheckers(container: StorageComponentContainer) } \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaNullabilityChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaNullabilityChecker.kt index c3462845953..4677b70b5f1 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaNullabilityChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaNullabilityChecker.kt @@ -21,11 +21,9 @@ import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtPostfixExpression -import org.jetbrains.kotlin.psi.KtWhenExpression +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.UpperBoundChecker import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext @@ -43,14 +41,17 @@ import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.makeNotNullable -class JavaNullabilityChecker : AdditionalTypeChecker { - +class JavaNullabilityChecker(val upperBoundChecker: UpperBoundChecker) : AdditionalTypeChecker { override fun checkType( expression: KtExpression, expressionType: KotlinType, expressionTypeWithSmartCast: KotlinType, c: ResolutionContext<*> ) { + if (expressionType is AbbreviatedType) { + upperBoundChecker.checkBoundsOfExpandedTypeAlias(expressionType.expandedType, expression, c.trace) + } + val dataFlowValue by lazy(LazyThreadSafetyMode.NONE) { c.dataFlowValueFactory.createDataFlowValue(expression, expressionType, c) } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/EnhancedUpperBoundChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/WarningAwareUpperBoundChecker.kt similarity index 58% rename from compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/EnhancedUpperBoundChecker.kt rename to compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/WarningAwareUpperBoundChecker.kt index 0a2c5fa18e4..7c2fababedb 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/EnhancedUpperBoundChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/WarningAwareUpperBoundChecker.kt @@ -5,10 +5,9 @@ package org.jetbrains.kotlin.resolve.jvm.checkers -import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.UpperBoundChecker @@ -18,8 +17,17 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.UPPER_BOUND_VIOLAT import org.jetbrains.kotlin.types.* // TODO: remove this checker after removing support LV < 1.6 -class EnhancedUpperBoundChecker(languageVersionSettings: LanguageVersionSettings) : UpperBoundChecker(languageVersionSettings) { - val isTypeEnhancementImprovementsEnabled = languageVersionSettings.supportsFeature(LanguageFeature.ImprovementsAroundTypeEnhancement) +class WarningAwareUpperBoundChecker : UpperBoundChecker() { + override fun checkBoundsOfExpandedTypeAlias(type: KotlinType, expression: KtExpression, trace: BindingTrace) { + val typeParameters = type.constructor.parameters + + for ((index, arg) in type.arguments.withIndex()) { + checkBounds( + null, arg.type, typeParameters[index], TypeSubstitutor.create(type), trace, expression, + withOnlyCheckForWarning = true + ) + } + } override fun checkBounds( argumentReference: KtTypeReference?, @@ -28,6 +36,21 @@ class EnhancedUpperBoundChecker(languageVersionSettings: LanguageVersionSettings substitutor: TypeSubstitutor, trace: BindingTrace, typeAliasUsageElement: KtElement? + ) { + checkBounds( + argumentReference, argumentType, typeParameterDescriptor, substitutor, trace, typeAliasUsageElement, + withOnlyCheckForWarning = false + ) + } + + fun checkBounds( + argumentReference: KtTypeReference?, + argumentType: KotlinType, + typeParameterDescriptor: TypeParameterDescriptor, + substitutor: TypeSubstitutor, + trace: BindingTrace, + typeAliasUsageElement: KtElement?, + withOnlyCheckForWarning: Boolean = false ) { if (typeParameterDescriptor.upperBounds.isEmpty()) return @@ -39,13 +62,13 @@ class EnhancedUpperBoundChecker(languageVersionSettings: LanguageVersionSettings ) for (bound in typeParameterDescriptor.upperBounds) { - val isCheckPassed = checkBound(bound, argumentType, argumentReference, substitutor, typeAliasUsageElement, diagnosticsReporter) + if (!withOnlyCheckForWarning) { + val isBaseCheckPassed = + checkBound(bound, argumentType, argumentReference, substitutor, typeAliasUsageElement, diagnosticsReporter) - // The error is already reported, it's unnecessary to do more checks - if (!isCheckPassed) continue - - // If improvements are enabled, then type parameter's upper bounds will already enhanced, and the error will reported inside the first check - if (isTypeEnhancementImprovementsEnabled) continue + // The error is already reported, it's unnecessary to do more checks + if (!isBaseCheckPassed) continue + } val enhancedBound = bound.getEnhancementDeeply() ?: continue diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt index 07a7924d721..f95625be0c8 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt @@ -6,10 +6,9 @@ package org.jetbrains.kotlin.resolve.jvm.platform import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMapper -import org.jetbrains.kotlin.container.PlatformExtensionsClashResolver -import org.jetbrains.kotlin.container.StorageComponentContainer -import org.jetbrains.kotlin.container.useImpl -import org.jetbrains.kotlin.container.useInstance +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.container.* import org.jetbrains.kotlin.load.java.sam.JvmSamConversionOracle import org.jetbrains.kotlin.resolve.PlatformConfiguratorBase import org.jetbrains.kotlin.resolve.checkers.BigFunctionTypeAvailabilityChecker @@ -61,7 +60,6 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase( ), additionalTypeCheckers = listOf( - JavaNullabilityChecker(), RuntimeAssertionsTypeChecker, JavaGenericVarianceViolationTypeChecker, JavaTypeAccessibilityChecker(), @@ -95,9 +93,13 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase( declarationReturnTypeSanitizer = JvmDeclarationReturnTypeSanitizer ) { - override fun configureModuleComponents(container: StorageComponentContainer) { + override fun configureModuleComponents(container: StorageComponentContainer, languageVersionSettings: LanguageVersionSettings) { + container.useImplIf( + !languageVersionSettings.supportsFeature(LanguageFeature.ImprovementsAroundTypeEnhancement) + ) + + container.useImpl() container.useImpl() - container.useImpl() container.useImpl() container.useImpl() container.useImpl() @@ -112,6 +114,7 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase( container.useImpl() container.useImpl() container.useImpl() + container.useInstance(FunctionWithBigAritySupport.LanguageVersionDependent) container.useInstance(GenericArrayClassLiteralSupport.Enabled) container.useInstance(JavaActualAnnotationArgumentExtractor()) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/common/CommonPlatform.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/common/CommonPlatform.kt index f6b55605db5..c3a6f2d984f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/common/CommonPlatform.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/common/CommonPlatform.kt @@ -6,12 +6,13 @@ package org.jetbrains.kotlin.analyzer.common import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.container.StorageComponentContainer import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.storage.StorageManager private object CommonPlatformConfigurator : PlatformConfiguratorBase() { - override fun configureModuleComponents(container: StorageComponentContainer) {} + override fun configureModuleComponents(container: StorageComponentContainer, languageVersionSettings: LanguageVersionSettings) {} } object CommonPlatformAnalyzerServices : PlatformDependentAnalyzerServices() { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt index 20b936b0438..558c904c5c6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt @@ -73,7 +73,7 @@ fun StorageComponentContainer.configureModule( useInstance(nonTrivialPlatformVersion ?: TargetPlatformVersion.NoVersion) - analyzerServices.platformConfigurator.configureModuleComponents(this) + analyzerServices.platformConfigurator.configureModuleComponents(this, languageVersionSettings) analyzerServices.platformConfigurator.configureModuleDependentCheckers(this) for (extension in StorageComponentContainerContributor.getInstances(moduleContext.project)) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/UpperBoundChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/UpperBoundChecker.kt index 2b29e5cbb9b..72a7a59e9c2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/UpperBoundChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/UpperBoundChecker.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.resolve -import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.container.DefaultImplementation import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor @@ -13,7 +12,9 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2 import org.jetbrains.kotlin.diagnostics.DiagnosticFactory3 import org.jetbrains.kotlin.diagnostics.Errors.UPPER_BOUND_VIOLATED import org.jetbrains.kotlin.diagnostics.Errors.UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION +import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext import org.jetbrains.kotlin.types.* @@ -21,7 +22,28 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.typeUtil.containsTypeAliasParameters @DefaultImplementation(impl = UpperBoundChecker::class) -open class UpperBoundChecker(val languageVersionSettings: LanguageVersionSettings) { +open class UpperBoundChecker { + open fun checkBoundsOfExpandedTypeAlias(type: KotlinType, expression: KtExpression, trace: BindingTrace) { + // do nothing in the strict mode as the errors are already reported in the type inference if necessary + } + + open fun checkBounds( + argumentReference: KtTypeReference?, + argumentType: KotlinType, + typeParameterDescriptor: TypeParameterDescriptor, + substitutor: TypeSubstitutor, + trace: BindingTrace, + typeAliasUsageElement: KtElement? = null, + ) { + if (typeParameterDescriptor.upperBounds.isEmpty()) return + + val diagnosticsReporter = UpperBoundViolatedReporter(trace, argumentType, typeParameterDescriptor) + + for (bound in typeParameterDescriptor.upperBounds) { + checkBound(bound, argumentType, argumentReference, substitutor, typeAliasUsageElement, diagnosticsReporter) + } + } + fun checkBounds(typeReference: KtTypeReference, type: KotlinType, trace: BindingTrace) { if (type.isError) return @@ -58,23 +80,6 @@ open class UpperBoundChecker(val languageVersionSettings: LanguageVersionSetting } } - open fun checkBounds( - argumentReference: KtTypeReference?, - argumentType: KotlinType, - typeParameterDescriptor: TypeParameterDescriptor, - substitutor: TypeSubstitutor, - trace: BindingTrace, - typeAliasUsageElement: KtElement? = null, - ) { - if (typeParameterDescriptor.upperBounds.isEmpty()) return - - val diagnosticsReporter = UpperBoundViolatedReporter(trace, argumentType, typeParameterDescriptor) - - for (bound in typeParameterDescriptor.upperBounds) { - checkBound(bound, argumentType, argumentReference, substitutor, typeAliasUsageElement, diagnosticsReporter) - } - } - protected fun checkBound( bound: KotlinType, argumentType: KotlinType, @@ -99,18 +104,17 @@ open class UpperBoundChecker(val languageVersionSettings: LanguageVersionSetting } class UpperBoundViolatedReporter( - val trace: BindingTrace, - val argumentType: KotlinType, - val typeParameterDescriptor: TypeParameterDescriptor? = null, - val baseDiagnostic: DiagnosticFactory2 = UPPER_BOUND_VIOLATED, - val diagnosticForTypeAliases: DiagnosticFactory3 = UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION + private val trace: BindingTrace, + private val argumentType: KotlinType, + private val typeParameterDescriptor: TypeParameterDescriptor, + private val baseDiagnostic: DiagnosticFactory2 = UPPER_BOUND_VIOLATED, + private val diagnosticForTypeAliases: DiagnosticFactory3 = UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION ) { fun report(typeArgumentReference: KtTypeReference, substitutedBound: KotlinType) { - trace.report(baseDiagnostic.on(typeArgumentReference, substitutedBound, argumentType)) + trace.reportDiagnosticOnce(baseDiagnostic.on(typeArgumentReference, substitutedBound, argumentType)) } fun reportForTypeAliasExpansion(callElement: KtElement, substitutedBound: KotlinType) { - if (typeParameterDescriptor == null) return - trace.report(diagnosticForTypeAliases.on(callElement, substitutedBound, argumentType, typeParameterDescriptor)) + trace.reportDiagnosticOnce(diagnosticForTypeAliases.on(callElement, substitutedBound, argumentType, typeParameterDescriptor)) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt index ad0373ae391..7398559c52d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -15,8 +15,6 @@ import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.isNull import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.UpperBoundChecker -import org.jetbrains.kotlin.resolve.UpperBoundViolatedReporter import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.reportTrailingLambdaErrorOr @@ -395,8 +393,8 @@ class DiagnosticReporterByTrackingStrategy( } (position as? ExplicitTypeParameterConstraintPositionImpl)?.let { - UpperBoundViolatedReporter(trace, error.upperKotlinType) - .report((it.typeArgument as SimpleTypeArgumentImpl).typeReference, error.lowerKotlinType) + val typeArgumentReference = (it.typeArgument as SimpleTypeArgumentImpl).typeReference + trace.report(UPPER_BOUND_VIOLATED.on(typeArgumentReference, error.upperKotlinType, error.lowerKotlinType)) } (position as? FixVariableConstraintPositionImpl)?.let { diff --git a/compiler/testData/diagnostics/tests/typealias/boundViolationInTypeAliasConstructor.kt b/compiler/testData/diagnostics/tests/typealias/boundViolationInTypeAliasConstructor.kt index ac96526df5b..9e236b31464 100644 --- a/compiler/testData/diagnostics/tests/typealias/boundViolationInTypeAliasConstructor.kt +++ b/compiler/testData/diagnostics/tests/typealias/boundViolationInTypeAliasConstructor.kt @@ -13,6 +13,6 @@ class TColl> typealias TC = TColl typealias TC2 = TC -val y1 = TCollAny>() -val y2 = TCAny>() -val y3 = TC2Any>() +val y1 = TCollAny>() +val y2 = TCAny>() +val y3 = TC2Any>() diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.fir.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.fir.kt index 7f8a87e86f3..b09e808a9d6 100644 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.fir.kt @@ -1,8 +1,18 @@ -// !WITH_NEW_INFERENCE -// NI_EXPECTED_FILE +// FULL_JDK +// FILE: MapLike.java +import java.util.Map; + +public class MapLike<@org.jetbrains.annotations.NotNull K> { + MapLike(K x) { } +} + +// FILE: main.kt class Cons(val head: T, val tail: Cons?) typealias C = Cons +typealias C2 = MapLike val test1 = C(1, C(2, null)) val test2 = C(1, C("", null)) +val test23 = C2(if (true) 1 else null) +val test234 = C2(C2(if (true) 1 else null)) diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.kt index 75f5863535f..79691b4f1bd 100644 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.kt +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.kt @@ -1,8 +1,18 @@ -// !WITH_NEW_INFERENCE -// NI_EXPECTED_FILE +// FULL_JDK +// FILE: MapLike.java +import java.util.Map; + +public class MapLike<@org.jetbrains.annotations.NotNull K> { + MapLike(K x) { } +} + +// FILE: main.kt class Cons(val head: T, val tail: Cons?) typealias C = Cons +typealias C2 = MapLike val test1 = C(1, C(2, null)) -val test2 = C(1, C("", null)) +val test2 = C(1, C("", null)) +val test23 = C2(if (true) 1 else null) +val test234 = C2(C2(if (true) 1 else null)) diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.ni.txt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.ni.txt deleted file mode 100644 index e22126a7d77..00000000000 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.ni.txt +++ /dev/null @@ -1,14 +0,0 @@ -package - -public val test1: C /* = Cons */ -public val test2: Cons - -public final class Cons { - public constructor Cons(/*0*/ head: T, /*1*/ tail: Cons?) - public final val head: T - public final val tail: Cons? - 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 C = Cons diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.txt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.txt index 10d357efcdc..24c31fabc9b 100644 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.txt +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.txt @@ -1,7 +1,9 @@ package public val test1: C /* = Cons */ -public val test2: C /* = Cons */ +public val test2: Cons +public val test23: C2 /* = MapLike */ +public val test234: C2<(C2 /* = MapLike */..C2? /* = MapLike? */)> /* = MapLike<(C2 /* = MapLike */..C2? /* = MapLike? */)> */ public final class Cons { public constructor Cons(/*0*/ head: T, /*1*/ tail: Cons?) @@ -11,4 +13,13 @@ public final class Cons { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + +public open class MapLike { + public/*package*/ constructor MapLike(/*0*/ x: K!) + 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 C = Cons +public typealias C2 = MapLike + diff --git a/compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBounds.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBounds.fir.kt index c74590f7a23..13b6e46077b 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBounds.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBounds.fir.kt @@ -14,11 +14,11 @@ import java.util.Collection; public class ListLike> {} // FILE: main.kt -fun test0(map : MapLike<Int?, Int>) {} -fun test11(map : MapLike<K, K>) {} -fun test12(map : MapLike<K?, K>) {} +fun test0(map : MapLike) {} +fun test11(map : MapLike) {} +fun test12(map : MapLike) {} fun test13(map : MapLike) {} -fun test14(map : MapLike<K?, K>) {} +fun test14(map : MapLike) {} class Foo @@ -26,11 +26,11 @@ typealias A = MapLike typealias A2 = Foo> typealias A3 = ListLike> -fun main1(x: A<Int?>) {} -fun main2(x: A2<Int?>) {} -fun main3(x: A3) {} +fun main1(x: A) {} +fun main2(x: A2) {} +fun main3(x: A3) {} fun main3() { val x = A3() // TODO: support reporting errors on typealias constructor calls val x2 = A() // TODO: support reporting errors on typealias constructor calls - val y: A3 = A3() + val y: A3 = A3() } diff --git a/compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBounds.kt b/compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBounds.kt index c74590f7a23..556657578d8 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBounds.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBounds.kt @@ -30,7 +30,7 @@ fun main1(x: A<Int?>) {} fun main2(x: A2<Int?>) {} fun main3(x: A3) {} fun main3() { - val x = A3() // TODO: support reporting errors on typealias constructor calls - val x2 = A() // TODO: support reporting errors on typealias constructor calls - val y: A3 = A3() + val x = A3() // TODO: support reporting errors on typealias constructor calls + val x2 = A() // TODO: support reporting errors on typealias constructor calls + val y: A3 = A3() } diff --git a/compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBoundsWithEnabledImprovements.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBoundsWithEnabledImprovements.fir.kt index a64a67bac51..bfc6b0c7b4d 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBoundsWithEnabledImprovements.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/java/checkEnhancedUpperBoundsWithEnabledImprovements.fir.kt @@ -15,11 +15,11 @@ import java.util.Collection; public class ListLike> {} // FILE: main.kt -fun test0(map : MapLike<Int?, Int>) {} -fun test11(map : MapLike<K, K>) {} -fun test12(map : MapLike<K?, K>) {} +fun test0(map : MapLike) {} +fun test11(map : MapLike) {} +fun test12(map : MapLike) {} fun test13(map : MapLike) {} -fun test14(map : MapLike<K?, K>) {} +fun test14(map : MapLike) {} class Foo @@ -27,11 +27,11 @@ typealias A = MapLike typealias A2 = Foo> typealias A3 = ListLike> -fun main1(x: A<Int?>) {} -fun main2(x: A2<Int?>) {} -fun main3(x: A3) {} +fun main1(x: A) {} +fun main2(x: A2) {} +fun main3(x: A3) {} fun main3() { val x = A3() // TODO: support reporting errors on typealias constructor calls val x2 = A() - val y: A3 = A3() + val y: A3 = A3() } diff --git a/compiler/testData/foreignAnnotations/java8Tests/typeEnhancementOnCompiledJava/ClassTypeParameterBoundWithWarnings.kt b/compiler/testData/foreignAnnotations/java8Tests/typeEnhancementOnCompiledJava/ClassTypeParameterBoundWithWarnings.kt index 29f07a9f8e4..184846a4b67 100644 --- a/compiler/testData/foreignAnnotations/java8Tests/typeEnhancementOnCompiledJava/ClassTypeParameterBoundWithWarnings.kt +++ b/compiler/testData/foreignAnnotations/java8Tests/typeEnhancementOnCompiledJava/ClassTypeParameterBoundWithWarnings.kt @@ -3,13 +3,13 @@ // SKIP_TXT // TODO: report warnings "UPPER_BOUND_VIOLATED" -fun main(x: ClassTypeParameterBoundWithWarnings, y: ClassTypeParameterBoundWithWarnings, a: String?, b: String) { +fun main(x: ClassTypeParameterBoundWithWarnings<String?>, y: ClassTypeParameterBoundWithWarnings, a: String?, b: String) { val x2 = ClassTypeParameterBoundWithWarnings() val y2 = ClassTypeParameterBoundWithWarnings() val x3 = ClassTypeParameterBoundWithWarnings(a) val y3 = ClassTypeParameterBoundWithWarnings(b) - val x4: ClassTypeParameterBoundWithWarnings = ClassTypeParameterBoundWithWarnings() + val x4: ClassTypeParameterBoundWithWarnings<String?> = ClassTypeParameterBoundWithWarnings() val y4: ClassTypeParameterBoundWithWarnings = ClassTypeParameterBoundWithWarnings() } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeWithEnhancement.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeWithEnhancement.kt index b5f179ad799..ca53bc49873 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeWithEnhancement.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeWithEnhancement.kt @@ -88,7 +88,7 @@ fun KotlinType.getEnhancement(): KotlinType? = when (this) { else -> null } -private fun List.enhanceTypeArguments(depth: Int) = +private fun List.enhanceTypeArguments() = map { argument -> // TODO: think about star projections with enhancement (e.g. came from Java: Foo<@NotNull ?>) if (argument.isStarProjection) { @@ -96,15 +96,34 @@ private fun List.enhanceTypeArguments(depth: Int) = } val argumentType = argument.type val enhancedArgumentType = if (argumentType is TypeWithEnhancement) argumentType.enhancement else argumentType - val enhancedDeeplyArgumentType = enhancedArgumentType.getEnhancementDeeply(depth + 1) + val enhancedDeeplyArgumentType = enhancedArgumentType.getEnhancementDeeplyInternal() + + if (argumentType === enhancedDeeplyArgumentType) return@map argument argument.replaceType(enhancedDeeplyArgumentType) } -private fun KotlinType.getEnhancementDeeply(depth: Int): KotlinType { - val newArguments = arguments.enhanceTypeArguments(depth) - val newArgumentsForUpperBound = if (this is FlexibleType) upperBound.arguments.enhanceTypeArguments(depth) else newArguments +private fun List.wereTypeArgumentsChanged(newArguments: List) = + newArguments.size != this.size || !this.withIndex().all { (i, arg) -> newArguments[i] === arg } + +private fun KotlinType.wereTypeArgumentsChanged(newArguments: List, newArgumentsForUpperBound: List) = + when (val type = unwrap()) { + is FlexibleType -> { + type.lowerBound.arguments.wereTypeArgumentsChanged(newArguments) || + type.upperBound.arguments.wereTypeArgumentsChanged(newArgumentsForUpperBound) + } + else -> { + type.arguments.wereTypeArgumentsChanged(newArguments) + } + } + +private fun KotlinType.getEnhancementDeeplyInternal(): KotlinType { + val newArguments = arguments.enhanceTypeArguments() + val newArgumentsForUpperBound = if (this is FlexibleType) upperBound.arguments.enhanceTypeArguments() else newArguments val enhancedType = if (this is TypeWithEnhancement) enhancement else this + val areArgumentsChanged = enhancedType.wereTypeArgumentsChanged(newArguments, newArgumentsForUpperBound) + + if (!areArgumentsChanged) return enhancedType return enhancedType.replace( newArguments = newArguments, @@ -113,7 +132,7 @@ private fun KotlinType.getEnhancementDeeply(depth: Int): KotlinType { } fun KotlinType.getEnhancementDeeply(): KotlinType? { - val enhancedTypeWithArguments = getEnhancementDeeply(depth = 0) + val enhancedTypeWithArguments = getEnhancementDeeplyInternal() if (enhancedTypeWithArguments === this) return null diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CompositeResolverForModuleFactory.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CompositeResolverForModuleFactory.kt index 3a3d7cefa66..80534bfa3fd 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CompositeResolverForModuleFactory.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/caches/resolve/CompositeResolverForModuleFactory.kt @@ -224,7 +224,7 @@ class CompositeResolverForModuleFactory( } class CompositeAnalyzerServices(val services: List) : PlatformDependentAnalyzerServices() { - override val platformConfigurator: PlatformConfigurator = CompositePlatformConigurator(services.map { it.platformConfigurator }) + override val platformConfigurator: PlatformConfigurator = CompositePlatformConfigurator(services.map { it.platformConfigurator }) override fun computePlatformSpecificDefaultImports(storageManager: StorageManager, result: MutableList) { val intersectionOfDefaultImports = services.map { service -> @@ -247,7 +247,7 @@ class CompositeAnalyzerServices(val services: List first.intersect(second) }.toList() } -class CompositePlatformConigurator(private val componentConfigurators: List) : PlatformConfigurator { +class CompositePlatformConfigurator(private val componentConfigurators: List) : PlatformConfigurator { override val platformSpecificContainer: StorageComponentContainer get() = composeContainer(this::class.java.simpleName) { configureDefaultCheckers() @@ -256,8 +256,8 @@ class CompositePlatformConigurator(private val componentConfigurators: List() - container.useImpl() } } \ No newline at end of file diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt index f7097f5a3c3..5cbd2b9d11e 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.js.resolve +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.container.StorageComponentContainer import org.jetbrains.kotlin.container.useImpl import org.jetbrains.kotlin.container.useInstance @@ -34,7 +35,7 @@ object JsPlatformConfigurator : PlatformConfiguratorBase( ), identifierChecker = JsIdentifierChecker ) { - override fun configureModuleComponents(container: StorageComponentContainer) { + override fun configureModuleComponents(container: StorageComponentContainer, languageVersionSettings: LanguageVersionSettings) { container.useInstance(NameSuggestion()) container.useImpl() container.useImpl() diff --git a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/platform/NativePlatformConfigurator.kt b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/platform/NativePlatformConfigurator.kt index 35a53f10e57..04eb768078f 100644 --- a/native/frontend/src/org/jetbrains/kotlin/resolve/konan/platform/NativePlatformConfigurator.kt +++ b/native/frontend/src/org/jetbrains/kotlin/resolve/konan/platform/NativePlatformConfigurator.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.resolve.konan.platform +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.container.StorageComponentContainer import org.jetbrains.kotlin.container.useImpl import org.jetbrains.kotlin.container.useInstance @@ -30,7 +31,7 @@ object NativePlatformConfigurator : PlatformConfiguratorBase( NativeTopLevelSingletonChecker, NativeThreadLocalChecker ) ) { - override fun configureModuleComponents(container: StorageComponentContainer) { + override fun configureModuleComponents(container: StorageComponentContainer, languageVersionSettings: LanguageVersionSettings) { container.useInstance(NativeInliningRule) }