diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 01e91d34924..e6bef57faf9 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -4539,6 +4539,24 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/checkArguments/kt1940.kt"); } + @Test + @TestMetadata("kt49276.kt") + public void testKt49276() throws Exception { + runTest("compiler/testData/diagnostics/tests/checkArguments/kt49276.kt"); + } + + @Test + @TestMetadata("kt49276Disabled.kt") + public void testKt49276Disabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/checkArguments/kt49276Disabled.kt"); + } + + @Test + @TestMetadata("kt49276Error.kt") + public void testKt49276Error() throws Exception { + runTest("compiler/testData/diagnostics/tests/checkArguments/kt49276Error.kt"); + } + @Test @TestMetadata("overloadedFunction.kt") public void testOverloadedFunction() throws Exception { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt index 1fb6f80b485..cbe504ae9b2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt @@ -411,6 +411,7 @@ class GenerationState private constructor( this[KOTLIN_1_6] = JvmMetadataVersion.INSTANCE this[KOTLIN_1_7] = JvmMetadataVersion(1, 7, 0) this[KOTLIN_1_8] = JvmMetadataVersion(1, 8, 0) + this[KOTLIN_1_9] = JvmMetadataVersion(1, 9, 0) check(size == LanguageVersion.values().size) { "Please add mappings from the missing LanguageVersion instances to the corresponding JvmMetadataVersion " + diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 19ec7395e3f..e0e214b2497 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -4539,6 +4539,24 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/checkArguments/kt1940.kt"); } + @Test + @TestMetadata("kt49276.kt") + public void testKt49276() throws Exception { + runTest("compiler/testData/diagnostics/tests/checkArguments/kt49276.kt"); + } + + @Test + @TestMetadata("kt49276Disabled.kt") + public void testKt49276Disabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/checkArguments/kt49276Disabled.kt"); + } + + @Test + @TestMetadata("kt49276Error.kt") + public void testKt49276Error() throws Exception { + runTest("compiler/testData/diagnostics/tests/checkArguments/kt49276Error.kt"); + } + @Test @TestMetadata("overloadedFunction.kt") public void testOverloadedFunction() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index c3127e7a4e5..409f95d7bac 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -4539,6 +4539,24 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/checkArguments/kt1940.kt"); } + @Test + @TestMetadata("kt49276.kt") + public void testKt49276() throws Exception { + runTest("compiler/testData/diagnostics/tests/checkArguments/kt49276.kt"); + } + + @Test + @TestMetadata("kt49276Disabled.kt") + public void testKt49276Disabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/checkArguments/kt49276Disabled.kt"); + } + + @Test + @TestMetadata("kt49276Error.kt") + public void testKt49276Error() throws Exception { + runTest("compiler/testData/diagnostics/tests/checkArguments/kt49276Error.kt"); + } + @Test @TestMetadata("overloadedFunction.kt") public void testOverloadedFunction() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 2dc9bd62ea4..72e4545de5f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -208,6 +208,8 @@ public interface Errors { DiagnosticFactory0 MODIFIER_LIST_NOT_ALLOWED = DiagnosticFactory0.create(ERROR); + DiagnosticFactoryForDeprecation1 PROGRESSIONS_CHANGING_RESOLVE = DiagnosticFactoryForDeprecation1.create(LanguageFeature.ProgressionsChangingResolve); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Errors in declarations diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index c380eb9dc18..662d8a96dc9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -612,6 +612,10 @@ public class DefaultErrorMessages { MAP.put(DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL, "Applying ''!!'' to the whole as/is expression without parentheses is deprecated. Please, put parentheses explicitly"); MAP.put(MODIFIER_LIST_NOT_ALLOWED, "Modifiers and annotations are not allowed here, because there are other modifiers or annotations outside of parenthesis"); + MAP.put(PROGRESSIONS_CHANGING_RESOLVE, "Progressions and ranges types will start implementing Collection interface soon. " + + "This call will resolve to another declaration: {0}. " + + "See https://youtrack.jetbrains.com/issue/KT-49276 for more details. " + + "Please specify a progrssion type of argument explicitly through explicit cast to resolve to a proper declaration.", COMPACT); MAP.put(TOO_MANY_ARGUMENTS, "Too many arguments for {0}", FQ_NAMES_IN_TYPES); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/IdentifierInfo.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/IdentifierInfo.kt index 118b74adddd..7fd29787dc6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/IdentifierInfo.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/IdentifierInfo.kt @@ -235,7 +235,7 @@ private fun getIdForSimpleNameExpression( if (implicitReceiver == null) { selectorInfo } else { - val receiverInfo = getIdForImplicitReceiver(implicitReceiver, simpleNameExpression) + val receiverInfo = getIdForImplicitReceiver(implicitReceiver) if (receiverInfo == null) { selectorInfo @@ -261,15 +261,10 @@ private fun getIdForSimpleNameExpression( } } -private fun getIdForImplicitReceiver(receiverValue: ReceiverValue?, expression: KtExpression?) = +private fun getIdForImplicitReceiver(receiverValue: ReceiverValue?): IdentifierInfo? = when (receiverValue) { is ContextReceiver -> IdentifierInfo.Receiver(receiverValue) - is ImplicitReceiver -> getIdForThisReceiver(receiverValue.declarationDescriptor) - - is TransientReceiver -> - throw AssertionError("Transient receiver is implicit for an explicit expression: $expression. Receiver: $receiverValue") - else -> null } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt index 81caec3ed8a..22d841097c1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt @@ -28,9 +28,13 @@ import org.jetbrains.kotlin.resolve.calls.components.candidate.SimpleResolutionC import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession +import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter +import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver +import org.jetbrains.kotlin.resolve.calls.inference.components.TypeVariableDirectionCalculator import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable +import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory @@ -79,6 +83,7 @@ class KotlinResolutionCallbacksImpl( private val topLevelCallContext: BasicCallResolutionContext, private val missingSupertypesResolver: MissingSupertypesResolver, private val kotlinCallResolver: KotlinCallResolver, + private val resultTypeResolver: ResultTypeResolver, ) : KotlinResolutionCallbacks { class LambdaInfo(val expectedType: UnwrappedType, val contextDependency: ContextDependency) { val returnStatements = ArrayList>() @@ -89,6 +94,15 @@ class KotlinResolutionCallbacksImpl( } } + override fun findResultType(constraintSystem: NewConstraintSystem, typeVariable: TypeVariableTypeConstructor): KotlinType? { + val variableWithConstraints = constraintSystem.getBuilder().currentStorage().notFixedTypeVariables[typeVariable] ?: return null + return resultTypeResolver.findResultType( + constraintSystem.asConstraintSystemCompleterContext(), + variableWithConstraints, + TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN + ) as KotlinType + } + override fun resolveCallableReferenceArgument( argument: CallableReferenceKotlinCallArgument, expectedType: UnwrappedType?, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index c56fac85fa6..d9d2d255c7d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver import org.jetbrains.kotlin.resolve.calls.SPECIAL_FUNCTION_NAMES import org.jetbrains.kotlin.resolve.calls.components.InferenceSession +import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext @@ -28,6 +29,7 @@ import org.jetbrains.kotlin.resolve.calls.context.CallPosition import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.inference.buildResultingSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter +import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.results.* import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo @@ -36,6 +38,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors import org.jetbrains.kotlin.resolve.calls.tasks.OldResolutionCandidate import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy import org.jetbrains.kotlin.resolve.calls.util.* +import org.jetbrains.kotlin.resolve.checkers.PassingProgressionAsCollectionCallChecker import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns @@ -72,8 +75,11 @@ class PSICallResolver( private val deprecationResolver: DeprecationResolver, private val moduleDescriptor: ModuleDescriptor, private val candidateInterceptor: CandidateInterceptor, - private val missingSupertypesResolver: MissingSupertypesResolver + private val missingSupertypesResolver: MissingSupertypesResolver, + private val resultTypeResolver: ResultTypeResolver, ) { + private val callCheckersWithAdditionalResolve = listOf(PassingProgressionAsCollectionCallChecker(kotlinCallResolver)) + private val givenCandidatesName = Name.special("") private val arePartiallySpecifiedTypeArgumentsEnabled = languageVersionSettings.supportsFeature(LanguageFeature.PartiallySpecifiedTypeArguments) @@ -114,8 +120,22 @@ class PSICallResolver( } val overloadResolutionResults = convertToOverloadResolutionResults(context, result, tracingStrategy) + return overloadResolutionResults.also { clearCacheForApproximationResults() + checkCallWithAdditionalResolve(it, scopeTower, resolutionCallbacks, expectedType, context) + } + } + + private fun checkCallWithAdditionalResolve( + overloadResolutionResults: OverloadResolutionResults, + scopeTower: ImplicitScopeTower, + resolutionCallbacks: KotlinResolutionCallbacks, + expectedType: UnwrappedType?, + context: BasicCallResolutionContext, + ) { + for (callChecker in callCheckersWithAdditionalResolve) { + callChecker.check(overloadResolutionResults, scopeTower, resolutionCallbacks, expectedType, context) } } @@ -189,7 +209,8 @@ class PSICallResolver( argumentTypeResolver, languageVersionSettings, kotlinToResolvedCallTransformer, dataFlowValueFactory, inferenceSession, constantExpressionEvaluator, typeResolver, this, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents, - doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, context, missingSupertypesResolver, kotlinCallResolver + doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, context, missingSupertypesResolver, kotlinCallResolver, + resultTypeResolver ) private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PassingProgressionAsCollectionCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PassingProgressionAsCollectionCallChecker.kt new file mode 100644 index 00000000000..c0949a8cae9 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PassingProgressionAsCollectionCallChecker.kt @@ -0,0 +1,184 @@ +/* + * 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.resolve.checkers + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.diagnostics.Errors.PROGRESSIONS_CHANGING_RESOLVE +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver +import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks +import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument +import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults +import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo +import org.jetbrains.kotlin.resolve.calls.tower.* +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo +import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerState +import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerStateInternals +import org.jetbrains.kotlin.types.checker.intersectTypes +import org.jetbrains.kotlin.types.typeUtil.isTypeParameter + +/* + NB: this checker is exceptionally temporary added for stdlib migration purposes (see KT-49276). + Please don't use similar logic for other checkers + */ +@OptIn(ClassicTypeCheckerStateInternals::class) +class PassingProgressionAsCollectionCallChecker(private val kotlinCallResolver: KotlinCallResolver) { + private val typeCheckerState = ClassicTypeCheckerState(isErrorTypeEqualsToAnything = false) + + private val iterableProgressions = listOf( + CHAR_RANGE_FQN, CHAR_PROGRESSION_FQN, + INT_RANGE_FQN, INT_PROGRESSION_FQN, + LONG_RANGE_FQN, LONG_PROGRESSION_FQN, + UINT_RANGE_FQN, UINT_PROGRESSION_FQN, + ULONG_RANGE_FQN, ULONG_PROGRESSION_FQN + ) + + private fun check( + resolvedCall: ResolvedCall<*>, + scopeTower: ImplicitScopeTower, + resolutionCallbacks: KotlinResolutionCallbacks, + expectedType: UnwrappedType?, + context: BasicCallResolutionContext, + ) { + // The stdlib migration is going to be finished in 1.8, checks aren't needed there (DisableCheckingChangedProgressionsResolve has 1.8 since version) + val isCheckingDisabled = context.languageVersionSettings.supportsFeature(LanguageFeature.DisableCheckingChangedProgressionsResolve) + + if (isCheckingDisabled || resolvedCall !is NewResolvedCallImpl<*>) return + + val kotlinCall = resolvedCall.psiKotlinCall + val valueArguments = kotlinCall.argumentsInParenthesis.takeIf { it.isNotEmpty() } ?: return + + val progressionOrRangeArgumentTypes = valueArguments.map { + if (it !is SimpleKotlinCallArgument) return@map null + getRangeOrProgressionElementType(it.receiver.receiverValue.type, iterableProgressions) + } + + if (progressionOrRangeArgumentTypes.all { it == null }) return + + val builtIns = resolvedCall.candidateDescriptor.builtIns + val newArguments = replaceArgumentsWithCollectionIfNeeded(valueArguments, progressionOrRangeArgumentTypes, context.trace, builtIns) + + val newCall = PSIKotlinCallImpl( + kotlinCall.callKind, kotlinCall.psiCall, kotlinCall.tracingStrategy, kotlinCall.explicitReceiver, + kotlinCall.dispatchReceiverForInvokeExtension, kotlinCall.name, kotlinCall.typeArguments, newArguments, + kotlinCall.externalArgument, kotlinCall.startingDataFlowInfo, kotlinCall.resultDataFlowInfo, + kotlinCall.dataFlowInfoForArguments, kotlinCall.isForImplicitInvoke + ) + + val candidateForCollectionReplacedArgument = kotlinCallResolver.resolveCall( + scopeTower, resolutionCallbacks, newCall, expectedType, context.collectAllCandidates + ).singleOrNull() ?: return + + // Resolve wasn't changed or inapplicable + if ( + candidateForCollectionReplacedArgument.descriptor == resolvedCall.candidateDescriptor || + !candidateForCollectionReplacedArgument.isSuccessful + ) return + + val collectionOfAnyType = makeCollectionOfAnyType(builtIns) + + for ((i, argument) in newCall.argumentsInParenthesis.withIndex()) { + // Skip if the argument wasn't a Range/Progression + if (progressionOrRangeArgumentTypes.getOrNull(i) == null) continue + + val resolvedCallForCollectionReplacedArgument = candidateForCollectionReplacedArgument.resolvedCall + val alternativeParameterType = + resolvedCallForCollectionReplacedArgument.argumentToCandidateParameter[argument]?.type?.let { type -> + if (type.isTypeParameter()) { + val typeVariable = resolvedCallForCollectionReplacedArgument.freshVariablesSubstitutor.freshVariables.find { + it.originalTypeParameter == type.constructor.declarationDescriptor + }?.freshTypeConstructor ?: return@let null + resolutionCallbacks.findResultType(candidateForCollectionReplacedArgument.getSystem(), typeVariable) + } else type + } ?: continue + + val cons = alternativeParameterType.constructor + + if (cons.declarationDescriptor != builtIns.collection && (cons !is IntersectionTypeConstructor || cons.supertypes.none { it.constructor.declarationDescriptor == builtIns.collection })) continue + + val argumentExpression = argument.psiExpression ?: continue + val initialArgumentType = resolvedCall.candidateDescriptor.valueParameters.getOrNull(i)?.type ?: continue + + // Iterable initial type is an exception, considered as similar to Collection passing candidate + if (initialArgumentType.constructor.declarationDescriptor == builtIns.iterable) continue + + // The initial type should be wider than Collection + if ( + AbstractTypeChecker.isSubtypeOf(typeCheckerState, collectionOfAnyType, initialArgumentType) + || initialArgumentType.isTypeParameter() + ) { + context.trace.report( + PROGRESSIONS_CHANGING_RESOLVE.on( + candidateForCollectionReplacedArgument.callComponents.languageVersionSettings, + argumentExpression, + resolvedCallForCollectionReplacedArgument.candidateDescriptor + ) + ) + } + } + } + + fun check( + overloadResolutionResults: OverloadResolutionResults<*>, + scopeTower: ImplicitScopeTower, + resolutionCallbacks: KotlinResolutionCallbacks, + expectedType: UnwrappedType?, + context: BasicCallResolutionContext, + ) { + if (!overloadResolutionResults.isSingleResult) return + + val resolvedCall = overloadResolutionResults.resultingCall as? NewAbstractResolvedCall<*> ?: return + + check(resolvedCall, scopeTower, resolutionCallbacks, expectedType, context) + } + + private fun makeCollectionOfAnyType(builtIns: KotlinBuiltIns): KotlinType = + KotlinTypeFactory.simpleNotNullType( + Annotations.EMPTY, + builtIns.collection, + listOf(TypeProjectionImpl(builtIns.nullableAnyType)) + ) + + private fun replaceArgumentsWithCollectionIfNeeded( + valueArguments: List, + progressionOrRangeArgumentTypes: List, + trace: BindingTrace, + builtIns: KotlinBuiltIns + ): List = valueArguments.mapIndexed { i, argument -> + if (argument !is ExpressionKotlinCallArgumentImpl) return@mapIndexed argument + val progressionOrRangeElementType = progressionOrRangeArgumentTypes[i] ?: return@mapIndexed argument + val psiExpression = argument.psiExpression ?: return@mapIndexed argument + val newType = intersectTypes( + listOf( + KotlinTypeFactory.simpleNotNullType( + Annotations.EMPTY, + builtIns.collection, + listOf(TypeProjectionImpl(progressionOrRangeElementType)) + ), + argument.receiver.receiverValue.type.unwrap() + ) + ) + + ExpressionKotlinCallArgumentImpl( + argument.psiCallArgument.valueArgument, + DataFlowInfo.EMPTY, + DataFlowInfo.EMPTY, + ReceiverValueWithSmartCastInfo( + ExpressionReceiver.create(psiExpression, newType, trace.bindingContext), + emptySet(), + true + ) + ) + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/RangeUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/RangeUtil.kt index 645ffecef52..d09d9fad5e3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/RangeUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/RangeUtil.kt @@ -281,10 +281,5 @@ fun isCharSequenceIterator(descriptor: CallableDescriptor) = } -fun isPrimitiveNumberClassDescriptor(descriptor: DeclarationDescriptor?): Boolean { - return if (descriptor !is ClassDescriptor) { - false - } else KotlinBuiltIns.isPrimitiveClass((descriptor as ClassDescriptor?)!!) && !KotlinBuiltIns.isBoolean( - (descriptor as ClassDescriptor?)!! - ) -} +fun isPrimitiveNumberClassDescriptor(descriptor: DeclarationDescriptor?): Boolean = + descriptor is ClassDescriptor && KotlinBuiltIns.isPrimitiveClass(descriptor) && !KotlinBuiltIns.isBoolean(descriptor) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/KotlinCallResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/KotlinCallResolver.kt index 477159fe3fb..c17f994d53d 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/KotlinCallResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/KotlinCallResolver.kt @@ -44,6 +44,17 @@ class KotlinCallResolver( return kotlinCallCompleter.runCompletion(candidateFactory, candidates, expectedType, resolutionCallbacks) } + fun resolveCall( + scopeTower: ImplicitScopeTower, + resolutionCallbacks: KotlinResolutionCallbacks, + kotlinCall: KotlinCall, + expectedType: UnwrappedType?, + collectAllCandidates: Boolean, + ): Collection { + val candidateFactory = createFactory(scopeTower, kotlinCall, resolutionCallbacks, expectedType) + return resolveCall(scopeTower, resolutionCallbacks, kotlinCall, collectAllCandidates, candidateFactory) + } + fun resolveAndCompleteGivenCandidates( scopeTower: ImplicitScopeTower, resolutionCallbacks: KotlinResolutionCallbacks, diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt index bd1837b4930..93f7763aa1c 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt @@ -14,9 +14,11 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate import org.jetbrains.kotlin.resolve.calls.components.candidate.SimpleResolutionCandidate +import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable +import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem import org.jetbrains.kotlin.resolve.calls.tower.CandidateFactoryProviderForInvoke @@ -94,6 +96,8 @@ interface KotlinResolutionCallbacks { baseSystem: ConstraintStorage, ): Collection + fun findResultType(constraintSystem: NewConstraintSystem, typeVariable: TypeVariableTypeConstructor): KotlinType? + fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom) fun isCompileTimeConstant(resolvedAtom: ResolvedCallAtom, expectedType: UnwrappedType): Boolean diff --git a/compiler/testData/cli/jvm/apiVersionInvalid.out b/compiler/testData/cli/jvm/apiVersionInvalid.out index 9d84f87e557..03e34c3f22e 100644 --- a/compiler/testData/cli/jvm/apiVersionInvalid.out +++ b/compiler/testData/cli/jvm/apiVersionInvalid.out @@ -1,3 +1,3 @@ error: unknown API version: 239.42 -Supported API versions: 1.4 (DEPRECATED), 1.5, 1.6, 1.7 (EXPERIMENTAL), 1.8 (EXPERIMENTAL) +Supported API versions: 1.4 (DEPRECATED), 1.5, 1.6, 1.7 (EXPERIMENTAL), 1.8 (EXPERIMENTAL), 1.9 (EXPERIMENTAL) COMPILATION_ERROR diff --git a/compiler/testData/cli/jvm/languageVersionInvalid.out b/compiler/testData/cli/jvm/languageVersionInvalid.out index ddf9958222c..2cce7fbff3d 100644 --- a/compiler/testData/cli/jvm/languageVersionInvalid.out +++ b/compiler/testData/cli/jvm/languageVersionInvalid.out @@ -1,3 +1,3 @@ error: unknown language version: 239.42 -Supported language versions: 1.4 (DEPRECATED), 1.5, 1.6, 1.7 (EXPERIMENTAL), 1.8 (EXPERIMENTAL) +Supported language versions: 1.4 (DEPRECATED), 1.5, 1.6, 1.7 (EXPERIMENTAL), 1.8 (EXPERIMENTAL), 1.9 (EXPERIMENTAL) COMPILATION_ERROR diff --git a/compiler/testData/diagnostics/tests/checkArguments/kt49276.fir.kt b/compiler/testData/diagnostics/tests/checkArguments/kt49276.fir.kt new file mode 100644 index 00000000000..0d561021b9f --- /dev/null +++ b/compiler/testData/diagnostics/tests/checkArguments/kt49276.fir.kt @@ -0,0 +1,43 @@ +// WITH_RUNTIME + +fun SmartList(x: E) {} +fun SmartList(x: Collection) {} + +fun append(x: Any?) {} +fun append(x: Collection<*>) {} + +fun append2(x: Iterable<*>) {} +fun append2(x: Collection<*>) {} + +class In(x: T) + +@JvmName("append31") +fun append3(x: In) {} +fun append3(x: In>) {} + +fun append4(x: E) {} +fun > append4(x: E) {} + +fun takes(range: T) {} +fun takes(range: T) where T : Collection<*>, T: ClosedRange<*> {} + +fun main() { + SmartList(1..2) // warning + SmartList(1..10) // no warning + + append(1..10) // warning + append((1..10) as Any) // no warning + append((1..10) as Iterable) // no warning + append("a".."z") // no warning, the range is not iterable + append(1.0..2.0) + + append2(1..10) // no warning + + append3(In(1..10)) // no warning + + append4(1..10) // warning + + append4(1..10) // warning + + takes(1..10) // warning +} diff --git a/compiler/testData/diagnostics/tests/checkArguments/kt49276.kt b/compiler/testData/diagnostics/tests/checkArguments/kt49276.kt new file mode 100644 index 00000000000..3317f6d6fad --- /dev/null +++ b/compiler/testData/diagnostics/tests/checkArguments/kt49276.kt @@ -0,0 +1,43 @@ +// WITH_RUNTIME + +fun SmartList(x: E) {} +fun SmartList(x: Collection) {} + +fun append(x: Any?) {} +fun append(x: Collection<*>) {} + +fun append2(x: Iterable<*>) {} +fun append2(x: Collection<*>) {} + +class In(x: T) + +@JvmName("append31") +fun append3(x: In) {} +fun append3(x: In>) {} + +fun append4(x: E) {} +fun > append4(x: E) {} + +fun takes(range: T) {} +fun takes(range: T) where T : Collection<*>, T: ClosedRange<*> {} + +fun main() { + SmartList( SmartList(x: Collection): Unit")!>1..2) // warning + SmartList(1..10) // no warning + + append(): Unit")!>1..10) // warning + append((1..10) as Any) // no warning + append((1..10) as Iterable) // no warning + append("a".."z") // no warning, the range is not iterable + append(1.0..2.0) + + append2(1..10) // no warning + + append3(In(1..10)) // no warning + + append4(> append4(x: E): Unit")!>1..10) // warning + + append4(1..10) // warning + + takes(> takes(range: T): Unit where T : ClosedRange<*>")!>1..10) // warning +} diff --git a/compiler/testData/diagnostics/tests/checkArguments/kt49276.txt b/compiler/testData/diagnostics/tests/checkArguments/kt49276.txt new file mode 100644 index 00000000000..3b8628dc7af --- /dev/null +++ b/compiler/testData/diagnostics/tests/checkArguments/kt49276.txt @@ -0,0 +1,23 @@ +package + +public fun SmartList(/*0*/ x: E): kotlin.Unit +public fun SmartList(/*0*/ x: kotlin.collections.Collection): kotlin.Unit +public fun append(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun append(/*0*/ x: kotlin.collections.Collection<*>): kotlin.Unit +public fun append2(/*0*/ x: kotlin.collections.Collection<*>): kotlin.Unit +public fun append2(/*0*/ x: kotlin.collections.Iterable<*>): kotlin.Unit +@kotlin.jvm.JvmName(name = "append31") public fun append3(/*0*/ x: In): kotlin.Unit +public fun append3(/*0*/ x: In>): kotlin.Unit +public fun append4(/*0*/ x: E): kotlin.Unit +public fun > append4(/*0*/ x: E): kotlin.Unit +public fun main(): kotlin.Unit +public fun takes(/*0*/ range: T): kotlin.Unit +public fun > takes(/*0*/ range: T): kotlin.Unit where T : kotlin.ranges.ClosedRange<*> + +public final class In { + public constructor In(/*0*/ x: T) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + diff --git a/compiler/testData/diagnostics/tests/checkArguments/kt49276Disabled.kt b/compiler/testData/diagnostics/tests/checkArguments/kt49276Disabled.kt new file mode 100644 index 00000000000..ac748b51f36 --- /dev/null +++ b/compiler/testData/diagnostics/tests/checkArguments/kt49276Disabled.kt @@ -0,0 +1,38 @@ +// FIR_IDENTICAL +// !LANGUAGE: +DisableCheckingChangedProgressionsResolve +// WITH_RUNTIME + +fun SmartList(x: E) {} +fun SmartList(x: Collection) {} + +fun append(x: Any?) {} +fun append(x: Collection<*>) {} + +fun append2(x: Iterable<*>) {} +fun append2(x: Collection<*>) {} + +class In(x: T) + +@JvmName("append31") +fun append3(x: In) {} +fun append3(x: In>) {} + +fun append4(x: E) {} +fun > append4(x: E) {} + +fun main() { + SmartList(1..2) // warning + SmartList(1..10) // no warning + + append(1..10) // warning + append((1..10) as Any) // no warning + append((1..10) as Iterable) // no warning + append("a".."z") // no warning, the range is not iterable + append(1.0..2.0) + + append2(1..10) // no warning + + append3(In(1..10)) // no warning + + append4(1..10) // warning +} diff --git a/compiler/testData/diagnostics/tests/checkArguments/kt49276Disabled.txt b/compiler/testData/diagnostics/tests/checkArguments/kt49276Disabled.txt new file mode 100644 index 00000000000..97c5f0f2c0c --- /dev/null +++ b/compiler/testData/diagnostics/tests/checkArguments/kt49276Disabled.txt @@ -0,0 +1,20 @@ +package + +public fun SmartList(/*0*/ x: E): kotlin.Unit +public fun SmartList(/*0*/ x: kotlin.collections.Collection): kotlin.Unit +public fun append(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun append(/*0*/ x: kotlin.collections.Collection<*>): kotlin.Unit +public fun append2(/*0*/ x: kotlin.collections.Collection<*>): kotlin.Unit +public fun append2(/*0*/ x: kotlin.collections.Iterable<*>): kotlin.Unit +@kotlin.jvm.JvmName(name = "append31") public fun append3(/*0*/ x: In): kotlin.Unit +public fun append3(/*0*/ x: In>): kotlin.Unit +public fun append4(/*0*/ x: E): kotlin.Unit +public fun > append4(/*0*/ x: E): kotlin.Unit +public fun main(): kotlin.Unit + +public final class In { + public constructor In(/*0*/ x: T) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/checkArguments/kt49276Error.fir.kt b/compiler/testData/diagnostics/tests/checkArguments/kt49276Error.fir.kt new file mode 100644 index 00000000000..3f6e5bda5e6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/checkArguments/kt49276Error.fir.kt @@ -0,0 +1,37 @@ +// WITH_RUNTIME +// !LANGUAGE: +ProgressionsChangingResolve + +fun SmartList(x: E) {} +fun SmartList(x: Collection) {} + +fun append(x: Any?) {} +fun append(x: Collection<*>) {} + +fun append2(x: Iterable<*>) {} +fun append2(x: Collection<*>) {} + +class In(x: T) + +@JvmName("append31") +fun append3(x: In) {} +fun append3(x: In>) {} + +fun append4(x: E) {} +fun > append4(x: E) {} + +fun main() { + SmartList(1..2) // warning + SmartList(1..10) // no warning + + append(1..10) // warning + append((1..10) as Any) // no warning + append((1..10) as Iterable) // no warning + append("a".."z") // no warning, the range is not iterable + append(1.0..2.0) + + append2(1..10) // no warning + + append3(In(1..10)) // no warning + + append4(1..10) // warning +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/checkArguments/kt49276Error.kt b/compiler/testData/diagnostics/tests/checkArguments/kt49276Error.kt new file mode 100644 index 00000000000..f4083aa3c90 --- /dev/null +++ b/compiler/testData/diagnostics/tests/checkArguments/kt49276Error.kt @@ -0,0 +1,37 @@ +// WITH_RUNTIME +// !LANGUAGE: +ProgressionsChangingResolve + +fun SmartList(x: E) {} +fun SmartList(x: Collection) {} + +fun append(x: Any?) {} +fun append(x: Collection<*>) {} + +fun append2(x: Iterable<*>) {} +fun append2(x: Collection<*>) {} + +class In(x: T) + +@JvmName("append31") +fun append3(x: In) {} +fun append3(x: In>) {} + +fun append4(x: E) {} +fun > append4(x: E) {} + +fun main() { + SmartList( SmartList(x: Collection): Unit")!>1..2) // warning + SmartList(1..10) // no warning + + append(): Unit")!>1..10) // warning + append((1..10) as Any) // no warning + append((1..10) as Iterable) // no warning + append("a".."z") // no warning, the range is not iterable + append(1.0..2.0) + + append2(1..10) // no warning + + append3(In(1..10)) // no warning + + append4(> append4(x: E): Unit")!>1..10) // warning +} diff --git a/compiler/testData/diagnostics/tests/checkArguments/kt49276Error.txt b/compiler/testData/diagnostics/tests/checkArguments/kt49276Error.txt new file mode 100644 index 00000000000..97c5f0f2c0c --- /dev/null +++ b/compiler/testData/diagnostics/tests/checkArguments/kt49276Error.txt @@ -0,0 +1,20 @@ +package + +public fun SmartList(/*0*/ x: E): kotlin.Unit +public fun SmartList(/*0*/ x: kotlin.collections.Collection): kotlin.Unit +public fun append(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun append(/*0*/ x: kotlin.collections.Collection<*>): kotlin.Unit +public fun append2(/*0*/ x: kotlin.collections.Collection<*>): kotlin.Unit +public fun append2(/*0*/ x: kotlin.collections.Iterable<*>): kotlin.Unit +@kotlin.jvm.JvmName(name = "append31") public fun append3(/*0*/ x: In): kotlin.Unit +public fun append3(/*0*/ x: In>): kotlin.Unit +public fun append4(/*0*/ x: E): kotlin.Unit +public fun > append4(/*0*/ x: E): kotlin.Unit +public fun main(): kotlin.Unit + +public final class In { + public constructor In(/*0*/ x: T) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 0b163399383..fb34ebbdfac 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -4545,6 +4545,24 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/checkArguments/kt1940.kt"); } + @Test + @TestMetadata("kt49276.kt") + public void testKt49276() throws Exception { + runTest("compiler/testData/diagnostics/tests/checkArguments/kt49276.kt"); + } + + @Test + @TestMetadata("kt49276Disabled.kt") + public void testKt49276Disabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/checkArguments/kt49276Disabled.kt"); + } + + @Test + @TestMetadata("kt49276Error.kt") + public void testKt49276Error() throws Exception { + runTest("compiler/testData/diagnostics/tests/checkArguments/kt49276Error.kt"); + } + @Test @TestMetadata("overloadedFunction.kt") public void testOverloadedFunction() throws Exception { diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 67c20e9fe5e..bad211327c1 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -248,6 +248,11 @@ enum class LanguageFeature( ProhibitConfusingSyntaxInWhenBranches(KOTLIN_1_8, kind = BUG_FIX), // KT-48385 UseConsistentRulesForPrivateConstructorsOfSealedClasses(sinceVersion = KOTLIN_1_8, kind = BUG_FIX), // KT-44866 + ProgressionsChangingResolve(KOTLIN_1_8), // KT-49276 + + // 1.9 + + DisableCheckingChangedProgressionsResolve(KOTLIN_1_9), // KT-49276 // Temporarily disabled, see KT-27084/KT-22379 SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX), @@ -358,6 +363,7 @@ enum class LanguageVersion(val major: Int, val minor: Int) : DescriptionAware, L KOTLIN_1_6(1, 6), KOTLIN_1_7(1, 7), KOTLIN_1_8(1, 8), + KOTLIN_1_9(1, 9), ; override val isStable: Boolean