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.LOWER_BOUND
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_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.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.RECEIVER_POSITION
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
@@ -244,7 +245,7 @@ public object Renderers {
LOG.assertTrue(status.hasViolatedUpperBound(), LOG.assertTrue(status.hasViolatedUpperBound(),
renderDebugMessage("Upper bound violated renderer is applied for incorrect status", inferenceErrorData)) 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 { val typeParameterDescriptor = inferenceErrorData.descriptor.getTypeParameters().firstOrNull {
!ConstraintsUtil.checkUpperBoundIsSatisfied(systemWithoutWeakConstraints, it, true) !ConstraintsUtil.checkUpperBoundIsSatisfied(systemWithoutWeakConstraints, it, true)
} }
@@ -78,7 +78,7 @@ public fun CallableDescriptor.hasInferredReturnType(constraintSystem: Constraint
if (hasReturnTypeDependentOnUninferredParams(constraintSystem)) return false if (hasReturnTypeDependentOnUninferredParams(constraintSystem)) return false
// Expected type mismatch was reported before as 'TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH' // 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 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) // (it's useful, when the arguments, e.g. lambdas or calls are incomplete)
return; return;
} }
if (status.hasOnlyErrorsFromPosition(EXPECTED_TYPE_POSITION.position())) { if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION)) {
JetType declaredReturnType = data.descriptor.getReturnType(); JetType declaredReturnType = data.descriptor.getReturnType();
if (declaredReturnType == null) return; if (declaredReturnType == null) return;
ConstraintSystem systemWithoutExpectedTypeConstraint = ConstraintSystem systemWithoutExpectedTypeConstraint =
((ConstraintSystemImpl) constraintSystem).filterConstraintsOut(EXPECTED_TYPE_POSITION.position()); ((ConstraintSystemImpl) constraintSystem).filterConstraintsOut(EXPECTED_TYPE_POSITION);
JetType substitutedReturnType = systemWithoutExpectedTypeConstraint.getResultingSubstitutor().substitute( JetType substitutedReturnType = systemWithoutExpectedTypeConstraint.getResultingSubstitutor().substitute(
declaredReturnType, Variance.OUT_VARIANCE); declaredReturnType, Variance.OUT_VARIANCE);
assert substitutedReturnType != null; //todo assert substitutedReturnType != null; //todo
@@ -375,7 +375,7 @@ public class ControlStructureTypingUtils {
return; return;
} }
JetExpression expression = (JetExpression) call.getCallElement(); 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)); expression.accept(checkTypeVisitor, new CheckTypeContext(trace, data.expectedType));
return; return;
} }
@@ -10,7 +10,7 @@ status:
-hasConflictingConstraints: false -hasConflictingConstraints: false
-hasContradiction: true -hasContradiction: true
-hasErrorInConstrainingTypes: false -hasErrorInConstrainingTypes: false
-hasTypeConstructorMismatch: true -hasTypeConstructorMismatch: false
-hasTypeInferenceIncorporationError: true -hasTypeInferenceIncorporationError: true
-hasUnknownParameters: true -hasUnknownParameters: true
-hasViolatedUpperBound: false -hasViolatedUpperBound: false
@@ -31,4 +31,4 @@ class TypeInferenceError(constraintPosition: ConstraintPosition): ConstraintErro
class CannotCapture(constraintPosition: ConstraintPosition, val typeVariable: TypeParameterDescriptor): ConstraintError(constraintPosition) class CannotCapture(constraintPosition: ConstraintPosition, val typeVariable: TypeParameterDescriptor): ConstraintError(constraintPosition)
fun newTypeInferenceOrConstructorMismatchError(constraintPosition: 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 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 { private open data class ConstraintPositionImpl(override val kind: ConstraintPositionKind) : ConstraintPosition {
@@ -58,13 +58,13 @@ class CompoundConstraintPosition(
vararg positions: ConstraintPosition vararg positions: ConstraintPosition
) : ConstraintPositionImpl(ConstraintPositionKind.COMPOUND_CONSTRAINT_POSITION) { ) : ConstraintPositionImpl(ConstraintPositionKind.COMPOUND_CONSTRAINT_POSITION) {
val positions: Collection<ConstraintPosition> = 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 isStrong() = positions.any { it.isStrong() }
override fun toString() = "$kind(${positions.joinToString()})" override fun toString() = "$kind(${positions.joinToString()})"
} }
fun ConstraintPosition.equalsOrContains(position: ConstraintPosition): Boolean { fun ConstraintPosition.derivedFrom(kind: ConstraintPositionKind): Boolean {
return if (this !is CompoundConstraintPosition) this == position else positions.any { it == position } 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.ConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind 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.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.resolve.scopes.JetScope
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.ErrorUtils.FunctionPlaceholderTypeConstructor import org.jetbrains.kotlin.types.ErrorUtils.FunctionPlaceholderTypeConstructor
@@ -84,7 +84,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
override fun hasContradiction() = hasTypeConstructorMismatch() || hasConflictingConstraints() override fun hasContradiction() = hasTypeConstructorMismatch() || hasConflictingConstraints()
|| hasCannotCaptureTypesError() || hasTypeInferenceIncorporationError() || 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 } 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 hasTypeConstructorMismatch() = errors.any { it is TypeConstructorMismatch }
override fun hasOnlyErrorsFromPosition(constraintPosition: ConstraintPosition): Boolean { override fun hasOnlyErrorsDerivedFrom(kind: ConstraintPositionKind): Boolean {
if (isSuccessful()) return false if (isSuccessful()) return false
if (filterConstraintsOut(constraintPosition).getStatus().isSuccessful()) return true if (filterConstraintsOut(kind).getStatus().isSuccessful()) return true
return errors.isNotEmpty() && errors.all { it.constraintPosition.equalsOrContains(constraintPosition) } return errors.isNotEmpty() && errors.all { it.constraintPosition.derivedFrom(kind) }
} }
override fun hasErrorInConstrainingTypes() = errors.any { it is ErrorInConstrainingType } override fun hasErrorInConstrainingTypes() = errors.any { it is ErrorInConstrainingType }
@@ -175,22 +175,8 @@ public class ConstraintSystemImpl : ConstraintSystem {
public fun copy(): ConstraintSystem = createNewConstraintSystemFromThis { true } public fun copy(): ConstraintSystem = createNewConstraintSystemFromThis { true }
public fun filterConstraintsOut(excludePosition: ConstraintPosition): ConstraintSystem { public fun filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem {
return filterConstraints { !it.equalsOrContains(excludePosition) } return createNewConstraintSystemFromThis { !it.derivedFrom(excludePositionKind) }
}
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() }
})
} }
private fun createNewConstraintSystemFromThis( private fun createNewConstraintSystemFromThis(
@@ -252,7 +238,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
if (isMyTypeVariable(typeProjection.getType())) return false if (isMyTypeVariable(typeProjection.getType())) return false
val myTypeVariable = getMyTypeVariable(typeVariable) val myTypeVariable = getMyTypeVariable(typeVariable)
if (myTypeVariable != null && constraintPosition.isCaptureAllowed()) { if (myTypeVariable != null && constraintPosition.isParameter()) {
if (depth > 0) { if (depth > 0) {
errors.add(CannotCapture(constraintPosition, myTypeVariable)) errors.add(CannotCapture(constraintPosition, myTypeVariable))
} }
@@ -16,7 +16,7 @@
package org.jetbrains.kotlin.resolve.calls.inference 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 { public trait ConstraintSystemStatus {
/** /**
@@ -69,7 +69,7 @@ public trait ConstraintSystemStatus {
* Returns <tt>true</tt> if there is type constructor mismatch only in constraintPosition or * Returns <tt>true</tt> if there is type constructor mismatch only in constraintPosition or
* constraint system is successful without constraints from this position. * 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/> * Returns <tt>true</tt> if there is an error in constraining types. <p/>