@@ -32,14 +32,17 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildClass
3232import org.jetbrains.kotlin.ir.builders.declarations.buildReceiverParameter
3333import org.jetbrains.kotlin.ir.declarations.IrClass
3434import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
35+ import org.jetbrains.kotlin.ir.declarations.IrFile
3536import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
3637import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
38+ import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
3739import org.jetbrains.kotlin.ir.expressions.IrExpression
3840import org.jetbrains.kotlin.ir.expressions.IrReturn
3941import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI
4042import org.jetbrains.kotlin.ir.types.IrType
4143import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
4244import org.jetbrains.kotlin.ir.util.addChild
45+ import org.jetbrains.kotlin.ir.util.deepCopyWithoutPatchingParents
4346import org.jetbrains.kotlin.ir.util.defaultType
4447import org.jetbrains.kotlin.ir.util.file
4548import org.jetbrains.kotlin.ir.util.statements
@@ -1872,6 +1875,54 @@ class ClassStabilityTransformTests(useFir: Boolean) : AbstractIrTransformTest(us
18721875 )
18731876 }
18741877
1878+ @Test
1879+ fun testStabilityCaching () {
1880+ val testFileSource = """
1881+ class A
1882+ class B(val a: A)
1883+ class C(val b: B)
1884+ class D(val c: C)
1885+ """ .trimIndent()
1886+
1887+ val files = listOf (SourceFile (" Test.kt" , testFileSource))
1888+ val irModule = compileToIr(files, additionalPaths)
1889+ val stabilityInferencer = StabilityInferencer (isTargetJvm = true , irModule.descriptor, setOf ())
1890+
1891+ val testIrFile = irModule.files.last()
1892+ val (aClass, bClass, cClass, dClass) = testIrFile.declarations.filterIsInstance<IrClass >()
1893+
1894+ // When a dependent in a different file requests the stability of a class defined in
1895+ // `testIrFile`, we expect the computed stability not to be cached. Note that
1896+ // `deepCopyWithoutPatchingParents` is used on the following line to obtain an object that
1897+ // is not referentially equal to `testIrFile`.
1898+ stabilityInferencer.stabilityOf(dClass.defaultType as IrType , testIrFile.deepCopyWithoutPatchingParents())
1899+ assertEquals(0 , stabilityInferencer.cache.size)
1900+
1901+ // When `StabilityInferencer`'s cache is initially empty and `D`'s stability is requested,
1902+ // we expect the stability values of `A`, `B`, `C`, and `D` to each be computed and added to
1903+ // the cache.
1904+ val stabilityOfD = stabilityInferencer.stabilityOf(dClass.defaultType as IrType , testIrFile)
1905+ assertEquals(4 , stabilityInferencer.cache.size)
1906+
1907+ // When the stability of a class is cached, we expect it to be returned from the cache, and
1908+ // we expect no cache modifications to happen.
1909+
1910+ assertEquals(
1911+ stabilityOfD,
1912+ stabilityInferencer.stabilityOf(dClass.defaultType as IrType , testIrFile)
1913+ )
1914+ assertEquals(4 , stabilityInferencer.cache.size)
1915+
1916+ stabilityInferencer.stabilityOf(cClass.defaultType as IrType , testIrFile)
1917+ assertEquals(4 , stabilityInferencer.cache.size)
1918+
1919+ stabilityInferencer.stabilityOf(bClass.defaultType as IrType , testIrFile)
1920+ assertEquals(4 , stabilityInferencer.cache.size)
1921+
1922+ stabilityInferencer.stabilityOf(aClass.defaultType as IrType , testIrFile)
1923+ assertEquals(4 , stabilityInferencer.cache.size)
1924+ }
1925+
18751926 private fun assertStability (
18761927 externalSrc : String ,
18771928 localSrc : String ,
0 commit comments