Introduced ConstraintError for storing errors in the constraint system
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
|
||||
open class ConstraintError(val constraintPosition: ConstraintPosition)
|
||||
|
||||
class TypeConstructorMismatch(constraintPosition: ConstraintPosition): ConstraintError(constraintPosition)
|
||||
|
||||
class ErrorInConstrainingType(constraintPosition: ConstraintPosition): ConstraintError(constraintPosition)
|
||||
|
||||
class CannotCapture(constraintPosition: ConstraintPosition, val typeVariable: TypeParameterDescriptor): ConstraintError(constraintPosition)
|
||||
+28
-51
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
|
||||
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedureCallbacks
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import java.util.LinkedHashMap
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.*
|
||||
import java.util.HashMap
|
||||
@@ -52,9 +51,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
}
|
||||
|
||||
private val typeParameterBounds = LinkedHashMap<TypeParameterDescriptor, TypeBoundsImpl>()
|
||||
private val errorConstraintPositions = HashSet<ConstraintPosition>()
|
||||
private var hasErrorInConstrainingTypes: Boolean = false
|
||||
private var cannotCaptureTypesError: Boolean = false
|
||||
private val errors = ArrayList<ConstraintError>()
|
||||
|
||||
private val constraintSystemStatus = object : ConstraintSystemStatus {
|
||||
// for debug ConstraintsUtil.getDebugMessageForStatus might be used
|
||||
@@ -63,51 +60,32 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
|
||||
override fun hasContradiction() = hasTypeConstructorMismatch() || hasConflictingConstraints() || hasCannotCaptureTypesError()
|
||||
|
||||
override fun hasViolatedUpperBound(): Boolean {
|
||||
if (isSuccessful()) return false
|
||||
return getSystemWithoutWeakConstraints().getStatus().isSuccessful()
|
||||
}
|
||||
override fun hasViolatedUpperBound() = !isSuccessful() && getSystemWithoutWeakConstraints().getStatus().isSuccessful()
|
||||
|
||||
override fun hasConflictingConstraints(): Boolean {
|
||||
for (typeBounds in typeParameterBounds.values()) {
|
||||
if (typeBounds.getValues().size() > 1) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
override fun hasConflictingConstraints() = typeParameterBounds.values().any { it.getValues().size() > 1 }
|
||||
|
||||
override fun hasUnknownParameters(): Boolean {
|
||||
for (typeBounds in typeParameterBounds.values()) {
|
||||
if (typeBounds.isEmpty()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
override fun hasUnknownParameters() = typeParameterBounds.values().any { it.isEmpty() }
|
||||
|
||||
override fun hasTypeConstructorMismatch() = !errorConstraintPositions.isEmpty()
|
||||
override fun hasTypeConstructorMismatch() = errors.any { it is TypeConstructorMismatch }
|
||||
|
||||
override fun hasTypeConstructorMismatchAt(constraintPosition: ConstraintPosition) =
|
||||
errorConstraintPositions.contains(constraintPosition)
|
||||
errors.any { it is TypeConstructorMismatch && it.constraintPosition == constraintPosition }
|
||||
|
||||
override fun hasOnlyErrorsFromPosition(constraintPosition: ConstraintPosition): Boolean {
|
||||
if (isSuccessful()) return false
|
||||
val systemWithoutConstraintsFromPosition = filterConstraintsOut(constraintPosition)
|
||||
if (systemWithoutConstraintsFromPosition.getStatus().isSuccessful()) {
|
||||
return true
|
||||
}
|
||||
if (errorConstraintPositions.size() == 1 && errorConstraintPositions.contains(constraintPosition)) {
|
||||
// e.g. if systemWithoutConstraintsFromPosition has unknown type parameters, it's not successful
|
||||
return true
|
||||
}
|
||||
return false
|
||||
if (filterConstraintsOut(constraintPosition).getStatus().isSuccessful()) return true
|
||||
return errors.isNotEmpty() && errors.all { it.constraintPosition == constraintPosition }
|
||||
}
|
||||
|
||||
override fun hasErrorInConstrainingTypes() = hasErrorInConstrainingTypes
|
||||
override fun hasErrorInConstrainingTypes() = errors.any { it is ErrorInConstrainingType }
|
||||
|
||||
override fun hasCannotCaptureTypesError() = cannotCaptureTypesError
|
||||
override fun hasCannotCaptureTypesError() = errors.any { it is CannotCapture }
|
||||
}
|
||||
|
||||
private fun getParameterToInferredValueMap(typeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>, getDefaultTypeProjection: Function1<TypeParameterDescriptor, TypeProjection>): Map<TypeParameterDescriptor, TypeProjection> {
|
||||
private fun getParameterToInferredValueMap(
|
||||
typeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>,
|
||||
getDefaultTypeProjection: (TypeParameterDescriptor) -> TypeProjection
|
||||
): Map<TypeParameterDescriptor, TypeProjection> {
|
||||
val substitutionContext = HashMap<TypeParameterDescriptor, TypeProjection>()
|
||||
for ((typeParameter, typeBounds) in typeParameterBounds) {
|
||||
val typeProjection: TypeProjection
|
||||
@@ -116,7 +94,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
typeProjection = TypeProjectionImpl(value)
|
||||
}
|
||||
else {
|
||||
typeProjection = getDefaultTypeProjection.invoke(typeParameter)
|
||||
typeProjection = getDefaultTypeProjection(typeParameter)
|
||||
}
|
||||
substitutionContext.put(typeParameter, typeProjection)
|
||||
}
|
||||
@@ -146,8 +124,9 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
for (declaredUpperBound in typeVariable.getUpperBounds()) {
|
||||
if (KotlinBuiltIns.getInstance().getNullableAnyType() == declaredUpperBound) continue //todo remove this line (?)
|
||||
val substitutedBound = constantSubstitutor?.substitute(declaredUpperBound, Variance.INVARIANT)
|
||||
if (substitutedBound != null && !isErrorOrSpecialType(substitutedBound)) {
|
||||
typeBounds.addBound(UPPER_BOUND, substitutedBound, TYPE_BOUND_POSITION.position(typeVariable.getIndex()))
|
||||
val position = TYPE_BOUND_POSITION.position(typeVariable.getIndex())
|
||||
if (substitutedBound != null && !isErrorOrSpecialType(substitutedBound, position)) {
|
||||
typeBounds.addBound(UPPER_BOUND, substitutedBound, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,10 +172,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
val newTypeParameter = substituteTypeVariable(typeParameter)
|
||||
newSystem.typeParameterBounds.put(newTypeParameter!!, replaceTypeBounds(typeBounds))
|
||||
}
|
||||
newSystem.errorConstraintPositions.addAll(errorConstraintPositions.filter(filterConstraintPosition))
|
||||
//todo if 'filterConstraintPosition' is not trivial, it's incorrect to just copy 'hasErrorInConstrainingTypes'
|
||||
newSystem.hasErrorInConstrainingTypes = hasErrorInConstrainingTypes
|
||||
newSystem.cannotCaptureTypesError = cannotCaptureTypesError
|
||||
newSystem.errors.addAll(errors.filter { filterConstraintPosition(it.constraintPosition) })
|
||||
return newSystem
|
||||
}
|
||||
|
||||
@@ -232,9 +208,10 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
}
|
||||
|
||||
override fun capture(typeVariable: JetType, typeProjection: TypeProjection): Boolean {
|
||||
if (isMyTypeVariable(typeVariable) && constraintPosition.isCaptureAllowed()) {
|
||||
val myTypeVariable = getMyTypeVariable(typeVariable)
|
||||
if (myTypeVariable != null && constraintPosition.isCaptureAllowed()) {
|
||||
if (!isTopLevel) {
|
||||
cannotCaptureTypesError = true
|
||||
errors.add(CannotCapture(constraintPosition, myTypeVariable))
|
||||
}
|
||||
generateTypeParameterCaptureConstraint(typeVariable, typeProjection, constraintPosition)
|
||||
return true
|
||||
@@ -243,20 +220,20 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
}
|
||||
|
||||
override fun noCorrespondingSupertype(subtype: JetType, supertype: JetType): Boolean {
|
||||
errorConstraintPositions.add(constraintPosition)
|
||||
errors.add(TypeConstructorMismatch(constraintPosition))
|
||||
return true
|
||||
}
|
||||
})
|
||||
doAddConstraint(constraintKind, subType, superType, constraintPosition, typeCheckingProcedure)
|
||||
}
|
||||
|
||||
private fun isErrorOrSpecialType(type: JetType?): Boolean {
|
||||
private fun isErrorOrSpecialType(type: JetType?, constraintPosition: ConstraintPosition): Boolean {
|
||||
if (TypeUtils.isDontCarePlaceholder(type) || ErrorUtils.isUninferredParameter(type)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (type == null || (type.isError() && type != TypeUtils.PLACEHOLDER_FUNCTION_TYPE)) {
|
||||
hasErrorInConstrainingTypes = true
|
||||
errors.add(ErrorInConstrainingType(constraintPosition))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -269,7 +246,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
constraintPosition: ConstraintPosition,
|
||||
typeCheckingProcedure: TypeCheckingProcedure
|
||||
) {
|
||||
if (isErrorOrSpecialType(subType) || isErrorOrSpecialType(superType)) return
|
||||
if (isErrorOrSpecialType(subType, constraintPosition) || isErrorOrSpecialType(superType, constraintPosition)) return
|
||||
if (subType == null || superType == null) return
|
||||
|
||||
assert(superType != TypeUtils.PLACEHOLDER_FUNCTION_TYPE) {
|
||||
@@ -282,7 +259,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
// a constraint binds type parameter and any function type, so there is no new info and no error
|
||||
return
|
||||
}
|
||||
errorConstraintPositions.add(constraintPosition)
|
||||
errors.add(TypeConstructorMismatch(constraintPosition))
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -379,7 +356,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
val typeVariable = getMyTypeVariable(parameterType)!!
|
||||
if (!KotlinBuiltIns.isNullableAny(typeVariable.getUpperBoundsAsType())
|
||||
&& constrainingTypeProjection.getProjectionKind() == Variance.IN_VARIANCE) {
|
||||
cannotCaptureTypesError = true
|
||||
errors.add(CannotCapture(constraintPosition, typeVariable))
|
||||
}
|
||||
val typeBounds = getTypeBounds(typeVariable)
|
||||
val typeProjection = if (parameterType.isMarkedNullable()) {
|
||||
|
||||
Reference in New Issue
Block a user