[FE 1.0] Implement checker to detect changed resolve for progressions and ranges due to the start of implementing Collection<T>

^KT-49276 Fixed
This commit is contained in:
Victor Petukhov
2021-11-30 14:47:17 +03:00
committed by teamcity
parent 4363667bc1
commit 7475d26902
25 changed files with 588 additions and 18 deletions
@@ -4539,6 +4539,24 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/checkArguments/kt1940.kt"); 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 @Test
@TestMetadata("overloadedFunction.kt") @TestMetadata("overloadedFunction.kt")
public void testOverloadedFunction() throws Exception { public void testOverloadedFunction() throws Exception {
@@ -411,6 +411,7 @@ class GenerationState private constructor(
this[KOTLIN_1_6] = JvmMetadataVersion.INSTANCE this[KOTLIN_1_6] = JvmMetadataVersion.INSTANCE
this[KOTLIN_1_7] = JvmMetadataVersion(1, 7, 0) this[KOTLIN_1_7] = JvmMetadataVersion(1, 7, 0)
this[KOTLIN_1_8] = JvmMetadataVersion(1, 8, 0) this[KOTLIN_1_8] = JvmMetadataVersion(1, 8, 0)
this[KOTLIN_1_9] = JvmMetadataVersion(1, 9, 0)
check(size == LanguageVersion.values().size) { check(size == LanguageVersion.values().size) {
"Please add mappings from the missing LanguageVersion instances to the corresponding JvmMetadataVersion " + "Please add mappings from the missing LanguageVersion instances to the corresponding JvmMetadataVersion " +
@@ -4539,6 +4539,24 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/checkArguments/kt1940.kt"); 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 @Test
@TestMetadata("overloadedFunction.kt") @TestMetadata("overloadedFunction.kt")
public void testOverloadedFunction() throws Exception { public void testOverloadedFunction() throws Exception {
@@ -4539,6 +4539,24 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/checkArguments/kt1940.kt"); 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 @Test
@TestMetadata("overloadedFunction.kt") @TestMetadata("overloadedFunction.kt")
public void testOverloadedFunction() throws Exception { public void testOverloadedFunction() throws Exception {
@@ -208,6 +208,8 @@ public interface Errors {
DiagnosticFactory0<KtModifierList> MODIFIER_LIST_NOT_ALLOWED = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<KtModifierList> MODIFIER_LIST_NOT_ALLOWED = DiagnosticFactory0.create(ERROR);
DiagnosticFactoryForDeprecation1<PsiElement, CallableDescriptor> PROGRESSIONS_CHANGING_RESOLVE = DiagnosticFactoryForDeprecation1.create(LanguageFeature.ProgressionsChangingResolve);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Errors in declarations // Errors in declarations
@@ -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(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(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); MAP.put(TOO_MANY_ARGUMENTS, "Too many arguments for {0}", FQ_NAMES_IN_TYPES);
@@ -235,7 +235,7 @@ private fun getIdForSimpleNameExpression(
if (implicitReceiver == null) { if (implicitReceiver == null) {
selectorInfo selectorInfo
} else { } else {
val receiverInfo = getIdForImplicitReceiver(implicitReceiver, simpleNameExpression) val receiverInfo = getIdForImplicitReceiver(implicitReceiver)
if (receiverInfo == null) { if (receiverInfo == null) {
selectorInfo selectorInfo
@@ -261,15 +261,10 @@ private fun getIdForSimpleNameExpression(
} }
} }
private fun getIdForImplicitReceiver(receiverValue: ReceiverValue?, expression: KtExpression?) = private fun getIdForImplicitReceiver(receiverValue: ReceiverValue?): IdentifierInfo? =
when (receiverValue) { when (receiverValue) {
is ContextReceiver -> IdentifierInfo.Receiver(receiverValue) is ContextReceiver -> IdentifierInfo.Receiver(receiverValue)
is ImplicitReceiver -> getIdForThisReceiver(receiverValue.declarationDescriptor) is ImplicitReceiver -> getIdForThisReceiver(receiverValue.declarationDescriptor)
is TransientReceiver ->
throw AssertionError("Transient receiver is implicit for an explicit expression: $expression. Receiver: $receiverValue")
else -> null else -> null
} }
@@ -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.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession 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.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.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable 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.model.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
@@ -79,6 +83,7 @@ class KotlinResolutionCallbacksImpl(
private val topLevelCallContext: BasicCallResolutionContext, private val topLevelCallContext: BasicCallResolutionContext,
private val missingSupertypesResolver: MissingSupertypesResolver, private val missingSupertypesResolver: MissingSupertypesResolver,
private val kotlinCallResolver: KotlinCallResolver, private val kotlinCallResolver: KotlinCallResolver,
private val resultTypeResolver: ResultTypeResolver,
) : KotlinResolutionCallbacks { ) : KotlinResolutionCallbacks {
class LambdaInfo(val expectedType: UnwrappedType, val contextDependency: ContextDependency) { class LambdaInfo(val expectedType: UnwrappedType, val contextDependency: ContextDependency) {
val returnStatements = ArrayList<Pair<KtReturnExpression, LambdaContextInfo?>>() val returnStatements = ArrayList<Pair<KtReturnExpression, LambdaContextInfo?>>()
@@ -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( override fun resolveCallableReferenceArgument(
argument: CallableReferenceKotlinCallArgument, argument: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?, expectedType: UnwrappedType?,
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.resolve.calls.CallTransformer
import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver
import org.jetbrains.kotlin.resolve.calls.SPECIAL_FUNCTION_NAMES import org.jetbrains.kotlin.resolve.calls.SPECIAL_FUNCTION_NAMES
import org.jetbrains.kotlin.resolve.calls.components.InferenceSession 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.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext 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.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.inference.buildResultingSubstitutor 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.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.* import org.jetbrains.kotlin.resolve.calls.results.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo 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.OldResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.calls.util.* 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.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
@@ -72,8 +75,11 @@ class PSICallResolver(
private val deprecationResolver: DeprecationResolver, private val deprecationResolver: DeprecationResolver,
private val moduleDescriptor: ModuleDescriptor, private val moduleDescriptor: ModuleDescriptor,
private val candidateInterceptor: CandidateInterceptor, 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("<given candidates>") private val givenCandidatesName = Name.special("<given candidates>")
private val arePartiallySpecifiedTypeArgumentsEnabled = languageVersionSettings.supportsFeature(LanguageFeature.PartiallySpecifiedTypeArguments) private val arePartiallySpecifiedTypeArgumentsEnabled = languageVersionSettings.supportsFeature(LanguageFeature.PartiallySpecifiedTypeArguments)
@@ -114,8 +120,22 @@ class PSICallResolver(
} }
val overloadResolutionResults = convertToOverloadResolutionResults<D>(context, result, tracingStrategy) val overloadResolutionResults = convertToOverloadResolutionResults<D>(context, result, tracingStrategy)
return overloadResolutionResults.also { return overloadResolutionResults.also {
clearCacheForApproximationResults() clearCacheForApproximationResults()
checkCallWithAdditionalResolve(it, scopeTower, resolutionCallbacks, expectedType, context)
}
}
private fun <D : CallableDescriptor> checkCallWithAdditionalResolve(
overloadResolutionResults: OverloadResolutionResults<D>,
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, argumentTypeResolver, languageVersionSettings, kotlinToResolvedCallTransformer,
dataFlowValueFactory, inferenceSession, constantExpressionEvaluator, typeResolver, dataFlowValueFactory, inferenceSession, constantExpressionEvaluator, typeResolver,
this, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents, this, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents,
doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, context, missingSupertypesResolver, kotlinCallResolver doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, context, missingSupertypesResolver, kotlinCallResolver,
resultTypeResolver
) )
private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? { private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? {
@@ -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<KotlinCallArgument>,
progressionOrRangeArgumentTypes: List<KotlinType?>,
trace: BindingTrace,
builtIns: KotlinBuiltIns
): List<KotlinCallArgument> = 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
)
)
}
}
@@ -281,10 +281,5 @@ fun isCharSequenceIterator(descriptor: CallableDescriptor) =
} }
fun isPrimitiveNumberClassDescriptor(descriptor: DeclarationDescriptor?): Boolean { fun isPrimitiveNumberClassDescriptor(descriptor: DeclarationDescriptor?): Boolean =
return if (descriptor !is ClassDescriptor) { descriptor is ClassDescriptor && KotlinBuiltIns.isPrimitiveClass(descriptor) && !KotlinBuiltIns.isBoolean(descriptor)
false
} else KotlinBuiltIns.isPrimitiveClass((descriptor as ClassDescriptor?)!!) && !KotlinBuiltIns.isBoolean(
(descriptor as ClassDescriptor?)!!
)
}
@@ -44,6 +44,17 @@ class KotlinCallResolver(
return kotlinCallCompleter.runCompletion(candidateFactory, candidates, expectedType, resolutionCallbacks) return kotlinCallCompleter.runCompletion(candidateFactory, candidates, expectedType, resolutionCallbacks)
} }
fun resolveCall(
scopeTower: ImplicitScopeTower,
resolutionCallbacks: KotlinResolutionCallbacks,
kotlinCall: KotlinCall,
expectedType: UnwrappedType?,
collectAllCandidates: Boolean,
): Collection<ResolutionCandidate> {
val candidateFactory = createFactory(scopeTower, kotlinCall, resolutionCallbacks, expectedType)
return resolveCall(scopeTower, resolutionCallbacks, kotlinCall, collectAllCandidates, candidateFactory)
}
fun resolveAndCompleteGivenCandidates( fun resolveAndCompleteGivenCandidates(
scopeTower: ImplicitScopeTower, scopeTower: ImplicitScopeTower,
resolutionCallbacks: KotlinResolutionCallbacks, resolutionCallbacks: KotlinResolutionCallbacks,
@@ -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.ResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.components.candidate.SimpleResolutionCandidate 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.components.ConstraintInjector
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage 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.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
import org.jetbrains.kotlin.resolve.calls.tower.CandidateFactoryProviderForInvoke import org.jetbrains.kotlin.resolve.calls.tower.CandidateFactoryProviderForInvoke
@@ -94,6 +96,8 @@ interface KotlinResolutionCallbacks {
baseSystem: ConstraintStorage, baseSystem: ConstraintStorage,
): Collection<CallableReferenceResolutionCandidate> ): Collection<CallableReferenceResolutionCandidate>
fun findResultType(constraintSystem: NewConstraintSystem, typeVariable: TypeVariableTypeConstructor): KotlinType?
fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom) fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom)
fun isCompileTimeConstant(resolvedAtom: ResolvedCallAtom, expectedType: UnwrappedType): Boolean fun isCompileTimeConstant(resolvedAtom: ResolvedCallAtom, expectedType: UnwrappedType): Boolean
+1 -1
View File
@@ -1,3 +1,3 @@
error: unknown API version: 239.42 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 COMPILATION_ERROR
+1 -1
View File
@@ -1,3 +1,3 @@
error: unknown language version: 239.42 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 COMPILATION_ERROR
@@ -0,0 +1,43 @@
// WITH_RUNTIME
fun <E> SmartList(x: E) {}
fun <E> SmartList(x: Collection<E>) {}
fun append(x: Any?) {}
fun append(x: Collection<*>) {}
fun append2(x: Iterable<*>) {}
fun append2(x: Collection<*>) {}
class In<in T>(x: T)
@JvmName("append31")
fun append3(x: In<Nothing>) {}
fun append3(x: In<Collection<*>>) {}
fun <E> append4(x: E) {}
fun <E: Collection<*>> append4(x: E) {}
fun <T> takes(range: T) {}
fun <T> takes(range: T) where T : Collection<*>, T: ClosedRange<*> {}
fun main() {
SmartList(1..2) // warning
SmartList<IntRange>(1..10) // no warning
append(1..10) // warning
append((1..10) as Any) // no warning
append((1..10) as Iterable<Int>) // 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<IntRange>(1..10) // warning
takes(1..10) // warning
}
@@ -0,0 +1,43 @@
// WITH_RUNTIME
fun <E> SmartList(x: E) {}
fun <E> SmartList(x: Collection<E>) {}
fun append(x: Any?) {}
fun append(x: Collection<*>) {}
fun append2(x: Iterable<*>) {}
fun append2(x: Collection<*>) {}
class In<in T>(x: T)
@JvmName("append31")
fun append3(x: In<Nothing>) {}
fun append3(x: In<Collection<*>>) {}
fun <E> append4(x: E) {}
fun <E: Collection<*>> append4(x: E) {}
fun <T> takes(range: T) {}
fun <T> takes(range: T) where T : Collection<*>, T: ClosedRange<*> {}
fun main() {
SmartList(<!PROGRESSIONS_CHANGING_RESOLVE_WARNING("fun <E> SmartList(x: Collection<E>): Unit")!>1..2<!>) // warning
SmartList<IntRange>(1..10) // no warning
append(<!PROGRESSIONS_CHANGING_RESOLVE_WARNING("fun append(x: Collection<*>): Unit")!>1..10<!>) // warning
append((1..10) as Any) // no warning
append((1..10) as Iterable<Int>) // 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(<!PROGRESSIONS_CHANGING_RESOLVE_WARNING("fun <E : Collection<*>> append4(x: E): Unit")!>1..10<!>) // warning
append4<IntRange>(1..10) // warning
takes(<!PROGRESSIONS_CHANGING_RESOLVE_WARNING("fun <T : Collection<*>> takes(range: T): Unit where T : ClosedRange<*>")!>1..10<!>) // warning
}
@@ -0,0 +1,23 @@
package
public fun </*0*/ E> SmartList(/*0*/ x: E): kotlin.Unit
public fun </*0*/ E> SmartList(/*0*/ x: kotlin.collections.Collection<E>): 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.Nothing>): kotlin.Unit
public fun append3(/*0*/ x: In<kotlin.collections.Collection<*>>): kotlin.Unit
public fun </*0*/ E> append4(/*0*/ x: E): kotlin.Unit
public fun </*0*/ E : kotlin.collections.Collection<*>> append4(/*0*/ x: E): kotlin.Unit
public fun main(): kotlin.Unit
public fun </*0*/ T> takes(/*0*/ range: T): kotlin.Unit
public fun </*0*/ T : kotlin.collections.Collection<*>> takes(/*0*/ range: T): kotlin.Unit where T : kotlin.ranges.ClosedRange<*>
public final class In</*0*/ in T> {
public constructor In</*0*/ in T>(/*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
}
@@ -0,0 +1,38 @@
// FIR_IDENTICAL
// !LANGUAGE: +DisableCheckingChangedProgressionsResolve
// WITH_RUNTIME
fun <E> SmartList(x: E) {}
fun <E> SmartList(x: Collection<E>) {}
fun append(x: Any?) {}
fun append(x: Collection<*>) {}
fun append2(x: Iterable<*>) {}
fun append2(x: Collection<*>) {}
class In<in T>(x: T)
@JvmName("append31")
fun append3(x: In<Nothing>) {}
fun append3(x: In<Collection<*>>) {}
fun <E> append4(x: E) {}
fun <E: Collection<*>> append4(x: E) {}
fun main() {
SmartList(1..2) // warning
SmartList<IntRange>(1..10) // no warning
append(1..10) // warning
append((1..10) as Any) // no warning
append((1..10) as Iterable<Int>) // 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
}
@@ -0,0 +1,20 @@
package
public fun </*0*/ E> SmartList(/*0*/ x: E): kotlin.Unit
public fun </*0*/ E> SmartList(/*0*/ x: kotlin.collections.Collection<E>): 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.Nothing>): kotlin.Unit
public fun append3(/*0*/ x: In<kotlin.collections.Collection<*>>): kotlin.Unit
public fun </*0*/ E> append4(/*0*/ x: E): kotlin.Unit
public fun </*0*/ E : kotlin.collections.Collection<*>> append4(/*0*/ x: E): kotlin.Unit
public fun main(): kotlin.Unit
public final class In</*0*/ in T> {
public constructor In</*0*/ in T>(/*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
}
@@ -0,0 +1,37 @@
// WITH_RUNTIME
// !LANGUAGE: +ProgressionsChangingResolve
fun <E> SmartList(x: E) {}
fun <E> SmartList(x: Collection<E>) {}
fun append(x: Any?) {}
fun append(x: Collection<*>) {}
fun append2(x: Iterable<*>) {}
fun append2(x: Collection<*>) {}
class In<in T>(x: T)
@JvmName("append31")
fun append3(x: In<Nothing>) {}
fun append3(x: In<Collection<*>>) {}
fun <E> append4(x: E) {}
fun <E: Collection<*>> append4(x: E) {}
fun main() {
SmartList(1..2) // warning
SmartList<IntRange>(1..10) // no warning
append(1..10) // warning
append((1..10) as Any) // no warning
append((1..10) as Iterable<Int>) // 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
}
@@ -0,0 +1,37 @@
// WITH_RUNTIME
// !LANGUAGE: +ProgressionsChangingResolve
fun <E> SmartList(x: E) {}
fun <E> SmartList(x: Collection<E>) {}
fun append(x: Any?) {}
fun append(x: Collection<*>) {}
fun append2(x: Iterable<*>) {}
fun append2(x: Collection<*>) {}
class In<in T>(x: T)
@JvmName("append31")
fun append3(x: In<Nothing>) {}
fun append3(x: In<Collection<*>>) {}
fun <E> append4(x: E) {}
fun <E: Collection<*>> append4(x: E) {}
fun main() {
SmartList(<!PROGRESSIONS_CHANGING_RESOLVE_ERROR("fun <E> SmartList(x: Collection<E>): Unit")!>1..2<!>) // warning
SmartList<IntRange>(1..10) // no warning
append(<!PROGRESSIONS_CHANGING_RESOLVE_ERROR("fun append(x: Collection<*>): Unit")!>1..10<!>) // warning
append((1..10) as Any) // no warning
append((1..10) as Iterable<Int>) // 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(<!PROGRESSIONS_CHANGING_RESOLVE_ERROR("fun <E : Collection<*>> append4(x: E): Unit")!>1..10<!>) // warning
}
@@ -0,0 +1,20 @@
package
public fun </*0*/ E> SmartList(/*0*/ x: E): kotlin.Unit
public fun </*0*/ E> SmartList(/*0*/ x: kotlin.collections.Collection<E>): 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.Nothing>): kotlin.Unit
public fun append3(/*0*/ x: In<kotlin.collections.Collection<*>>): kotlin.Unit
public fun </*0*/ E> append4(/*0*/ x: E): kotlin.Unit
public fun </*0*/ E : kotlin.collections.Collection<*>> append4(/*0*/ x: E): kotlin.Unit
public fun main(): kotlin.Unit
public final class In</*0*/ in T> {
public constructor In</*0*/ in T>(/*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
}
@@ -4545,6 +4545,24 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/checkArguments/kt1940.kt"); 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 @Test
@TestMetadata("overloadedFunction.kt") @TestMetadata("overloadedFunction.kt")
public void testOverloadedFunction() throws Exception { public void testOverloadedFunction() throws Exception {
@@ -248,6 +248,11 @@ enum class LanguageFeature(
ProhibitConfusingSyntaxInWhenBranches(KOTLIN_1_8, kind = BUG_FIX), // KT-48385 ProhibitConfusingSyntaxInWhenBranches(KOTLIN_1_8, kind = BUG_FIX), // KT-48385
UseConsistentRulesForPrivateConstructorsOfSealedClasses(sinceVersion = KOTLIN_1_8, kind = BUG_FIX), // KT-44866 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 // Temporarily disabled, see KT-27084/KT-22379
SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX), 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_6(1, 6),
KOTLIN_1_7(1, 7), KOTLIN_1_7(1, 7),
KOTLIN_1_8(1, 8), KOTLIN_1_8(1, 8),
KOTLIN_1_9(1, 9),
; ;
override val isStable: Boolean override val isStable: Boolean