JVM_IR merge annotations when substituting types

Otherwise special annotations such as @EnhancedNullability are lost,
which affects JVM signatures.

KT-42330
This commit is contained in:
Dmitry Petrov
2020-09-30 13:14:12 +03:00
parent 4b152a635e
commit af86c52101
8 changed files with 127 additions and 10 deletions
@@ -82,8 +82,16 @@ fun IrType.substitute(params: List<IrTypeParameter>, arguments: List<IrType>): I
fun IrType.substitute(substitutionMap: Map<IrTypeParameterSymbol, IrType>): IrType {
if (this !is IrSimpleType) return this
substitutionMap[classifier]?.let {
return it.withHasQuestionMark(hasQuestionMark || it is IrSimpleType && it.hasQuestionMark)
val newAnnotations = annotations.map { it.deepCopyWithSymbols() }
substitutionMap[classifier]?.let { substitutedType ->
// Add nullability and annotations from original type
return substitutedType
.withHasQuestionMark(
hasQuestionMark ||
substitutedType is IrSimpleType && substitutedType.hasQuestionMark
)
.addAnnotations(newAnnotations)
}
val newArguments = arguments.map {
@@ -94,7 +102,6 @@ fun IrType.substitute(substitutionMap: Map<IrTypeParameterSymbol, IrType>): IrTy
}
}
val newAnnotations = annotations.map { it.deepCopyWithSymbols() }
return IrSimpleTypeImpl(
classifier,
hasQuestionMark,
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
@@ -35,6 +36,20 @@ fun IrType.withHasQuestionMark(newHasQuestionMark: Boolean): IrType =
else -> this
}
fun IrType.addAnnotations(newAnnotations: List<IrConstructorCall>): IrType =
if (newAnnotations.isEmpty())
this
else when (this) {
is IrSimpleType ->
toBuilder().apply {
annotations = annotations + newAnnotations
}.buildSimpleType()
is IrDynamicType ->
IrDynamicTypeImpl(null, annotations + newAnnotations, Variance.INVARIANT)
else ->
this
}
val IrType.classifierOrFail: IrClassifierSymbol
get() = cast<IrSimpleType>().classifier
@@ -156,11 +156,11 @@ public final class DIntMap {
private synthetic final field $$delegate_0: java.util.Map
public method <init>(@org.jetbrains.annotations.NotNull p0: java.util.Map): void
public method clear(): void
public method compute(p0: int, p1: java.util.function.BiFunction): java.lang.Double
public method compute(p0: java.lang.Integer, p1: java.util.function.BiFunction): java.lang.Double
public synthetic bridge method compute(p0: java.lang.Object, p1: java.util.function.BiFunction): java.lang.Object
public method computeIfAbsent(p0: int, p1: java.util.function.Function): java.lang.Double
public method computeIfAbsent(p0: java.lang.Integer, p1: java.util.function.Function): java.lang.Double
public synthetic bridge method computeIfAbsent(p0: java.lang.Object, p1: java.util.function.Function): java.lang.Object
public method computeIfPresent(p0: int, p1: java.util.function.BiFunction): java.lang.Double
public method computeIfPresent(p0: java.lang.Integer, p1: java.util.function.BiFunction): java.lang.Double
public synthetic bridge method computeIfPresent(p0: java.lang.Object, p1: java.util.function.BiFunction): java.lang.Object
public method containsKey(p0: int): boolean
public bridge final method containsKey(p0: java.lang.Object): boolean
@@ -176,18 +176,18 @@ public final class DIntMap {
public @org.jetbrains.annotations.NotNull method getValues(): java.util.Collection
public method isEmpty(): boolean
public bridge final method keySet(): java.util.Set
public method merge(p0: int, p1: double, p2: java.util.function.BiFunction): java.lang.Double
public method merge(p0: java.lang.Integer, p1: java.lang.Double, p2: java.util.function.BiFunction): java.lang.Double
public synthetic bridge method merge(p0: java.lang.Object, p1: java.lang.Object, p2: java.util.function.BiFunction): java.lang.Object
public method put(p0: int, p1: double): java.lang.Double
public synthetic bridge method put(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
public method putAll(p0: java.util.Map): void
public method putIfAbsent(p0: int, p1: double): java.lang.Double
public method putIfAbsent(p0: java.lang.Integer, p1: java.lang.Double): java.lang.Double
public synthetic bridge method putIfAbsent(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
public method remove(p0: java.lang.Object): java.lang.Double
public synthetic bridge method remove(p0: java.lang.Object): java.lang.Object
public method remove(p0: java.lang.Object, p1: java.lang.Object): boolean
public method replace(p0: int, p1: double): java.lang.Double
public method replace(p0: int, p1: double, p2: double): boolean
public method replace(p0: java.lang.Integer, p1: java.lang.Double): java.lang.Double
public method replace(p0: java.lang.Integer, p1: java.lang.Double, p2: java.lang.Double): boolean
public synthetic bridge method replace(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
public synthetic bridge method replace(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): boolean
public method replaceAll(p0: java.util.function.BiFunction): void
@@ -0,0 +1,3 @@
// FULL_JDK
abstract class IntIntMap : Map<Int, Int>
@@ -0,0 +1,40 @@
@kotlin.Metadata
public abstract class IntIntMap {
// source: 'mapOfPrimitivesFullJdk.kt'
public method <init>(): void
public method clear(): void
public method compute(p0: java.lang.Integer, p1: java.util.function.BiFunction): java.lang.Integer
public synthetic method compute(p0: java.lang.Object, p1: java.util.function.BiFunction): java.lang.Object
public method computeIfAbsent(p0: java.lang.Integer, p1: java.util.function.Function): java.lang.Integer
public synthetic method computeIfAbsent(p0: java.lang.Object, p1: java.util.function.Function): java.lang.Object
public method computeIfPresent(p0: java.lang.Integer, p1: java.util.function.BiFunction): java.lang.Integer
public synthetic method computeIfPresent(p0: java.lang.Object, p1: java.util.function.BiFunction): java.lang.Object
public abstract method containsKey(p0: int): boolean
public bridge final method containsKey(p0: java.lang.Object): boolean
public abstract method containsValue(p0: int): boolean
public bridge final method containsValue(p0: java.lang.Object): boolean
public bridge final method entrySet(): java.util.Set
public abstract method get(p0: int): java.lang.Integer
public bridge final method get(p0: java.lang.Object): java.lang.Object
public abstract method getEntries(): java.util.Set
public abstract method getKeys(): java.util.Set
public abstract method getSize(): int
public abstract method getValues(): java.util.Collection
public bridge final method keySet(): java.util.Set
public method merge(p0: java.lang.Integer, p1: java.lang.Integer, p2: java.util.function.BiFunction): java.lang.Integer
public synthetic method merge(p0: java.lang.Object, p1: java.lang.Object, p2: java.util.function.BiFunction): java.lang.Object
public method put(p0: int, p1: int): java.lang.Integer
public synthetic method put(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
public method putAll(p0: java.util.Map): void
public method putIfAbsent(p0: java.lang.Integer, p1: java.lang.Integer): java.lang.Integer
public synthetic method putIfAbsent(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
public method remove(p0: java.lang.Object): java.lang.Object
public method remove(p0: java.lang.Object, p1: java.lang.Object): boolean
public method replace(p0: java.lang.Integer, p1: java.lang.Integer): java.lang.Integer
public method replace(p0: java.lang.Integer, p1: java.lang.Integer, p2: java.lang.Integer): boolean
public synthetic method replace(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
public synthetic method replace(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): boolean
public method replaceAll(p0: java.util.function.BiFunction): void
public bridge final method size(): int
public bridge final method values(): java.util.Collection
}
@@ -0,0 +1,42 @@
@kotlin.Metadata
public abstract class IntIntMap {
// source: 'mapOfPrimitivesFullJdk.kt'
public method <init>(): void
public method clear(): void
public method compute(p0: java.lang.Integer, p1: java.util.function.BiFunction): java.lang.Integer
public synthetic bridge method compute(p0: java.lang.Object, p1: java.util.function.BiFunction): java.lang.Object
public method computeIfAbsent(p0: java.lang.Integer, p1: java.util.function.Function): java.lang.Integer
public synthetic bridge method computeIfAbsent(p0: java.lang.Object, p1: java.util.function.Function): java.lang.Object
public method computeIfPresent(p0: java.lang.Integer, p1: java.util.function.BiFunction): java.lang.Integer
public synthetic bridge method computeIfPresent(p0: java.lang.Object, p1: java.util.function.BiFunction): java.lang.Object
public abstract method containsKey(p0: int): boolean
public bridge final method containsKey(p0: java.lang.Object): boolean
public abstract method containsValue(p0: int): boolean
public bridge final method containsValue(p0: java.lang.Object): boolean
public bridge final method entrySet(): java.util.Set
public abstract method get(p0: int): java.lang.Integer
public bridge final method get(p0: java.lang.Object): java.lang.Integer
public synthetic bridge method get(p0: java.lang.Object): java.lang.Object
public abstract method getEntries(): java.util.Set
public abstract method getKeys(): java.util.Set
public abstract method getSize(): int
public abstract method getValues(): java.util.Collection
public bridge final method keySet(): java.util.Set
public method merge(p0: java.lang.Integer, p1: java.lang.Integer, p2: java.util.function.BiFunction): java.lang.Integer
public synthetic bridge method merge(p0: java.lang.Object, p1: java.lang.Object, p2: java.util.function.BiFunction): java.lang.Object
public method put(p0: int, p1: int): java.lang.Integer
public synthetic bridge method put(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
public method putAll(p0: java.util.Map): void
public method putIfAbsent(p0: java.lang.Integer, p1: java.lang.Integer): java.lang.Integer
public synthetic bridge method putIfAbsent(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
public method remove(p0: java.lang.Object): java.lang.Integer
public synthetic bridge method remove(p0: java.lang.Object): java.lang.Object
public method remove(p0: java.lang.Object, p1: java.lang.Object): boolean
public method replace(p0: java.lang.Integer, p1: java.lang.Integer): java.lang.Integer
public method replace(p0: java.lang.Integer, p1: java.lang.Integer, p2: java.lang.Integer): boolean
public synthetic bridge method replace(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
public synthetic bridge method replace(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): boolean
public method replaceAll(p0: java.util.function.BiFunction): void
public bridge final method size(): int
public bridge final method values(): java.util.Collection
}
@@ -284,6 +284,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/extendingAbstractCollection.kt");
}
@TestMetadata("mapOfPrimitivesFullJdk.kt")
public void testMapOfPrimitivesFullJdk() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/mapOfPrimitivesFullJdk.kt");
}
@TestMetadata("noStubsForCollection.kt")
public void testNoStubsForCollection() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/noStubsForCollection.kt");
@@ -284,6 +284,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/extendingAbstractCollection.kt");
}
@TestMetadata("mapOfPrimitivesFullJdk.kt")
public void testMapOfPrimitivesFullJdk() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/mapOfPrimitivesFullJdk.kt");
}
@TestMetadata("noStubsForCollection.kt")
public void testNoStubsForCollection() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/noStubsForCollection.kt");