Prevent leaking of type parameter erasion results cache into static scope

This commit is contained in:
Victor Petukhov
2021-07-26 14:08:21 +03:00
committed by teamcityserver
parent 6706ee87ad
commit 20d50cfee7
20 changed files with 170 additions and 36 deletions
@@ -43,7 +43,7 @@ class ErasedOverridabilityCondition : ExternalOverridabilityCondition {
if (signatureTypes.any { it.arguments.isNotEmpty() && it.unwrap() !is RawTypeImpl }) return Result.UNKNOWN
var erasedSuper = superDescriptor.substitute(RawSubstitution.buildSubstitutor()) ?: return Result.UNKNOWN
var erasedSuper = superDescriptor.substitute(RawSubstitution().buildSubstitutor()) ?: return Result.UNKNOWN
if (erasedSuper is SimpleFunctionDescriptor && erasedSuper.typeParameters.isNotEmpty()) {
// Only simple functions are supported now for erased overrides
@@ -41,7 +41,8 @@ class JavaTypeResolver(
private val c: LazyJavaResolverContext,
private val typeParameterResolver: TypeParameterResolver
) {
val typeParameterUpperBoundEraser = TypeParameterUpperBoundEraser()
private val typeParameterUpperBoundEraser = TypeParameterUpperBoundEraser()
private val rawSubstitution = RawSubstitution(typeParameterUpperBoundEraser)
fun transformJavaType(javaType: JavaType?, attr: JavaTypeAttributes): KotlinType {
return when (javaType) {
@@ -237,7 +238,7 @@ class JavaTypeResolver(
)
}
RawSubstitution.computeProjection(
rawSubstitution.computeProjection(
parameter,
// if erasure happens due to invalid arguments number, use star projections instead
if (isRaw) attr else attr.withFlexibility(INFLEXIBLE),
@@ -51,7 +51,7 @@ class RawTypeImpl private constructor(lowerBound: SimpleType, upperBound: Simple
get() {
val classDescriptor = constructor.declarationDescriptor as? ClassDescriptor
?: error("Incorrect classifier: ${constructor.declarationDescriptor}")
return classDescriptor.getMemberScope(RawSubstitution)
return classDescriptor.getMemberScope(RawSubstitution())
}
override fun replaceAnnotations(newAnnotations: Annotations) =
@@ -101,14 +101,11 @@ class RawTypeImpl private constructor(lowerBound: SimpleType, upperBound: Simple
}
}
internal object RawSubstitution : TypeSubstitution() {
internal class RawSubstitution(typeParameterUpperBoundEraser: TypeParameterUpperBoundEraser? = null) : TypeSubstitution() {
private val typeParameterUpperBoundEraser = typeParameterUpperBoundEraser ?: TypeParameterUpperBoundEraser(this)
override fun get(key: KotlinType) = TypeProjectionImpl(eraseType(key))
private val typeParameterUpperBoundEraser = TypeParameterUpperBoundEraser()
private val lowerTypeAttr = TypeUsage.COMMON.toAttributes().withFlexibility(JavaTypeFlexibility.FLEXIBLE_LOWER_BOUND)
private val upperTypeAttr = TypeUsage.COMMON.toAttributes().withFlexibility(JavaTypeFlexibility.FLEXIBLE_UPPER_BOUND)
private fun eraseType(type: KotlinType, attr: JavaTypeAttributes = JavaTypeAttributes(TypeUsage.COMMON)): KotlinType {
return when (val declaration = type.constructor.declarationDescriptor) {
is TypeParameterDescriptor ->
@@ -153,7 +150,7 @@ internal object RawSubstitution : TypeSubstitution() {
if (type.isError) return ErrorUtils.createErrorType("Raw error type: ${type.constructor}") to false
val memberScope = declaration.getMemberScope(RawSubstitution)
val memberScope = declaration.getMemberScope(this)
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
type.annotations, declaration.typeConstructor,
declaration.typeConstructor.parameters.map { parameter ->
@@ -199,4 +196,9 @@ internal object RawSubstitution : TypeSubstitution() {
}
override fun isEmpty() = false
companion object {
private val lowerTypeAttr = TypeUsage.COMMON.toAttributes().withFlexibility(JavaTypeFlexibility.FLEXIBLE_LOWER_BOUND)
private val upperTypeAttr = TypeUsage.COMMON.toAttributes().withFlexibility(JavaTypeFlexibility.FLEXIBLE_UPPER_BOUND)
}
}
@@ -13,11 +13,12 @@ import org.jetbrains.kotlin.types.typeUtil.extractTypeParametersFromUpperBounds
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjectionOrMapped
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
class TypeParameterUpperBoundEraser {
internal class TypeParameterUpperBoundEraser(rawSubstitution: RawSubstitution? = null) {
private val storage = LockBasedStorageManager("Type parameter upper bound erasion results")
private val erroneousErasedBound by lazy {
ErrorUtils.createErrorType("Can't compute erased upper bound of type parameter `$this`")
}
private val rawSubstitution = rawSubstitution ?: RawSubstitution(this)
private data class DataToEraseUpperBound(
val typeParameter: TypeParameterDescriptor,
@@ -83,7 +84,7 @@ class TypeParameterUpperBoundEraser {
*/
val erasedUpperBounds = typeParameter.defaultType.extractTypeParametersFromUpperBounds(visitedTypeParameters).associate {
val boundProjection = if (visitedTypeParameters == null || it !in visitedTypeParameters) {
RawSubstitution.computeProjection(
rawSubstitution.computeProjection(
it,
// if erasure happens due to invalid arguments number, use star projections instead
if (isRaw) typeAttr else typeAttr.withFlexibility(JavaTypeFlexibility.INFLEXIBLE),