[NI] Support wrong number of type arguments and integer constants.

- report WRONG_NUMBER_OF_TYPE_ARGUMENTS
- make integral types work again: IntegerValueType is represented as {Int & Byte & Short & Long} in the constraint system
This commit is contained in:
Dmitry Petrov
2016-10-25 12:41:02 +03:00
committed by Stanislav Erokhin
parent f5c59b1343
commit d67b51e91a
4 changed files with 30 additions and 19 deletions
@@ -20,10 +20,7 @@ import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.*
import org.jetbrains.kotlin.psi.Call
import org.jetbrains.kotlin.psi.KtConstantExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.calls.components.*
@@ -61,7 +58,19 @@ class DiagnosticReporterByTrackingStrategy(
}
override fun onTypeArguments(diagnostic: KotlinCallDiagnostic) {
val psiCallElement = psiKotlinCall.psiCall.callElement
val reportElement =
if (psiCallElement is KtCallExpression)
psiCallElement.typeArgumentList ?: psiCallElement.calleeExpression ?: psiCallElement
else
psiCallElement
when (diagnostic) {
is WrongCountOfTypeArguments -> {
val expectedTypeArgumentsCount = diagnostic.descriptor.typeParameters.size
trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(reportElement, expectedTypeArgumentsCount, diagnostic.descriptor))
}
}
}
override fun onCallName(diagnostic: KotlinCallDiagnostic) {
@@ -25,8 +25,7 @@ import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.IMPOSSIBLE_TO_GENERATE
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.RUNTIME_ERROR
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.*
import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError
import org.jetbrains.kotlin.types.IndexedParametersSubstitution
import org.jetbrains.kotlin.types.TypeSubstitutor
@@ -141,7 +140,6 @@ internal object CreteDescriptorWithFreshTypeVariables : ResolutionPart {
return emptyList()
}
// add explicit type parameter
for (index in typeParameters.indices) {
val typeParameter = typeParameters[index]
val typeArgument = typeArgumentMappingByOriginal.getTypeArgument(typeParameter)
@@ -28,19 +28,16 @@ class TypeArgumentsToParametersMapper {
abstract fun getTypeArgument(typeParameterDescriptor: TypeParameterDescriptor): TypeArgument
object NoExplicitArguments : TypeArgumentsMapping(emptyList()) {
override fun getTypeArgument(typeParameterDescriptor: TypeParameterDescriptor): TypeArgument {
return TypeArgumentPlaceholder
}
override fun getTypeArgument(typeParameterDescriptor: TypeParameterDescriptor): TypeArgument =
TypeArgumentPlaceholder
}
class TypeArgumentsMappingImpl(
diagnostics: List<KotlinCallDiagnostic>,
private val typeParameterToArgumentMap: Map<TypeParameterDescriptor, TypeArgument>
): TypeArgumentsMapping(diagnostics) {
override fun getTypeArgument(typeParameterDescriptor: TypeParameterDescriptor): TypeArgument {
return typeParameterToArgumentMap[typeParameterDescriptor] ?:
error("No argument for parameter: $typeParameterDescriptor. Reported diagnostics: $diagnostics")
}
override fun getTypeArgument(typeParameterDescriptor: TypeParameterDescriptor): TypeArgument =
typeParameterToArgumentMap[typeParameterDescriptor] ?: TypeArgumentPlaceholder
}
}
@@ -16,16 +16,15 @@
package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.resolve.calls.components.CommonSupertypeCalculator
import org.jetbrains.kotlin.resolve.calls.inference.components.FixationOrderCalculator.ResolveDirection
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.intersectTypes
import org.jetbrains.kotlin.types.singleBestRepresentative
import java.util.*
class ResultTypeResolver(val commonSupertypeCalculator: CommonSupertypeCalculator) {
@@ -76,14 +75,22 @@ class ResultTypeResolver(val commonSupertypeCalculator: CommonSupertypeCalculato
private fun convertLowerTypesWithKnowledgeOfNumberTypes(lowerConstraints: Collection<Constraint>): Collection<UnwrappedType> {
if (lowerConstraints.isEmpty()) return emptyList()
if (lowerConstraints.size == 1) return listOf(lowerConstraints.first().type)
val (numberLowerBounds, generalLowerBounds) = lowerConstraints.map { it.type }.partition { it.constructor is IntegerValueTypeConstructor }
val (numberLowerBounds, generalLowerBounds) = lowerConstraints.map { it.type }.partition { it.isNumberValueType() }
val numberType = commonSupertypeForNumberTypes(numberLowerBounds) ?: return generalLowerBounds
return generalLowerBounds + numberType
}
private fun KotlinType.isNumberValueType() =
constructor is IntegerValueTypeConstructor ||
(constructor is IntersectionTypeConstructor && constructor.supertypes.all { it.isPrimitiveIntegerType() } )
private fun KotlinType.isPrimitiveIntegerType() =
KotlinBuiltIns.isByte(this) ||
KotlinBuiltIns.isShort(this) ||
KotlinBuiltIns.isInt(this) ||
KotlinBuiltIns.isLong(this)
private fun commonSupertypeForNumberTypes(numberLowerBounds: Collection<UnwrappedType>): UnwrappedType? {
if (numberLowerBounds.isEmpty()) return null