[NI] Run checks for captured types only once in NewTypeSubstitutor
Sometimes we can get Enum<Captured(*)> type here, so, supertype for Captured(*) is Enum<Capture(*)> and we go into SO.
This commit is contained in:
committed by
Mikhail Zarechenskiy
parent
d58c6e245f
commit
91241a34d1
+15
-11
@@ -30,15 +30,17 @@ interface NewTypeSubstitutor {
|
|||||||
fun safeSubstitute(type: UnwrappedType): UnwrappedType = substitute(type) ?: type
|
fun safeSubstitute(type: UnwrappedType): UnwrappedType = substitute(type) ?: type
|
||||||
|
|
||||||
// null means that this type isn't changed
|
// null means that this type isn't changed
|
||||||
fun substitute(type: UnwrappedType): UnwrappedType? =
|
fun substitute(type: UnwrappedType): UnwrappedType? = substitute(type, runCapturedChecks = true)
|
||||||
|
|
||||||
|
private fun substitute(type: UnwrappedType, runCapturedChecks: Boolean): UnwrappedType? =
|
||||||
when (type) {
|
when (type) {
|
||||||
is SimpleType -> substitute(type)
|
is SimpleType -> substitute(type, runCapturedChecks)
|
||||||
is FlexibleType -> if (type is DynamicType || type is RawType) {
|
is FlexibleType -> if (type is DynamicType || type is RawType) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val lowerBound = substitute(type.lowerBound)
|
val lowerBound = substitute(type.lowerBound, runCapturedChecks)
|
||||||
val upperBound = substitute(type.upperBound)
|
val upperBound = substitute(type.upperBound, runCapturedChecks)
|
||||||
if (lowerBound == null && upperBound == null) {
|
if (lowerBound == null && upperBound == null) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@@ -49,27 +51,29 @@ interface NewTypeSubstitutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun substitute(type: SimpleType): UnwrappedType? {
|
private fun substitute(type: SimpleType, runCapturedChecks: Boolean): UnwrappedType? {
|
||||||
if (type.isError) return null
|
if (type.isError) return null
|
||||||
|
|
||||||
if (type.arguments.isNotEmpty()) {
|
if (type.arguments.isNotEmpty()) {
|
||||||
return substituteParametrizedType(type)
|
return substituteParametrizedType(type, runCapturedChecks)
|
||||||
}
|
}
|
||||||
|
|
||||||
val typeConstructor = type.constructor
|
val typeConstructor = type.constructor
|
||||||
|
|
||||||
if (typeConstructor is NewCapturedTypeConstructor) {
|
if (typeConstructor is NewCapturedTypeConstructor) {
|
||||||
|
if (!runCapturedChecks) return null
|
||||||
|
|
||||||
assert(type is NewCapturedType) { // KT-16147
|
assert(type is NewCapturedType) { // KT-16147
|
||||||
"Type is inconsistent -- somewhere we create type with typeConstructor = $typeConstructor " +
|
"Type is inconsistent -- somewhere we create type with typeConstructor = $typeConstructor " +
|
||||||
"and class: ${type::class.java.canonicalName}. type.toString() = $type"
|
"and class: ${type::class.java.canonicalName}. type.toString() = $type"
|
||||||
}
|
}
|
||||||
val lower = (type as NewCapturedType).lowerType?.let { substitute(it) }
|
val lower = (type as NewCapturedType).lowerType?.let { substitute(it, runCapturedChecks = false) }
|
||||||
if (lower != null) throw IllegalStateException("Illegal type substitutor: $this, " +
|
if (lower != null) throw IllegalStateException("Illegal type substitutor: $this, " +
|
||||||
"because for captured type '$type' lower type approximation should be null, but it is: '$lower'," +
|
"because for captured type '$type' lower type approximation should be null, but it is: '$lower'," +
|
||||||
"original lower type: '${type.lowerType}")
|
"original lower type: '${type.lowerType}")
|
||||||
|
|
||||||
type.constructor.supertypes.forEach { supertype ->
|
type.constructor.supertypes.forEach { supertype ->
|
||||||
substitute(supertype)?.let {
|
substitute(supertype, runCapturedChecks = false)?.let {
|
||||||
throw IllegalStateException("Illegal type substitutor: $this, " +
|
throw IllegalStateException("Illegal type substitutor: $this, " +
|
||||||
"because for captured type '$type' supertype approximation should be null, but it is: '$supertype'," +
|
"because for captured type '$type' supertype approximation should be null, but it is: '$supertype'," +
|
||||||
"original supertype: '$supertype'")
|
"original supertype: '$supertype'")
|
||||||
@@ -82,7 +86,7 @@ interface NewTypeSubstitutor {
|
|||||||
if (typeConstructor is IntersectionTypeConstructor) {
|
if (typeConstructor is IntersectionTypeConstructor) {
|
||||||
var thereIsChanges = false
|
var thereIsChanges = false
|
||||||
val newTypes = typeConstructor.supertypes.map {
|
val newTypes = typeConstructor.supertypes.map {
|
||||||
substitute(it.unwrap())?.apply { thereIsChanges = true } ?: it.unwrap()
|
substitute(it.unwrap(), runCapturedChecks)?.apply { thereIsChanges = true } ?: it.unwrap()
|
||||||
}
|
}
|
||||||
if (!thereIsChanges) return null
|
if (!thereIsChanges) return null
|
||||||
return intersectTypes(newTypes).let { if (type.isMarkedNullable) it.makeNullableAsSpecified(true) else it }
|
return intersectTypes(newTypes).let { if (type.isMarkedNullable) it.makeNullableAsSpecified(true) else it }
|
||||||
@@ -94,7 +98,7 @@ interface NewTypeSubstitutor {
|
|||||||
return if (type.isMarkedNullable) replacement.makeNullableAsSpecified(true) else replacement
|
return if (type.isMarkedNullable) replacement.makeNullableAsSpecified(true) else replacement
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun substituteParametrizedType(type: SimpleType): UnwrappedType? {
|
private fun substituteParametrizedType(type: SimpleType, runCapturedChecks: Boolean): UnwrappedType? {
|
||||||
val parameters = type.constructor.parameters
|
val parameters = type.constructor.parameters
|
||||||
val arguments = type.arguments
|
val arguments = type.arguments
|
||||||
if (parameters.size != arguments.size) {
|
if (parameters.size != arguments.size) {
|
||||||
@@ -107,7 +111,7 @@ interface NewTypeSubstitutor {
|
|||||||
val argument = arguments[index]
|
val argument = arguments[index]
|
||||||
|
|
||||||
if (argument.isStarProjection) continue
|
if (argument.isStarProjection) continue
|
||||||
val substitutedArgumentType = substitute(argument.type.unwrap()) ?: continue
|
val substitutedArgumentType = substitute(argument.type.unwrap(), runCapturedChecks) ?: continue
|
||||||
|
|
||||||
newArguments[index] = TypeProjectionImpl(argument.projectionKind, substitutedArgumentType)
|
newArguments[index] = TypeProjectionImpl(argument.projectionKind, substitutedArgumentType)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user