[FIR] Remove hack for @OnlyInputTypes
#KT-65704
This commit is contained in:
committed by
Space Team
parent
b90598823e
commit
ef29879740
+6
@@ -28,6 +28,8 @@ FILE: onlyInputTypesCapturedTypeWithRecursiveBounds.kt
|
||||
}
|
||||
private final fun test(node: R|Foo<*>|): R|kotlin/Unit| {
|
||||
R|<local>/node|.R|SubstitutionOverride</Foo.data: R|kotlin/collections/Map<CapturedType(*), kotlin/Any?>|>|.R|kotlin/collections/get|<R|it(kotlin/Enum<*> & I)|, R|kotlin/Any?|>(Q|MyEnum|.R|/MyEnum.EnumEntry|)
|
||||
lval map: R|kotlin/collections/Map<out it(kotlin/Enum<*> & I), kotlin/Any?>| = R|<local>/node|.R|SubstitutionOverride</Foo.data: R|kotlin/collections/Map<CapturedType(*), kotlin/Any?>|>|
|
||||
R|<local>/map|.R|kotlin/collections/get|<R|it(kotlin/Enum<*> & I)|, R|kotlin/Any?|>(Q|MyEnum|.R|/MyEnum.EnumEntry|)
|
||||
}
|
||||
public open class FooEnumMap<P : R|kotlin/Enum<P>|, R|I|> : R|kotlin/Any| {
|
||||
public constructor<P : R|kotlin/Enum<P>|, R|I|>(data: R|java/util/EnumMap<P, kotlin/Any?>|): R|FooEnumMap<P>| {
|
||||
@@ -40,6 +42,8 @@ FILE: onlyInputTypesCapturedTypeWithRecursiveBounds.kt
|
||||
}
|
||||
private final fun test(node: R|FooEnumMap<*>|): R|kotlin/Unit| {
|
||||
R|<local>/node|.R|SubstitutionOverride</FooEnumMap.data: R|java/util/EnumMap<CapturedType(*), kotlin/Any?>|>|.R|kotlin/collections/get|<R|ft<it(kotlin/Enum<*> & I), it(kotlin/Enum<*>? & I?)>|, R|kotlin/Any!|>(Q|MyEnum|.R|/MyEnum.EnumEntry|)
|
||||
lval map: R|java/util/EnumMap<out it(kotlin/Enum<*> & I), kotlin/Any?>| = R|<local>/node|.R|SubstitutionOverride</FooEnumMap.data: R|java/util/EnumMap<CapturedType(*), kotlin/Any?>|>|
|
||||
R|<local>/map|.R|kotlin/collections/get|<R|ft<it(kotlin/Enum<out ft<it(kotlin/Enum<out ft<it(kotlin/Enum<*> & I), it(kotlin/Enum<*>? & I?)>> & I), it(kotlin/Enum<*>? & I?)>> & I), it(kotlin/Enum<*>? & I?)>|, R|kotlin/Any!|>(Q|MyEnum|.R|/MyEnum.EnumEntry|)
|
||||
}
|
||||
public open class Foo2<P : R|I|> : R|kotlin/Any| {
|
||||
public constructor<P : R|I|>(data: R|kotlin/collections/Map<P, kotlin/Any?>|): R|Foo2<P>| {
|
||||
@@ -52,6 +56,8 @@ FILE: onlyInputTypesCapturedTypeWithRecursiveBounds.kt
|
||||
}
|
||||
private final fun test(node: R|Foo2<*>|): R|kotlin/Unit| {
|
||||
R|<local>/node|.R|SubstitutionOverride</Foo2.data: R|kotlin/collections/Map<CapturedType(*), kotlin/Any?>|>|.R|kotlin/collections/get|<R|I|, R|kotlin/Any?|>(Q|MyEnum|.R|/MyEnum.EnumEntry|)
|
||||
lval map: R|kotlin/collections/Map<out I, kotlin/Any?>| = R|<local>/node|.R|SubstitutionOverride</Foo2.data: R|kotlin/collections/Map<CapturedType(*), kotlin/Any?>|>|
|
||||
R|<local>/map|.R|kotlin/collections/get|<R|I|, R|kotlin/Any?|>(Q|MyEnum|.R|/MyEnum.EnumEntry|)
|
||||
}
|
||||
public abstract interface I2 : R|kotlin/Any| {
|
||||
}
|
||||
|
||||
+10
-1
@@ -12,18 +12,26 @@ open class Foo<P>(val data: Map<P, Any?>) where P : Enum<P>, P : I
|
||||
|
||||
private fun test(node: Foo<*>) {
|
||||
node.data.get(MyEnum.EnumEntry)
|
||||
val map = node.data
|
||||
map.get(MyEnum.EnumEntry)
|
||||
}
|
||||
|
||||
open class FooEnumMap<P>(val data: EnumMap<P, Any?>) where P : Enum<P>, P : I
|
||||
|
||||
private fun test(node: FooEnumMap<*>) {
|
||||
node.data.get(MyEnum.EnumEntry)
|
||||
val map = node.data
|
||||
// TODO inferred type argument is giant multi-level type KT-65704
|
||||
// R|<local>/map|.R|kotlin/collections/get|<R|ft<it(kotlin/Enum<out ft<it(kotlin/Enum<out ft<it(kotlin/Enum<*> & I), it(kotlin/Enum<*>? & I?)>> & I), it(kotlin/Enum<*>? & I?)>> & I), it(kotlin/Enum<*>? & I?)>|, R|kotlin/Any!|>(Q|MyEnum|.R|/MyEnum.EnumEntry|)
|
||||
map.get(MyEnum.EnumEntry)
|
||||
}
|
||||
|
||||
open class Foo2<P : I>(val data: Map<P, Any?>)
|
||||
|
||||
private fun test(node: Foo2<*>) {
|
||||
node.data.get(MyEnum.EnumEntry)
|
||||
val map = node.data
|
||||
map.get(MyEnum.EnumEntry)
|
||||
}
|
||||
|
||||
interface I2
|
||||
@@ -34,4 +42,5 @@ open class Foo3<P>(val data: Map<P, Any?>) where P : I, P : I2
|
||||
|
||||
fun test3(node: Foo3<*>) {
|
||||
node.data.get(C)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-13
@@ -419,20 +419,8 @@ class ConstraintSystemCompleter(components: BodyResolveComponents) {
|
||||
TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN
|
||||
)
|
||||
|
||||
val resultTypeForOnlyInputTypes =
|
||||
if (with(ConeConstraintSystemUtilContext) { variableWithConstraints.typeVariable.hasOnlyInputTypesAttribute() }) {
|
||||
inferenceComponents.resultTypeResolver.findResultType(
|
||||
c,
|
||||
variableWithConstraints,
|
||||
TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN,
|
||||
isForOnlyInputTypes = true
|
||||
)
|
||||
} else {
|
||||
resultType
|
||||
}
|
||||
|
||||
val variable = variableWithConstraints.typeVariable
|
||||
c.fixVariable(variable, resultType, ConeFixVariableConstraintPosition(variable), resultTypeForOnlyInputTypes)
|
||||
c.fixVariable(variable, resultType, ConeFixVariableConstraintPosition(variable))
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+3
-3
@@ -401,7 +401,7 @@ object NewCommonSuperTypeCalculator {
|
||||
return false // arguments for contravariant parameters are intersected, recursion should not be possible
|
||||
|
||||
val originalTypesSet = originalTypesForCst.toSet()
|
||||
val typeArgumentsTypeSet = typeArgumentsForSuperConstructorParameter.map { it.getType().lowerBoundIfFlexible() }.toSet()
|
||||
val typeArgumentsTypeSet = typeArgumentsForSuperConstructorParameter.map { it.getType().lowerBoundIfFlexible().originalIfDefinitelyNotNullable() }.toSet()
|
||||
|
||||
if (originalTypesSet.size != typeArgumentsTypeSet.size)
|
||||
return false
|
||||
@@ -414,7 +414,7 @@ object NewCommonSuperTypeCalculator {
|
||||
|
||||
var starProjectionFound = false
|
||||
for (supertype in supertypesIfCapturedStarProjection(argumentType).orEmpty()) {
|
||||
if (supertype.lowerBoundIfFlexible().typeConstructor() !in originalTypeConstructorSet)
|
||||
if (supertype.lowerBoundIfFlexible().originalIfDefinitelyNotNullable().typeConstructor() !in originalTypeConstructorSet)
|
||||
return false
|
||||
else starProjectionFound = true
|
||||
}
|
||||
@@ -429,7 +429,7 @@ object NewCommonSuperTypeCalculator {
|
||||
for (type in types) {
|
||||
if (isCapturedStarProjection(type)) {
|
||||
for (supertype in supertypesIfCapturedStarProjection(type).orEmpty()) {
|
||||
yield(supertype.lowerBoundIfFlexible().typeConstructor())
|
||||
yield(supertype.lowerBoundIfFlexible().originalIfDefinitelyNotNullable().typeConstructor())
|
||||
}
|
||||
} else {
|
||||
yield(type.typeConstructor())
|
||||
|
||||
-1
@@ -36,7 +36,6 @@ abstract class ConstraintSystemCompletionContext : VariableFixationFinder.Contex
|
||||
variable: TypeVariableMarker,
|
||||
resultType: KotlinTypeMarker,
|
||||
position: FixVariableConstraintPosition<*>,
|
||||
resultTypeForOnlyInputTypes: KotlinTypeMarker = resultType
|
||||
)
|
||||
|
||||
abstract fun couldBeResolvedWithUnrestrictedBuilderInference(): Boolean
|
||||
|
||||
+8
-15
@@ -59,8 +59,8 @@ class ResultTypeResolver(
|
||||
return if (direction == ResolveDirection.TO_SUBTYPE) nothingType() else nullableAnyType()
|
||||
}
|
||||
|
||||
fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection, isForOnlyInputTypes: Boolean = false): KotlinTypeMarker {
|
||||
findResultTypeOrNull(c, variableWithConstraints, direction, isForOnlyInputTypes)?.let { return it }
|
||||
fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): KotlinTypeMarker {
|
||||
findResultTypeOrNull(c, variableWithConstraints, direction)?.let { return it }
|
||||
|
||||
// no proper constraints
|
||||
return c.getDefaultType(direction, variableWithConstraints.constraints, variableWithConstraints.typeVariable)
|
||||
@@ -70,7 +70,6 @@ class ResultTypeResolver(
|
||||
c: Context,
|
||||
variableWithConstraints: VariableWithConstraints,
|
||||
direction: ResolveDirection,
|
||||
isForOnlyInputTypes: Boolean = false,
|
||||
): KotlinTypeMarker? {
|
||||
val resultTypeFromEqualConstraint = findResultIfThereIsEqualsConstraint(c, variableWithConstraints)
|
||||
if (resultTypeFromEqualConstraint != null) {
|
||||
@@ -85,7 +84,7 @@ class ResultTypeResolver(
|
||||
}
|
||||
}
|
||||
|
||||
val subType = c.findSubType(variableWithConstraints, isForOnlyInputTypes)
|
||||
val subType = c.findSubType(variableWithConstraints)
|
||||
// Super type should be the most flexible, sub type should be the least one
|
||||
val superType = c.findSuperType(variableWithConstraints).makeFlexibleIfNecessary(c, variableWithConstraints.constraints)
|
||||
|
||||
@@ -210,11 +209,12 @@ class ResultTypeResolver(
|
||||
return constraints.singleOrNull { it.kind.isLower() }?.isNullabilityConstraint ?: false
|
||||
}
|
||||
|
||||
private fun Context.findSubType(variableWithConstraints: VariableWithConstraints, isForOnlyInputTypes: Boolean): KotlinTypeMarker? {
|
||||
val lowerConstraintTypes = prepareLowerConstraints(variableWithConstraints.constraints, isForOnlyInputTypes)
|
||||
private fun Context.findSubType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? {
|
||||
val lowerConstraintTypes = prepareLowerConstraints(variableWithConstraints.constraints)
|
||||
|
||||
if (lowerConstraintTypes.isNotEmpty()) {
|
||||
val types = sinkIntegerLiteralTypes(lowerConstraintTypes)
|
||||
// TODO Improve handling of flexible types with recursive captured type arguments to not produce giant multi-level-deep types KT-65704
|
||||
var commonSuperType = computeCommonSuperType(types)
|
||||
|
||||
if (commonSuperType.contains { it.asSimpleType()?.isStubTypeForVariableInSubtyping() == true }) {
|
||||
@@ -268,7 +268,7 @@ class ResultTypeResolver(
|
||||
private fun Context.computeCommonSuperType(types: List<KotlinTypeMarker>): KotlinTypeMarker =
|
||||
with(NewCommonSuperTypeCalculator) { commonSuperType(types) }
|
||||
|
||||
private fun Context.prepareLowerConstraints(constraints: List<Constraint>, isForOnlyInputTypes: Boolean): List<KotlinTypeMarker> {
|
||||
private fun Context.prepareLowerConstraints(constraints: List<Constraint>): List<KotlinTypeMarker> {
|
||||
var atLeastOneProper = false
|
||||
var atLeastOneNonProper = false
|
||||
|
||||
@@ -277,14 +277,7 @@ class ResultTypeResolver(
|
||||
for (constraint in constraints) {
|
||||
if (constraint.kind != ConstraintKind.LOWER) continue
|
||||
|
||||
var type = constraint.type
|
||||
|
||||
// The call to commonSuperTypes will replace arguments that have recursive supertypes with star projections,
|
||||
// which will lead to a different resulting type than approximating it first.
|
||||
// This breaks the @OnlyInputTypes check for captured types with recursive super types.
|
||||
if (isForOnlyInputTypes && isK2 && hasRecursiveTypeParametersWithGivenSelfType(type.typeConstructor())) {
|
||||
type = typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.InternalTypesApproximation) ?: type
|
||||
}
|
||||
val type = constraint.type
|
||||
|
||||
lowerConstraintTypes.add(type)
|
||||
|
||||
|
||||
+1
-2
@@ -567,7 +567,6 @@ class NewConstraintSystemImpl(
|
||||
variable: TypeVariableMarker,
|
||||
resultType: KotlinTypeMarker,
|
||||
position: FixVariableConstraintPosition<*>,
|
||||
resultTypeForOnlyInputTypes: KotlinTypeMarker,
|
||||
) = with(utilContext) {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
|
||||
@@ -594,7 +593,7 @@ class NewConstraintSystemImpl(
|
||||
// Substitute freshly fixed type variable into missed constraints
|
||||
substituteMissedConstraints()
|
||||
|
||||
postponeOnlyInputTypesCheck(variableWithConstraints, resultTypeForOnlyInputTypes)
|
||||
postponeOnlyInputTypesCheck(variableWithConstraints, resultType)
|
||||
|
||||
doPostponedComputationsIfAllVariablesAreFixed()
|
||||
}
|
||||
|
||||
+4
-4
@@ -288,7 +288,7 @@ abstract class AbstractTypeApproximator(
|
||||
toSuper: Boolean,
|
||||
depth: Int
|
||||
): KotlinTypeMarker? {
|
||||
fun KotlinTypeMarker.replaceRecursionWithStarProjection(capturedType: CapturedTypeMarker, toSuper: Boolean): KotlinTypeMarker {
|
||||
fun KotlinTypeMarker.replaceRecursionWithStarProjection(capturedType: CapturedTypeMarker): KotlinTypeMarker {
|
||||
// This replacement is important for resolving the code like below in K2.
|
||||
// fun bar(y: FieldOrRef<*>) = y.field
|
||||
// interface FieldOrRef<FF : AbstractField<FF>> { val field: FF }
|
||||
@@ -311,7 +311,7 @@ abstract class AbstractTypeApproximator(
|
||||
return getType().lowerBoundIfFlexible().originalIfDefinitelyNotNullable()
|
||||
}
|
||||
|
||||
return if (isK2 && toSuper && getArguments().any { it.unwrapForComparison() == capturedType }) {
|
||||
return if (isK2 && getArguments().any { it.unwrapForComparison() == capturedType }) {
|
||||
replaceArguments {
|
||||
when {
|
||||
it.unwrapForComparison() != capturedType -> it
|
||||
@@ -326,7 +326,7 @@ abstract class AbstractTypeApproximator(
|
||||
val supertypes = capturedType.typeConstructor().supertypes()
|
||||
val baseSuperType = when (supertypes.size) {
|
||||
0 -> nullableAnyType() // Let C = in Int, then superType for C and C? is Any?
|
||||
1 -> supertypes.single().replaceRecursionWithStarProjection(capturedType, toSuper)
|
||||
1 -> supertypes.single().replaceRecursionWithStarProjection(capturedType)
|
||||
|
||||
// Consider the following example:
|
||||
// A.getA()::class.java, where `getA()` returns some class from Java
|
||||
@@ -347,7 +347,7 @@ abstract class AbstractTypeApproximator(
|
||||
|
||||
else -> {
|
||||
val projection = capturedType.typeConstructorProjection()
|
||||
if (projection.isStarProjection()) intersectTypes(supertypes.map { it.replaceRecursionWithStarProjection(capturedType, toSuper) })
|
||||
if (projection.isStarProjection()) intersectTypes(supertypes.map { it.replaceRecursionWithStarProjection(capturedType) })
|
||||
else projection.getType()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user