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:
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -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
|
||||||
|
|||||||
+1
-1
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -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
|
||||||
|
|||||||
+1
-1
@@ -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)
|
||||||
+4
-4
@@ -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 }
|
||||||
}
|
}
|
||||||
+8
-22
@@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -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/>
|
||||||
|
|||||||
Reference in New Issue
Block a user