Generate specific type inference error

only for bounds from 'parameter' positions (receiver & value arguments).
They can be marked as error (with red color) explicitly later.

Replaced getSystemWithoutWeakConstraints() with filterConstraintsOut(TYPE_BOUND_POSITION)
This commit is contained in:
Svetlana Isakova
2015-07-07 21:26:20 +03:00
parent 4c8b75928e
commit 3c698992e0
9 changed files with 22 additions and 35 deletions
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
@@ -244,7 +245,7 @@ public object Renderers {
LOG.assertTrue(status.hasViolatedUpperBound(),
renderDebugMessage("Upper bound violated renderer is applied for incorrect status", inferenceErrorData))
val systemWithoutWeakConstraints = constraintSystem.getSystemWithoutWeakConstraints()
val systemWithoutWeakConstraints = constraintSystem.filterConstraintsOut(ConstraintPositionKind.TYPE_BOUND_POSITION)
val typeParameterDescriptor = inferenceErrorData.descriptor.getTypeParameters().firstOrNull {
!ConstraintsUtil.checkUpperBoundIsSatisfied(systemWithoutWeakConstraints, it, true)
}
@@ -78,7 +78,7 @@ public fun CallableDescriptor.hasInferredReturnType(constraintSystem: Constraint
if (hasReturnTypeDependentOnUninferredParams(constraintSystem)) return false
// Expected type mismatch was reported before as 'TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH'
if (constraintSystem.getStatus().hasOnlyErrorsFromPosition(EXPECTED_TYPE_POSITION.position())) return false
if (constraintSystem.getStatus().hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION)) return false
return true
}
@@ -208,12 +208,12 @@ public abstract class AbstractTracingStrategy implements TracingStrategy {
// (it's useful, when the arguments, e.g. lambdas or calls are incomplete)
return;
}
if (status.hasOnlyErrorsFromPosition(EXPECTED_TYPE_POSITION.position())) {
if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION)) {
JetType declaredReturnType = data.descriptor.getReturnType();
if (declaredReturnType == null) return;
ConstraintSystem systemWithoutExpectedTypeConstraint =
((ConstraintSystemImpl) constraintSystem).filterConstraintsOut(EXPECTED_TYPE_POSITION.position());
((ConstraintSystemImpl) constraintSystem).filterConstraintsOut(EXPECTED_TYPE_POSITION);
JetType substitutedReturnType = systemWithoutExpectedTypeConstraint.getResultingSubstitutor().substitute(
declaredReturnType, Variance.OUT_VARIANCE);
assert substitutedReturnType != null; //todo
@@ -375,7 +375,7 @@ public class ControlStructureTypingUtils {
return;
}
JetExpression expression = (JetExpression) call.getCallElement();
if (status.hasOnlyErrorsFromPosition(EXPECTED_TYPE_POSITION.position()) || status.hasConflictingConstraints()) {
if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION) || status.hasConflictingConstraints()) {
expression.accept(checkTypeVisitor, new CheckTypeContext(trace, data.expectedType));
return;
}
@@ -10,7 +10,7 @@ status:
-hasConflictingConstraints: false
-hasContradiction: true
-hasErrorInConstrainingTypes: false
-hasTypeConstructorMismatch: true
-hasTypeConstructorMismatch: false
-hasTypeInferenceIncorporationError: true
-hasUnknownParameters: true
-hasViolatedUpperBound: false
@@ -31,4 +31,4 @@ class TypeInferenceError(constraintPosition: ConstraintPosition): ConstraintErro
class CannotCapture(constraintPosition: ConstraintPosition, val typeVariable: TypeParameterDescriptor): ConstraintError(constraintPosition)
fun newTypeInferenceOrConstructorMismatchError(constraintPosition: ConstraintPosition) =
if (constraintPosition is CompoundConstraintPosition) TypeInferenceError(constraintPosition) else TypeConstructorMismatch(constraintPosition)
if (constraintPosition.isParameter()) TypeConstructorMismatch(constraintPosition) else TypeInferenceError(constraintPosition)
@@ -44,7 +44,7 @@ public trait ConstraintPosition {
fun isStrong(): Boolean = kind != TYPE_BOUND_POSITION
fun isCaptureAllowed(): Boolean = kind in setOf(VALUE_PARAMETER_POSITION, RECEIVER_POSITION)
fun isParameter(): Boolean = kind in setOf(VALUE_PARAMETER_POSITION, RECEIVER_POSITION)
}
private open data class ConstraintPositionImpl(override val kind: ConstraintPositionKind) : ConstraintPosition {
@@ -58,13 +58,13 @@ class CompoundConstraintPosition(
vararg positions: ConstraintPosition
) : ConstraintPositionImpl(ConstraintPositionKind.COMPOUND_CONSTRAINT_POSITION) {
val positions: Collection<ConstraintPosition> =
positions.flatMap { if (it is CompoundConstraintPosition) it.positions else listOf(it) }.toCollection(LinkedHashSet<ConstraintPosition>())
positions.flatMap { if (it is CompoundConstraintPosition) it.positions else listOf(it) }.toSet()
override fun isStrong() = positions.any { it.isStrong() }
override fun toString() = "$kind(${positions.joinToString()})"
}
fun ConstraintPosition.equalsOrContains(position: ConstraintPosition): Boolean {
return if (this !is CompoundConstraintPosition) this == position else positions.any { it == position }
fun ConstraintPosition.derivedFrom(kind: ConstraintPositionKind): Boolean {
return if (this !is CompoundConstraintPosition) this.kind == kind else positions.any { it.kind == kind }
}
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.CompoundC
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.TYPE_BOUND_POSITION
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.equalsOrContains
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.derivedFrom
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.ErrorUtils.FunctionPlaceholderTypeConstructor
@@ -84,7 +84,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
override fun hasContradiction() = hasTypeConstructorMismatch() || hasConflictingConstraints()
|| hasCannotCaptureTypesError() || hasTypeInferenceIncorporationError()
override fun hasViolatedUpperBound() = !isSuccessful() && getSystemWithoutWeakConstraints().getStatus().isSuccessful()
override fun hasViolatedUpperBound() = !isSuccessful() && filterConstraintsOut(TYPE_BOUND_POSITION).getStatus().isSuccessful()
override fun hasConflictingConstraints() = typeParameterBounds.values().any { it.values.size() > 1 }
@@ -92,10 +92,10 @@ public class ConstraintSystemImpl : ConstraintSystem {
override fun hasTypeConstructorMismatch() = errors.any { it is TypeConstructorMismatch }
override fun hasOnlyErrorsFromPosition(constraintPosition: ConstraintPosition): Boolean {
override fun hasOnlyErrorsDerivedFrom(kind: ConstraintPositionKind): Boolean {
if (isSuccessful()) return false
if (filterConstraintsOut(constraintPosition).getStatus().isSuccessful()) return true
return errors.isNotEmpty() && errors.all { it.constraintPosition.equalsOrContains(constraintPosition) }
if (filterConstraintsOut(kind).getStatus().isSuccessful()) return true
return errors.isNotEmpty() && errors.all { it.constraintPosition.derivedFrom(kind) }
}
override fun hasErrorInConstrainingTypes() = errors.any { it is ErrorInConstrainingType }
@@ -175,22 +175,8 @@ public class ConstraintSystemImpl : ConstraintSystem {
public fun copy(): ConstraintSystem = createNewConstraintSystemFromThis { true }
public fun filterConstraintsOut(excludePosition: ConstraintPosition): ConstraintSystem {
return filterConstraints { !it.equalsOrContains(excludePosition) }
}
public fun filterConstraints(condition: (ConstraintPosition) -> Boolean): ConstraintSystem {
return createNewConstraintSystemFromThis(condition)
}
public fun getSystemWithoutWeakConstraints(): ConstraintSystem {
return filterConstraints(fun (constraintPosition): Boolean {
if (constraintPosition !is CompoundConstraintPosition) return constraintPosition.isStrong()
// 'isStrong' for compound means 'has some strong constraints'
// but for testing absence of weak constraints we need 'has only strong constraints' here
return constraintPosition.positions.all { it.isStrong() }
})
public fun filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem {
return createNewConstraintSystemFromThis { !it.derivedFrom(excludePositionKind) }
}
private fun createNewConstraintSystemFromThis(
@@ -252,7 +238,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
if (isMyTypeVariable(typeProjection.getType())) return false
val myTypeVariable = getMyTypeVariable(typeVariable)
if (myTypeVariable != null && constraintPosition.isCaptureAllowed()) {
if (myTypeVariable != null && constraintPosition.isParameter()) {
if (depth > 0) {
errors.add(CannotCapture(constraintPosition, myTypeVariable))
}
@@ -16,7 +16,7 @@
package org.jetbrains.kotlin.resolve.calls.inference
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
public trait ConstraintSystemStatus {
/**
@@ -69,7 +69,7 @@ public trait ConstraintSystemStatus {
* Returns <tt>true</tt> if there is type constructor mismatch only in constraintPosition or
* constraint system is successful without constraints from this position.
*/
public fun hasOnlyErrorsFromPosition(constraintPosition: ConstraintPosition): Boolean
public fun hasOnlyErrorsDerivedFrom(kind: ConstraintPositionKind): Boolean
/**
* Returns <tt>true</tt> if there is an error in constraining types. <p/>