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) }