[NI] Support @OnlyInputTypes annotation. #KT-29307 fixed

This commit is contained in:
Dmitriy Novozhilov
2019-03-21 17:36:17 +03:00
parent 0f7e91ff6d
commit e574106799
25 changed files with 474 additions and 32 deletions
@@ -8,9 +8,14 @@ package org.jetbrains.kotlin.resolve.calls.inference.model
import org.jetbrains.kotlin.resolve.calls.inference.trimToSize
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.typeUtil.unCapture
import kotlin.collections.ArrayList
import kotlin.collections.LinkedHashMap
@@ -27,6 +32,16 @@ class MutableVariableWithConstraints(
return simplifiedConstraints!!
}
// see @OnlyInputTypes annotation
val projectedInputCallTypes: Collection<UnwrappedType>
get() =
mutableConstraints.filter {
val position = it.position.from
position is ArgumentConstraintPosition || position is ReceiverConstraintPosition || position is ExpectedTypeConstraintPosition
}.map {
(it.type as KotlinType).unCapture().unwrap()
}
private val mutableConstraints = ArrayList(constraints)
private var simplifiedConstraints: List<Constraint>? = null
@@ -9,12 +9,16 @@ import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.inference.*
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.resolve.calls.model.OnlyInputTypesDiagnostic
import org.jetbrains.kotlin.types.IntersectionTypeConstructor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import kotlin.math.max
class NewConstraintSystemImpl(
@@ -247,7 +251,8 @@ class NewConstraintSystemImpl(
checkState(State.BUILDING, State.COMPLETION)
constraintInjector.addInitialEqualityConstraint(this, variable.defaultType(), resultType, FixVariableConstraintPosition(variable))
notFixedTypeVariables.remove(variable.freshTypeConstructor())
val variableWithConstraints = notFixedTypeVariables.remove(variable.freshTypeConstructor())
checkOnlyInputTypesAnnotation(variableWithConstraints, resultType)
for (variableWithConstraint in notFixedTypeVariables.values) {
variableWithConstraint.removeConstrains {
@@ -258,6 +263,25 @@ class NewConstraintSystemImpl(
storage.fixedTypeVariables[variable.freshTypeConstructor()] = resultType
}
private fun checkOnlyInputTypesAnnotation(
variableWithConstraints: MutableVariableWithConstraints?,
resultType: KotlinTypeMarker
) {
if (resultType !is KotlinType) return
if (variableWithConstraints == null || variableWithConstraints.typeVariable.safeAs<NewTypeVariable>()?.hasOnlyInputTypesAnnotation() != true ) return
val projectedInputCallTypes = variableWithConstraints.projectedInputCallTypes
val resultTypeIsInputType = projectedInputCallTypes.any { inputType ->
val constructor = inputType.constructor
if (constructor is IntersectionTypeConstructor)
constructor.supertypes.any { NewKotlinTypeChecker.equalTypes(resultType, it) }
else
NewKotlinTypeChecker.equalTypes(resultType, inputType)
}
if (!resultTypeIsInputType) {
addError(OnlyInputTypesDiagnostic(variableWithConstraints.typeVariable as NewTypeVariable))
}
}
// KotlinConstraintSystemCompleter.Context, PostponedArgumentsAnalyzer.Context
override fun canBeProper(type: KotlinTypeMarker): Boolean {
checkState(State.BUILDING, State.COMPLETION)
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOnlyInputTypesAnnotation
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.SimpleType
@@ -53,15 +54,21 @@ sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) : TypeVaria
nullable = false, memberScope = builtIns.any.unsubstitutedMemberScope
)
abstract fun hasOnlyInputTypesAnnotation(): Boolean
override fun toString() = freshTypeConstructor.toString()
}
class TypeVariableFromCallableDescriptor(
val originalTypeParameter: TypeParameterDescriptor
) : NewTypeVariable(originalTypeParameter.builtIns, originalTypeParameter.name.identifier)
) : NewTypeVariable(originalTypeParameter.builtIns, originalTypeParameter.name.identifier) {
override fun hasOnlyInputTypesAnnotation(): Boolean = originalTypeParameter.hasOnlyInputTypesAnnotation()
}
class TypeVariableForLambdaReturnType(
val lambdaArgument: LambdaKotlinCallArgument,
builtIns: KotlinBuiltIns,
name: String
) : NewTypeVariable(builtIns, name)
) : NewTypeVariable(builtIns, name) {
override fun hasOnlyInputTypesAnnotation(): Boolean = false
}
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceCandidate
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.*
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType
@@ -195,4 +196,10 @@ class ArgumentTypeMismatchDiagnostic(
override fun report(reporter: DiagnosticReporter) {
reporter.onCallArgument(expressionArgument, this)
}
}
class OnlyInputTypesDiagnostic(val typeVariable: NewTypeVariable) : KotlinCallDiagnostic(INAPPLICABLE) {
override fun report(reporter: DiagnosticReporter) {
reporter.onCall(this)
}
}