diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt index 9c477b013cc..4f4802c1214 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt @@ -30,15 +30,17 @@ interface NewTypeSubstitutor { fun safeSubstitute(type: UnwrappedType): UnwrappedType = substitute(type) ?: type // 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) { - is SimpleType -> substitute(type) + is SimpleType -> substitute(type, runCapturedChecks) is FlexibleType -> if (type is DynamicType || type is RawType) { null } else { - val lowerBound = substitute(type.lowerBound) - val upperBound = substitute(type.upperBound) + val lowerBound = substitute(type.lowerBound, runCapturedChecks) + val upperBound = substitute(type.upperBound, runCapturedChecks) if (lowerBound == null && upperBound == 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.arguments.isNotEmpty()) { - return substituteParametrizedType(type) + return substituteParametrizedType(type, runCapturedChecks) } val typeConstructor = type.constructor if (typeConstructor is NewCapturedTypeConstructor) { + if (!runCapturedChecks) return null + assert(type is NewCapturedType) { // KT-16147 "Type is inconsistent -- somewhere we create type with typeConstructor = $typeConstructor " + "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, " + "because for captured type '$type' lower type approximation should be null, but it is: '$lower'," + "original lower type: '${type.lowerType}") type.constructor.supertypes.forEach { supertype -> - substitute(supertype)?.let { + substitute(supertype, runCapturedChecks = false)?.let { throw IllegalStateException("Illegal type substitutor: $this, " + "because for captured type '$type' supertype approximation should be null, but it is: '$supertype'," + "original supertype: '$supertype'") @@ -82,7 +86,7 @@ interface NewTypeSubstitutor { if (typeConstructor is IntersectionTypeConstructor) { var thereIsChanges = false 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 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 } - private fun substituteParametrizedType(type: SimpleType): UnwrappedType? { + private fun substituteParametrizedType(type: SimpleType, runCapturedChecks: Boolean): UnwrappedType? { val parameters = type.constructor.parameters val arguments = type.arguments if (parameters.size != arguments.size) { @@ -107,7 +111,7 @@ interface NewTypeSubstitutor { val argument = arguments[index] 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) }