Kotlin: fix type variable erasure inside default function values

Previously because extractClassInstance didn't use the declaration stack, we wouldn't notice that it was legal to refer to its type variable in the context of extracting a specialised method <-> method source-decl edge. This led to erasing the types of the source-decl, so that e.g. Map.put(...) would have signature (Object, Object) not (K, V)
as it should.
This commit is contained in:
Chris Smowton
2022-10-07 17:31:38 +01:00
parent 0d98eba604
commit bef4011947
5 changed files with 94 additions and 13 deletions

View File

@@ -254,9 +254,23 @@ open class KotlinFileExtractor(
}
}
fun extractClassInstance(classLabel: Label<out DbClassorinterface>, c: IrClass, argsIncludingOuterClasses: List<IrTypeArgument>?, shouldExtractOutline: Boolean, shouldExtractDetails: Boolean) {
DeclarationStackAdjuster(c).use {
if (shouldExtractOutline) {
extractClassWithoutMembers(c, argsIncludingOuterClasses)
}
if (shouldExtractDetails) {
val supertypeMode = if (argsIncludingOuterClasses == null) ExtractSupertypesMode.Raw else ExtractSupertypesMode.Specialised(argsIncludingOuterClasses)
extractClassSupertypes(c, classLabel, supertypeMode, true)
extractNonPrivateMemberPrototypes(c, argsIncludingOuterClasses, classLabel)
}
}
}
// `argsIncludingOuterClasses` can be null to describe a raw generic type.
// For non-generic types it will be zero-length list.
fun extractClassInstance(c: IrClass, argsIncludingOuterClasses: List<IrTypeArgument>?): Label<out DbClassorinterface> {
private fun extractClassWithoutMembers(c: IrClass, argsIncludingOuterClasses: List<IrTypeArgument>?): Label<out DbClassorinterface> {
with("class instance", c) {
if (argsIncludingOuterClasses?.isEmpty() == true) {
logger.error("Instance without type arguments: " + c.name.asString())

View File

@@ -411,16 +411,9 @@ open class KotlinUsesExtractor(
if (replacedArgsIncludingOuterClasses == null || replacedArgsIncludingOuterClasses.isNotEmpty()) {
// If this is a generic type instantiation or a raw type then it has no
// source entity, so we need to extract it here
val extractorWithCSource by lazy { this.withFileOfClass(replacedClass) }
if (!instanceSeenBefore) {
extractorWithCSource.extractClassInstance(replacedClass, replacedArgsIncludingOuterClasses)
}
if (inReceiverContext && tw.lm.genericSpecialisationsExtracted.add(classLabelResult.classLabel)) {
val supertypeMode = if (replacedArgsIncludingOuterClasses == null) ExtractSupertypesMode.Raw else ExtractSupertypesMode.Specialised(replacedArgsIncludingOuterClasses)
extractorWithCSource.extractClassSupertypes(replacedClass, classLabel, supertypeMode, true)
extractorWithCSource.extractNonPrivateMemberPrototypes(replacedClass, replacedArgsIncludingOuterClasses, classLabel)
val shouldExtractClassDetails = inReceiverContext && tw.lm.genericSpecialisationsExtracted.add(classLabelResult.classLabel)
if (!instanceSeenBefore || shouldExtractClassDetails) {
this.withFileOfClass(replacedClass).extractClassInstance(classLabel, replacedClass, replacedArgsIncludingOuterClasses, !instanceSeenBefore, shouldExtractClassDetails)
}
}