Process captured types with type variable inside properly, in the operations related with the type variables fixation

This commit is contained in:
Victor Petukhov
2021-03-15 12:53:18 +03:00
parent a2b1aa753b
commit 60f2f85be7
4 changed files with 35 additions and 21 deletions
@@ -143,7 +143,7 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
}
@Test
@TestMetadata("javaAnnotationArrayValueDefault.kt")
@TestMetadata("javaAnnotatestInferenceWithTypeVariableInsideCapturedType tionArrayValueDefault.kt")
public void testJavaAnnotationArrayValueDefault() throws Exception {
runTest("compiler/testData/codegen/box/annotations/javaAnnotationArrayValueDefault.kt");
}
@@ -94,7 +94,7 @@ class ConstraintIncorporator(
val freshTypeConstructor = typeVariable.freshTypeConstructor()
for (typeVariableWithConstraint in this@insideOtherConstraint.allTypeVariablesWithConstraints) {
val constraintsWhichConstraintMyVariable = typeVariableWithConstraint.constraints.filter {
it.type.contains { it.typeConstructor() == freshTypeConstructor }
containsTypeVariable(it.type, freshTypeConstructor)
}
constraintsWhichConstraintMyVariable.forEach {
generateNewConstraint(typeVariableWithConstraint.typeVariable, it, typeVariable, constraint)
@@ -130,7 +130,7 @@ class ConstraintIncorporator(
otherConstraint: Constraint
) {
val isBaseGenericType = baseConstraint.type.argumentsCount() != 0
val isOtherCapturedType = otherConstraint.type.isCapturedType()
val isBaseOrOtherCapturedType = baseConstraint.type.isCapturedType() || otherConstraint.type.isCapturedType()
val (type, needApproximation) = when (otherConstraint.kind) {
ConstraintKind.EQUALITY -> {
otherConstraint.type to false
@@ -145,9 +145,9 @@ class ConstraintIncorporator(
* incorporatedConstraint = Approx(CapturedType(out Number)) <: TypeVariable(A) => Nothing <: TypeVariable(A)
* TODO: implement this for generics and captured types
*/
if (baseConstraint.kind == ConstraintKind.LOWER && !isBaseGenericType && !isOtherCapturedType) {
if (baseConstraint.kind == ConstraintKind.LOWER && !isBaseGenericType && !isBaseOrOtherCapturedType) {
nothingType() to false
} else if (baseConstraint.kind == ConstraintKind.UPPER && !isBaseGenericType && !isOtherCapturedType) {
} else if (baseConstraint.kind == ConstraintKind.UPPER && !isBaseGenericType && !isBaseOrOtherCapturedType) {
otherConstraint.type to false
} else {
createCapturedType(
@@ -168,9 +168,9 @@ class ConstraintIncorporator(
* incorporatedConstraint = TypeVariable(A) <: Approx(CapturedType(in Number)) => TypeVariable(A) <: Any?
* TODO: implement this for generics and captured types
*/
if (baseConstraint.kind == ConstraintKind.UPPER && !isBaseGenericType && !isOtherCapturedType) {
if (baseConstraint.kind == ConstraintKind.UPPER && !isBaseGenericType && !isBaseOrOtherCapturedType) {
nullableAnyType() to false
} else if (baseConstraint.kind == ConstraintKind.LOWER && !isBaseGenericType && !isOtherCapturedType) {
} else if (baseConstraint.kind == ConstraintKind.LOWER && !isBaseGenericType && !isBaseOrOtherCapturedType) {
otherConstraint.type to false
} else {
createCapturedType(
@@ -168,17 +168,33 @@ class VariableFixationFinder(
}
}
inline fun TypeSystemInferenceExtensionContext.isProperTypeForFixation(
type: KotlinTypeMarker,
isProper: (KotlinTypeMarker) -> Boolean
): Boolean {
if (!isProper(type)) return false
if (type.isCapturedType()) {
val projection = (type as? SimpleTypeMarker)?.asCapturedType()?.typeConstructorProjection() ?: return true
if (projection.isStarProjection()) return true
inline fun TypeSystemInferenceExtensionContext.isProperTypeForFixation(type: KotlinTypeMarker, isProper: (KotlinTypeMarker) -> Boolean) =
isProper(type) && extractProjectionsForAllCapturedTypes(type).all(isProper)
if (!isProper(projection.getType())) return false
@OptIn(ExperimentalStdlibApi::class)
fun TypeSystemInferenceExtensionContext.extractProjectionsForAllCapturedTypes(baseType: KotlinTypeMarker): Set<KotlinTypeMarker> {
val simpleBaseType = baseType.asSimpleType()
return buildSet {
val projectionType = if (simpleBaseType is CapturedTypeMarker) {
val typeArgument = simpleBaseType.typeConstructorProjection().takeIf { !it.isStarProjection() } ?: return@buildSet
typeArgument.getType().also(::add)
} else baseType
val argumentsCount = projectionType.argumentsCount().takeIf { it != 0 } ?: return@buildSet
for (i in 0 until argumentsCount) {
val typeArgument = projectionType.getArgument(i).takeIf { !it.isStarProjection() } ?: continue
addAll(extractProjectionsForAllCapturedTypes(typeArgument.getType()))
}
}
}
fun TypeSystemInferenceExtensionContext.containsTypeVariable(type: KotlinTypeMarker, typeVariable: TypeConstructorMarker): Boolean {
if (type.contains { it.typeConstructor() == typeVariable }) return true
val typeProjections = extractProjectionsForAllCapturedTypes(type)
return typeProjections.any { typeProjectionsType ->
typeProjectionsType.contains { it.typeConstructor() == typeVariable }
}
return true
}
@@ -336,9 +336,7 @@ class NewConstraintSystemImpl(
val variableWithConstraints = notFixedTypeVariables.remove(freshTypeConstructor)
for (otherVariableWithConstraints in notFixedTypeVariables.values) {
otherVariableWithConstraints.removeConstrains { otherConstraint ->
otherConstraint.type.contains { it.typeConstructor() == freshTypeConstructor }
}
otherVariableWithConstraints.removeConstrains { containsTypeVariable(it.type, freshTypeConstructor) }
}
storage.fixedTypeVariables[freshTypeConstructor] = resultType