Compare commits

...

25 Commits

Author SHA1 Message Date
Simon Ogorodnik
667dc57a9f WIP: FIR concurrency 2019-07-30 20:08:31 +03:00
Simon Ogorodnik
d31d29bb61 [FIR] concurrency: non-fir changes 2019-07-30 20:08:12 +03:00
Simon Ogorodnik
80e0da1751 WIP: Concurrency 2019-07-25 04:45:29 +03:00
Simon Ogorodnik
ccceacd8cc WIP: Multithreaded compiler 2019-07-17 19:56:54 +03:00
Simon Ogorodnik
379f564a98 Fixup: t 2019-07-17 16:23:11 +03:00
Simon Ogorodnik
2a4dbb3a2a Remove FirTotalKotlinResolveInIdeTest as no more useful 2019-07-17 16:22:57 +03:00
Simon Ogorodnik
b81716a918 Candidate pool WIP 2019-07-16 21:35:50 +03:00
Simon Ogorodnik
f53001a6e1 WIP: Make call resolver resettable 2019-07-16 21:03:55 +03:00
Simon Ogorodnik
7372bb2e5f WIP: Do not recreate body resolve transformer for each file 2019-07-16 20:57:05 +03:00
Mikhail Glukhikh
abadfc50bd FIR resolve: attempt to skip non-valid groups 2019-07-16 13:45:38 +03:00
Mikhail Glukhikh
b99de17e40 ++ Make ... not resolved 2019-07-16 13:29:57 +03:00
Mikhail Glukhikh
f1374612ed FIR resolve: fix vararg parameter types 2019-07-15 18:44:30 +03:00
Mikhail Glukhikh
11df6091fa Make FirNamedReferenceWithCandidate not resolved, fix receiver completion
Counting it as resolved provokes a lot of difficult to discover errors
2019-07-15 18:21:45 +03:00
Mikhail Glukhikh
d11a4f96f2 FIR resolve: add early protection against cyclic property resolve 2019-07-15 17:47:38 +03:00
Mikhail Glukhikh
0b5a5c6d62 Extract part of utility FIR transformers into TransformUtils 2019-07-15 17:34:07 +03:00
Mikhail Glukhikh
45d3e6eb97 Minor (FIR resolve): replace session with fileSession 2019-07-15 17:32:37 +03:00
Mikhail Glukhikh
b16d53c855 Minor (FIR resolve): remove duplicated check 2019-07-15 17:32:37 +03:00
Mikhail Glukhikh
605cd838d5 FIR: set constructor parameter scope correctly for designated transformer 2019-07-15 17:32:36 +03:00
Mikhail Glukhikh
c2caccc175 FIR: preliminary implementation of delegate resolve #KT-32217 Fixed 2019-07-15 17:32:36 +03:00
Mikhail Glukhikh
6e63310b68 Measure unresolved function call & qualified access # in FIR bench 2019-07-15 17:32:36 +03:00
Simon Ogorodnik
67f2259e1a Use no-op substitutor instead of substitutor with empty map 2019-07-15 17:32:36 +03:00
Mikhail Glukhikh
f76356a4fe ++ FIR2IR test data 2019-07-15 17:32:35 +03:00
Simon Ogorodnik
de08dfbc7f FIR resolve: perform inference completion for property access 2019-07-15 17:32:35 +03:00
Mikhail Glukhikh
d5228afa94 ? FIR: questionable invoke refactoring -- breaks FIR2IR test(s) ? 2019-07-15 17:32:14 +03:00
Mikhail Glukhikh
75d315f5c9 Add test (works only partially) for "type from delegate" 2019-07-15 17:07:33 +03:00
89 changed files with 1906 additions and 787 deletions

View File

@@ -23,11 +23,12 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.*
import com.intellij.psi.impl.file.PsiPackageImpl
import com.intellij.psi.search.GlobalSearchScope
import gnu.trove.THashMap
import gnu.trove.THashSet
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex
import org.jetbrains.kotlin.fir.concurrent.ConcurrentHashMapNonRecursiveComputeCache
import org.jetbrains.kotlin.fir.concurrent.NonRecursiveCooperativeComputeCache
import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
@@ -41,6 +42,7 @@ import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
import org.jetbrains.kotlin.util.PerformanceCounter
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
import java.util.concurrent.locks.ReentrantLock
// TODO: do not inherit from CoreJavaFileManager to avoid accidental usage of its methods which do not use caches/indices
// Currently, the only relevant usage of this class as CoreJavaFileManager is at CoreJavaDirectoryService.getPackage,
@@ -50,7 +52,7 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
private lateinit var index: JvmDependenciesIndex
private lateinit var singleJavaFileRootsIndex: SingleJavaFileRootsIndex
private lateinit var packagePartProviders: List<JvmPackagePartProvider>
private val topLevelClassesCache: MutableMap<FqName, VirtualFile?> = THashMap()
private val topLevelClassesCache = ConcurrentHashMapNonRecursiveComputeCache<FqName, VirtualFile?>()
private val allScope = GlobalSearchScope.allScope(myPsiManager.project)
private var useFastClassFilesReading = false
@@ -72,25 +74,30 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
private fun findVirtualFileForTopLevelClass(classId: ClassId, searchScope: GlobalSearchScope): VirtualFile? {
val relativeClassName = classId.relativeClassName.asString()
return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) {
return topLevelClassesCache.lookup(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) {
index.findClass(classId) { dir, type ->
findVirtualFileGivenPackage(dir, relativeClassName, type)
} ?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
}?.takeIf { it in searchScope }
}
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
private val binaryCache: NonRecursiveCooperativeComputeCache<ClassId, JavaClass?> =
NonRecursiveCooperativeComputeCache()
private val signatureParsingComponent = BinaryClassSignatureParser()
fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? = findClass(JavaClassFinder.Request(classId), searchScope)
private val findVirtualFileLock = ReentrantLock()
private val binaryCacheLock = ReentrantLock()
override fun findClass(request: JavaClassFinder.Request, searchScope: GlobalSearchScope): JavaClass? {
val (classId, classFileContentFromRequest, outerClassFromRequest) = request
val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null
if (useFastClassFilesReading && virtualFile.extension == "class") {
// We return all class files' names in the directory in knownClassNamesInPackage method, so one may request an inner class
return binaryCache.getOrPut(classId) {
return binaryCache.lookup(classId) {
// Note that currently we implicitly suppose that searchScope for binary classes is constant and we do not use it
// as a key in cache
// This is a true assumption by now since there are two search scopes in compiler: one for sources and another one for binary
@@ -100,7 +107,7 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
classId.outerClassId?.let { outerClassId ->
val outerClass = outerClassFromRequest ?: findClass(outerClassId, searchScope)
return if (outerClass is BinaryJavaClass)
return@lookup if (outerClass is BinaryJavaClass)
outerClass.findInnerClass(classId.shortClassName, classFileContentFromRequest)
else
outerClass?.findInnerClass(classId.shortClassName)
@@ -108,7 +115,7 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
// Here, we assume the class is top-level
val classContent = classFileContentFromRequest ?: virtualFile.contentsToByteArray()
if (virtualFile.nameWithoutExtension.contains("$") && isNotTopLevelClass(classContent)) return@getOrPut null
if (virtualFile.nameWithoutExtension.contains("$") && isNotTopLevelClass(classContent)) return@lookup null
val resolver = ClassifierResolutionContext { findClass(it, allScope) }

View File

@@ -57,7 +57,7 @@ import org.jetbrains.kotlin.fir.java.FirLibrarySession
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.FirStagesTransformerFactory
import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.javac.JavacWrapper
@@ -327,7 +327,7 @@ object KotlinToJVMBytecodeCompiler {
}
val builder = RawFirBuilder(session, stubMode = false)
val resolveTransformer = FirTotalResolveTransformer()
val resolveTransformer = FirStagesTransformerFactory(session)
val firFiles = ktFiles.map {
val firFile = builder.buildFirFile(it)
(session.service<FirProvider>() as FirProviderImpl).recordFile(firFile)

View File

@@ -25,11 +25,38 @@ import gnu.trove.THashMap
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import java.util.*
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependenciesIndex {
override val indexedRoots: Sequence<JavaRoot>
get() = local.get().indexedRoots
override fun <T : Any> findClass(
classId: ClassId,
acceptedRootTypes: Set<JavaRoot.RootType>,
findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T?
): T? = local.get().findClass(classId, acceptedRootTypes, findClassGivenDirectory)
override fun traverseDirectoriesInPackage(
packageFqName: FqName,
acceptedRootTypes: Set<JavaRoot.RootType>,
continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean
) = local.get().traverseDirectoriesInPackage(packageFqName, acceptedRootTypes, continueSearch)
val local = object : ThreadLocal<JvmDependenciesIndexImplU>() {
override fun initialValue(): JvmDependenciesIndexImplU {
return JvmDependenciesIndexImplU(_roots)
}
}
}
// speeds up finding files/classes in classpath/java source roots
// NOT THREADSAFE, needs to be adapted/removed if we want compiler to be multithreaded
// the main idea of this class is for each package to store roots which contains it to avoid excessive file system traversal
class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependenciesIndex {
class JvmDependenciesIndexImplU(_roots: List<JavaRoot>) : JvmDependenciesIndex {
//these fields are computed based on _roots passed to constructor which are filled in later
private val roots: List<JavaRoot> by lazy { _roots.toList() }
@@ -76,6 +103,7 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependenciesIndex {
search(TraverseRequest(packageFqName, acceptedRootTypes)) { dir, rootType ->
if (continueSearch(dir, rootType)) null else Unit
}
Unit
}
// findClassGivenDirectory MUST check whether the class with this classId exists in given package
@@ -121,7 +149,7 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependenciesIndex {
// NOTE: indices manipulation instead of using caches.reversed() is here for performance reasons
for (cacheIndex in caches.lastIndex downTo 0) {
val cacheRootIndices = caches[cacheIndex].rootIndices
for (i in 0..cacheRootIndices.size() - 1) {
for (i in 0 until cacheRootIndices.size()) {
val rootIndex = cacheRootIndices[i]
if (rootIndex <= processedRootsUpTo) continue // roots with those indices have been processed by now
@@ -215,6 +243,7 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependenciesIndex {
return childDirectory
}
private fun cachesPath(path: List<String>): List<Cache> {
val caches = ArrayList<Cache>(path.size + 1)
caches.add(rootCache)

View File

@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.backend.Fir2IrConverter
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.FirStagesTransformerFactory
import org.jetbrains.kotlin.ir.AbstractIrTextTestCase
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import java.io.File
@@ -78,7 +78,7 @@ abstract class AbstractFir2IrTextTest : AbstractIrTextTestCase() {
val builder = RawFirBuilder(session, stubMode = false)
val resolveTransformer = FirTotalResolveTransformer()
val resolveTransformer = FirStagesTransformerFactory(session)
val firFiles = psiFiles.map {
val firFile = builder.buildFirFile(it)
(session.service<FirProvider>() as FirProviderImpl).recordFile(firFile)

View File

@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.java
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiPackage
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibility
@@ -19,6 +20,8 @@ import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope
import org.jetbrains.kotlin.fir.java.scopes.JavaClassUseSiteScope
import org.jetbrains.kotlin.fir.concurrent.ConcurrentHashMapNonRecursiveComputeCache
import org.jetbrains.kotlin.fir.concurrent.TransactionalCache
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirSuperTypeScope
@@ -38,6 +41,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
import org.jetbrains.kotlin.types.Variance.INVARIANT
import java.util.concurrent.locks.ReentrantLock
class JavaSymbolProvider(
val session: FirSession,
@@ -50,7 +54,12 @@ class JavaSymbolProvider(
private fun findClass(
classId: ClassId,
content: KotlinClassFinder.Result.ClassFileContent?
): JavaClass? = facade.findClass(JavaClassFinder.Request(classId, previouslyFoundClassFileContent = content?.content), searchScope)
): JavaClass? = //findClassLock.withLock {
facade.findClass(
JavaClassFinder.Request(classId, previouslyFoundClassFileContent = content?.content),
searchScope
)
//}
override fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List<FirCallableSymbol<*>> =
emptyList()
@@ -75,7 +84,7 @@ class JavaSymbolProvider(
scopeSession: ScopeSession
): JavaClassEnhancementScope {
return scopeSession.getOrBuild(symbol, JAVA_ENHANCEMENT) {
JavaClassEnhancementScope(useSiteSession, buildJavaUseSiteScope(symbol.fir, useSiteSession, scopeSession))
JavaClassEnhancementScope(useSiteSession, this, buildJavaUseSiteScope(symbol.fir, useSiteSession, scopeSession))
}
}
@@ -134,127 +143,151 @@ class JavaSymbolProvider(
override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? = getFirJavaClass(classId)
val findClassLock = globalFindClassLock
val nClassCache = TransactionalCache<ClassId, ClassCacheRec?>()
data class ClassCacheRec(val symbol: FirClassLikeSymbol<*>, var foundClass: JavaClass?)
fun getFirJavaClass(classId: ClassId, content: KotlinClassFinder.Result.ClassFileContent? = null): FirClassLikeSymbol<*>? {
if (!hasTopLevelClassOf(classId)) return null
return classCache.lookupCacheOrCalculateWithPostCompute(classId, {
val foundClass = findClass(classId, content)
if (foundClass == null || foundClass.annotations.any { it.classId?.asSingleFqName() == JvmAnnotationNames.METADATA_FQ_NAME }) {
null to null
} else {
FirClassSymbol(classId) to foundClass
}
}) { firSymbol, foundClass ->
foundClass?.let { javaClass ->
val javaTypeParameterStack = JavaTypeParameterStack()
val parentFqName = classId.relativeClassName.parent()
val isTopLevel = parentFqName.isRoot
if (!isTopLevel) {
val parentId = ClassId(classId.packageFqName, parentFqName, false)
val parentClassSymbol = getClassLikeSymbolByFqName(parentId) as? FirClassSymbol
val parentClass = parentClassSymbol?.fir
if (parentClass is FirJavaClass) {
javaTypeParameterStack.addStack(parentClass.javaTypeParameterStack)
}
return nClassCache.lookup(
classId,
{
val foundClass = findClass(classId, content)
if (foundClass == null || foundClass.annotations.any { it.classId?.asSingleFqName() == JvmAnnotationNames.METADATA_FQ_NAME }) {
null
} else {
ClassCacheRec(FirClassSymbol(classId), foundClass)
}
FirJavaClass(
session, firSymbol as FirClassSymbol, javaClass.name,
javaClass.visibility, javaClass.modality,
javaClass.classKind, isTopLevel = isTopLevel,
isStatic = javaClass.isStatic,
javaTypeParameterStack = javaTypeParameterStack
).apply {
this.typeParameters += foundClass.typeParameters.convertTypeParameters(javaTypeParameterStack)
addAnnotationsFrom(this@JavaSymbolProvider.session, javaClass, javaTypeParameterStack)
for (supertype in javaClass.supertypes) {
superTypeRefs += supertype.toFirResolvedTypeRef(this@JavaSymbolProvider.session, javaTypeParameterStack)
}
// TODO: may be we can process fields & methods later.
// However, they should be built up to override resolve stage
for (javaField in javaClass.fields) {
val fieldName = javaField.name
val fieldId = CallableId(classId.packageFqName, classId.relativeClassName, fieldName)
val fieldSymbol = FirFieldSymbol(fieldId)
val returnType = javaField.type
val firJavaField = FirJavaField(
this@JavaSymbolProvider.session, fieldSymbol, fieldName,
javaField.visibility, javaField.modality,
returnTypeRef = returnType.toFirJavaTypeRef(this@JavaSymbolProvider.session, javaTypeParameterStack),
isVar = !javaField.isFinal,
isStatic = javaField.isStatic
).apply {
addAnnotationsFrom(this@JavaSymbolProvider.session, javaField, javaTypeParameterStack)
},
{
it?.let { (firSymbol, foundClass) ->
val javaClass = foundClass!!
it.foundClass = null
val javaTypeParameterStack = JavaTypeParameterStack()
val parentFqName = classId.relativeClassName.parent()
val isTopLevel = parentFqName.isRoot
if (!isTopLevel) {
val parentId = ClassId(classId.packageFqName, parentFqName, false)
val parentClassSymbol = getClassLikeSymbolByFqName(parentId) as? FirClassSymbol
val parentClass = parentClassSymbol?.fir
if (parentClass is FirJavaClass) {
javaTypeParameterStack.addStack(parentClass.javaTypeParameterStack)
}
declarations += firJavaField
}
for (javaMethod in javaClass.methods) {
val methodName = javaMethod.name
val methodId = CallableId(classId.packageFqName, classId.relativeClassName, methodName)
val methodSymbol = FirNamedFunctionSymbol(methodId)
val returnType = javaMethod.returnType
val firJavaMethod = FirJavaMethod(
this@JavaSymbolProvider.session, methodSymbol, methodName,
javaMethod.visibility, javaMethod.modality,
returnTypeRef = returnType.toFirJavaTypeRef(this@JavaSymbolProvider.session, javaTypeParameterStack),
isStatic = javaMethod.isStatic
).apply {
this.typeParameters += javaMethod.typeParameters.convertTypeParameters(javaTypeParameterStack)
addAnnotationsFrom(this@JavaSymbolProvider.session, javaMethod, javaTypeParameterStack)
for (valueParameter in javaMethod.valueParameters) {
valueParameters += valueParameter.toFirValueParameters(
this@JavaSymbolProvider.session, javaTypeParameterStack
FirJavaClass(
session, firSymbol as FirClassSymbol, javaClass.name,
javaClass.visibility, javaClass.modality,
javaClass.classKind, isTopLevel = isTopLevel,
isStatic = javaClass.isStatic,
javaTypeParameterStack = javaTypeParameterStack
).apply {
this.typeParameters += foundClass.typeParameters.convertTypeParameters(javaTypeParameterStack)
addAnnotationsFrom(this@JavaSymbolProvider.session, javaClass, javaTypeParameterStack)
for (supertype in javaClass.supertypes) {
superTypeRefs += supertype.toFirResolvedTypeRef(this@JavaSymbolProvider.session, javaTypeParameterStack)
}
// TODO: may be we can process fields & methods later.
// However, they should be built up to override resolve stage
for (javaField in javaClass.fields) {
val fieldName = javaField.name
val fieldId = CallableId(classId.packageFqName, classId.relativeClassName, fieldName)
val fieldSymbol = FirFieldSymbol(fieldId)
val returnType = javaField.type
val firJavaField = FirJavaField(
this@JavaSymbolProvider.session, fieldSymbol, fieldName,
javaField.visibility, javaField.modality,
returnTypeRef = returnType.toFirJavaTypeRef(this@JavaSymbolProvider.session, javaTypeParameterStack),
isVar = !javaField.isFinal,
isStatic = javaField.isStatic
).apply {
addAnnotationsFrom(this@JavaSymbolProvider.session, javaField, javaTypeParameterStack)
}
declarations += firJavaField
}
for (javaMethod in javaClass.methods) {
val methodName = javaMethod.name
val methodId = CallableId(classId.packageFqName, classId.relativeClassName, methodName)
val methodSymbol = FirNamedFunctionSymbol(methodId)
val returnType = javaMethod.returnType
val firJavaMethod = FirJavaMethod(
this@JavaSymbolProvider.session, methodSymbol, methodName,
javaMethod.visibility, javaMethod.modality,
returnTypeRef = returnType.toFirJavaTypeRef(this@JavaSymbolProvider.session, javaTypeParameterStack),
isStatic = javaMethod.isStatic
).apply {
this.typeParameters += javaMethod.typeParameters.convertTypeParameters(javaTypeParameterStack)
addAnnotationsFrom(this@JavaSymbolProvider.session, javaMethod, javaTypeParameterStack)
for (valueParameter in javaMethod.valueParameters) {
valueParameters += valueParameter.toFirValueParameters(
this@JavaSymbolProvider.session, javaTypeParameterStack
)
}
}
declarations += firJavaMethod
}
val javaClassDeclaredConstructors = javaClass.constructors
val constructorId = CallableId(classId.packageFqName, classId.relativeClassName, classId.shortClassName)
fun addJavaConstructor(
visibility: Visibility = this.visibility,
isPrimary: Boolean = false
): FirJavaConstructor {
val constructorSymbol = FirConstructorSymbol(constructorId)
val classTypeParameters = javaClass.typeParameters.convertTypeParameters(javaTypeParameterStack)
val firJavaConstructor = FirJavaConstructor(
this@JavaSymbolProvider.session, constructorSymbol, visibility, isPrimary,
FirResolvedTypeRefImpl(
this@JavaSymbolProvider.session, null,
firSymbol.constructType(
classTypeParameters.map {
ConeTypeParameterTypeImpl(
it.symbol.toLookupTag(),
false
)
}.toTypedArray(),
false
)
)
).apply {
this.typeParameters += classTypeParameters
}
declarations += firJavaConstructor
return firJavaConstructor
}
if (javaClassDeclaredConstructors.isEmpty() && javaClass.classKind == ClassKind.CLASS) {
addJavaConstructor(isPrimary = true)
}
for (javaConstructor in javaClassDeclaredConstructors) {
addJavaConstructor(javaConstructor.visibility).apply {
this.typeParameters += javaConstructor.typeParameters.convertTypeParameters(javaTypeParameterStack)
addAnnotationsFrom(this@JavaSymbolProvider.session, javaConstructor, javaTypeParameterStack)
for (valueParameter in javaConstructor.valueParameters) {
valueParameters += valueParameter.toFirValueParameters(
this@JavaSymbolProvider.session, javaTypeParameterStack
)
}
}
}
declarations += firJavaMethod
}
val javaClassDeclaredConstructors = javaClass.constructors
val constructorId = CallableId(classId.packageFqName, classId.relativeClassName, classId.shortClassName)
fun addJavaConstructor(
visibility: Visibility = this.visibility,
isPrimary: Boolean = false
): FirJavaConstructor {
val constructorSymbol = FirConstructorSymbol(constructorId)
val classTypeParameters = javaClass.typeParameters.convertTypeParameters(javaTypeParameterStack)
val firJavaConstructor = FirJavaConstructor(
this@JavaSymbolProvider.session, constructorSymbol, visibility, isPrimary,
FirResolvedTypeRefImpl(
this@JavaSymbolProvider.session, null,
firSymbol.constructType(
classTypeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
false
)
)
).apply {
this.typeParameters += classTypeParameters
}
declarations += firJavaConstructor
return firJavaConstructor
}
if (javaClassDeclaredConstructors.isEmpty() && javaClass.classKind == ClassKind.CLASS) {
addJavaConstructor(isPrimary = true)
}
for (javaConstructor in javaClassDeclaredConstructors) {
addJavaConstructor(javaConstructor.visibility).apply {
this.typeParameters += javaConstructor.typeParameters.convertTypeParameters(javaTypeParameterStack)
addAnnotationsFrom(this@JavaSymbolProvider.session, javaConstructor, javaTypeParameterStack)
for (valueParameter in javaConstructor.valueParameters) {
valueParameters += valueParameter.toFirValueParameters(
this@JavaSymbolProvider.session, javaTypeParameterStack
)
}
}
}
}
}
}
)?.symbol
}
private fun findPackageUncached(fqName: FqName): PsiPackage? {
return facade.findPackage(fqName.asString(), searchScope)
}
val nPackageCache = ConcurrentHashMapNonRecursiveComputeCache<FqName, FqName?>()
override fun getPackage(fqName: FqName): FqName? {
return packageCache.lookupCacheOrCalculate(fqName) {
val facade = KotlinJavaPsiFacade.getInstance(project)
val javaPackage = facade.findPackage(fqName.asString(), searchScope) ?: return@lookupCacheOrCalculate null
return nPackageCache.lookup(fqName) {
val javaPackage = findPackageUncached(fqName) ?: return@lookup null
FqName(javaPackage.qualifiedName)
}
}
@@ -266,16 +299,19 @@ class JavaSymbolProvider(
.map { it.fir }
}
private val knownClassNamesInPackage = mutableMapOf<FqName, Set<String>?>()
private val knownClassNamesInPackage =
ConcurrentHashMapNonRecursiveComputeCache<FqName, Set<String>?>()
private fun hasTopLevelClassOf(classId: ClassId): Boolean {
val knownNames = knownClassNamesInPackage.getOrPut(classId.packageFqName) {
val knownNames = knownClassNamesInPackage.lookup(classId.packageFqName) {
facade.knownClassNamesInPackage(classId.packageFqName)
} ?: return true
return classId.relativeClassName.topLevelName() in knownNames
}
}
val globalFindClassLock = ReentrantLock()
fun FqName.topLevelName() =
asString().substringBefore(".")

View File

@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirAbstractCallableMember
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.symbols.impl.FirFieldSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.name.Name
class FirJavaField(
@@ -43,4 +44,8 @@ class FirJavaField(
init {
status.isStatic = isStatic
}
override fun <D> transformChildrenWithoutAccessors(transformer: FirTransformer<D>, data: D) {
transformChildren(transformer, data)
}
}

View File

@@ -21,6 +21,9 @@ import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
import org.jetbrains.kotlin.fir.java.createConstant
import org.jetbrains.kotlin.fir.java.topLevelName
import org.jetbrains.kotlin.fir.concurrent.ConcurrentHashMapNonRecursiveComputeCache
import org.jetbrains.kotlin.fir.concurrent.SynchronizedComputeCache
import org.jetbrains.kotlin.fir.concurrent.TransactionalCache
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.resolve.*
@@ -52,7 +55,6 @@ import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.serialization.deserialization.getName
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import org.jetbrains.kotlin.utils.getOrPutNullable
class KotlinDeserializedJvmSymbolsProvider(
val session: FirSession,
@@ -63,8 +65,11 @@ class KotlinDeserializedJvmSymbolsProvider(
private val javaClassFinder: JavaClassFinder
) : AbstractFirSymbolProvider() {
private val classesCache = HashMap<ClassId, FirClassSymbol>()
private val typeAliasCache = HashMap<ClassId, FirTypeAliasSymbol?>()
private val packagePartsCache = HashMap<FqName, Collection<PackagePartsCacheData>>()
private val typeAliasCache =
ConcurrentHashMapNonRecursiveComputeCache<ClassId, FirTypeAliasSymbol?>()
private val packagePartsCache =
SynchronizedComputeCache<FqName, Collection<PackagePartsCacheData>>()
private val handledByJava = HashSet<ClassId>()
@@ -144,7 +149,7 @@ class KotlinDeserializedJvmSymbolsProvider(
useSiteSession: FirSession,
scopeSession: ScopeSession
): FirScope? {
val symbol = this.getClassLikeSymbolByFqName(classId) as? FirClassSymbol ?: return null
val symbol = this.findAndDeserializeClassInternal(classId)?.takeUnless { it.fromJava }?.symbol ?: return null
return symbol.fir.buildDefaultUseSiteScope(session, scopeSession)
}
@@ -156,7 +161,7 @@ class KotlinDeserializedJvmSymbolsProvider(
private fun findAndDeserializeTypeAlias(
classId: ClassId
): FirTypeAliasSymbol? {
return typeAliasCache.getOrPutNullable(classId) {
return typeAliasCache.lookup(classId) {
getPackageParts(classId.packageFqName).firstNotNullResult { part ->
val ids = part.typeAliasNameIndex[classId.shortClassName]
if (ids == null || ids.isEmpty()) return@firstNotNullResult null
@@ -306,56 +311,106 @@ class KotlinDeserializedJvmSymbolsProvider(
return loadAnnotation(annotationClassId, result)
}
private val nClassesCache = TransactionalCache<ClassId, ClassCacheRec?/* null | FirClassSymbol */>()
private data class ClassCacheRec(
val symbol: FirClassSymbol,
var binaryClass: KotlinJvmBinaryClass? = null,
val fromJava: Boolean = false
)
private val enumEntryCache = TransactionalCache<FirClassSymbol, Map<Name, FirClassSymbol>?>()
private fun findAndDeserializeClass(
classId: ClassId,
parentContext: FirDeserializationContext? = null
): FirClassSymbol? {
if (!hasTopLevelClassOf(classId)) return null
if (classesCache.containsKey(classId)) return classesCache[classId]
return findAndDeserializeClassInternal(classId, parentContext)?.symbol
}
if (classId in handledByJava) return null
private fun findAndDeserializeClassInternal(
classId: ClassId,
parentContext: FirDeserializationContext? = null
): ClassCacheRec? {
val kotlinJvmBinaryClass = when (val result = kotlinClassFinder.findKotlinClassOrContent(classId)) {
is KotlinClassFinder.Result.KotlinClass -> result.kotlinJvmBinaryClass
is KotlinClassFinder.Result.ClassFileContent -> {
handledByJava.add(classId)
return javaSymbolProvider.getFirJavaClass(classId, result) as FirClassSymbol?
}
null -> null
}
if (kotlinJvmBinaryClass == null) {
fun tryLoadEnum(classId: ClassId): FirClassSymbol? {
val outerClassId = classId.outerClassId ?: return null
findAndDeserializeClass(outerClassId) ?: return null
} else {
if (kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return null
val (nameResolver, classProto) = kotlinJvmBinaryClass.readClassDataFrom() ?: return null
val symbol = FirClassSymbol(classId)
deserializeClassToSymbol(
classId, classProto, symbol, nameResolver, session,
JvmBinaryAnnotationDeserializer(session),
parentContext, this::findAndDeserializeClass
)
symbol.fir.declarations.filterIsInstance<FirEnumEntryImpl>().forEach {
classesCache[it.symbol.classId] = it.symbol
}
classesCache[classId] = symbol
val annotations = mutableListOf<FirAnnotationCall>()
kotlinJvmBinaryClass.loadClassAnnotations(object : KotlinJvmBinaryClass.AnnotationVisitor {
override fun visitAnnotation(classId: ClassId, source: SourceElement): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
return loadAnnotationIfNotSpecial(classId, annotations)
}
override fun visitEnd() {
}
}, null)
(symbol.fir as FirAbstractAnnotatedElement).annotations += annotations
val outerClass = findAndDeserializeClass(outerClassId) ?: return null
return enumEntryCache.lookup(
outerClass,
{
val enumEntries = outerClass.fir.declarations.filterIsInstance<FirEnumEntryImpl>()
if (enumEntries.isNotEmpty()) {
enumEntries.associate {
it.name to it.symbol
}
} else null
},
{}
)?.get(classId.shortClassName)
}
return classesCache[classId]
// }
if (!hasTopLevelClassOf(classId)) return null
return nClassesCache.lookup(
classId,
{
val kotlinJvmBinaryClass = when (val result = kotlinClassFinder.findKotlinClassOrContent(classId)) {
is KotlinClassFinder.Result.KotlinClass -> result.kotlinJvmBinaryClass
is KotlinClassFinder.Result.ClassFileContent -> {
return@lookup (javaSymbolProvider.getFirJavaClass(classId, result) as FirClassSymbol?)?.let {
ClassCacheRec(
it,
fromJava = true
)
}
}
null -> null
}
if (kotlinJvmBinaryClass == null) {
return@lookup tryLoadEnum(classId)?.let(::ClassCacheRec)
// side-effect: loads enum
} else {
if (kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return@lookup null
val (nameResolver, classProto) = kotlinJvmBinaryClass.readClassDataFrom() ?: return@lookup null
val symbol = FirClassSymbol(classId)
deserializeClassToSymbol(
classId, classProto, symbol, nameResolver, session,
JvmBinaryAnnotationDeserializer(session),
parentContext, this::findAndDeserializeClass
)
return@lookup ClassCacheRec(symbol, kotlinJvmBinaryClass)
}
}, { rec ->
if (rec != null) {
val (symbol, binaryClass) = rec
if (binaryClass == null) return@lookup
val annotations = mutableListOf<FirAnnotationCall>()
binaryClass.loadClassAnnotations(object : KotlinJvmBinaryClass.AnnotationVisitor {
override fun visitAnnotation(
classId: ClassId,
source: SourceElement
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
return loadAnnotationIfNotSpecial(classId, annotations)
}
override fun visitEnd() {
}
}, null)
(symbol.fir as FirAbstractAnnotatedElement).annotations += annotations
rec.binaryClass = null
}
}
)
}
private fun loadFunctionsByName(part: PackagePartsCacheData, name: Name): List<FirCallableSymbol<*>> {
@@ -378,19 +433,25 @@ class KotlinDeserializedJvmSymbolsProvider(
}
}
private val topLevelCallablesCache =
ConcurrentHashMapNonRecursiveComputeCache<CallableId, List<FirCallableSymbol<*>>>()
override fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List<FirCallableSymbol<*>> {
return getPackageParts(packageFqName).flatMap { part ->
loadFunctionsByName(part, name) + loadPropertiesByName(part, name)
return topLevelCallablesCache.lookup(CallableId(packageFqName, null, name)) {
getPackageParts(packageFqName).flatMap { part ->
loadFunctionsByName(part, name) + loadPropertiesByName(part, name)
}
}
}
override fun getClassDeclaredMemberScope(classId: ClassId) =
findRegularClass(classId)?.let {
declaredMemberScope(it)
findAndDeserializeClassInternal(classId)?.takeUnless { it.fromJava }?.let {
declaredMemberScope(it.symbol.fir)
}
private fun getPackageParts(packageFqName: FqName): Collection<PackagePartsCacheData> {
return packagePartsCache.getOrPut(packageFqName) {
return packagePartsCache.lookup(packageFqName) {
computePackagePartsInfos(packageFqName)
}
}

View File

@@ -27,6 +27,8 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.utils.Jsr305State
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
internal class EnhancementSignatureParts(
private val typeQualifierResolver: FirAnnotationTypeQualifierResolver,
@@ -46,6 +48,7 @@ internal class EnhancementSignatureParts(
internal fun enhance(
session: FirSession,
jsr305State: Jsr305State,
lock: ReentrantLock,
predefined: TypeEnhancementInfo? = null
): PartEnhancementResult {
val qualifiers = computeIndexedQualifiersForOverride(session, jsr305State)

View File

@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotationContainer
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirConstExpressionImpl
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.java.declarations.*
import org.jetbrains.kotlin.fir.java.enhancement.*
@@ -33,9 +34,11 @@ import org.jetbrains.kotlin.load.java.typeEnhancement.PredefinedFunctionEnhancem
import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.Jsr305State
import kotlin.concurrent.withLock
class JavaClassEnhancementScope(
private val session: FirSession,
val symbolProvider: JavaSymbolProvider,
private val useSiteScope: JavaClassUseSiteScope
) : FirScope() {
private val owner: FirRegularClass = useSiteScope.symbol.fir
@@ -241,7 +244,14 @@ class JavaClassEnhancementScope(
private fun StringBuilder.appendErasedType(typeRef: FirTypeRef) {
when (typeRef) {
is FirResolvedTypeRef -> appendConeType(typeRef.type)
is FirJavaTypeRef -> appendConeType(typeRef.toNotNullConeKotlinType(session, javaTypeParameterStack))
is FirJavaTypeRef -> //symbolProvider.findClassLock.withLock {
appendConeType(
typeRef.toNotNullConeKotlinType(
session,
javaTypeParameterStack
)
)
//}
}
}
@@ -278,7 +288,7 @@ class JavaClassEnhancementScope(
parameterContainer = ownerFunction,
methodContext = memberContext,
typeInSignature = TypeInSignature.Receiver
).enhance(session, jsr305State)
).enhance(session, jsr305State, symbolProvider.findClassLock)
return signatureParts.type
}
@@ -299,7 +309,7 @@ class JavaClassEnhancementScope(
parameterContainer = ownerParameter,
methodContext = memberContext,
typeInSignature = TypeInSignature.ValueParameter(hasReceiver, index)
).enhance(session, jsr305State, predefinedEnhancementInfo?.parametersInfo?.getOrNull(index))
).enhance(session, jsr305State, symbolProvider.findClassLock, predefinedEnhancementInfo?.parametersInfo?.getOrNull(index))
val firResolvedTypeRef = signatureParts.type
val defaultValueExpression = when (val defaultValue = ownerParameter.getDefaultValueFromAnnotation()) {
NullDefaultValue -> FirConstExpressionImpl(session, null, IrConstKind.Null, null)
@@ -324,7 +334,7 @@ class JavaClassEnhancementScope(
if (owner is FirJavaField) AnnotationTypeQualifierResolver.QualifierApplicabilityType.FIELD
else AnnotationTypeQualifierResolver.QualifierApplicabilityType.METHOD_RETURN_TYPE,
typeInSignature = TypeInSignature.Return
).enhance(session, jsr305State, predefinedEnhancementInfo?.returnTypeInfo)
).enhance(session, jsr305State, symbolProvider.findClassLock, predefinedEnhancementInfo?.returnTypeInfo)
return signatureParts.type
}

View File

@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.java.toNotNullConeKotlinType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.*
@@ -68,7 +68,7 @@ class JavaClassUseSiteScope(
val types = base.typeParameters.map {
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
}
val substitution = ConeSubstitutorByMap(overriddenInJava.typeParameters.map { it.symbol }.zip(types).toMap())
val substitution = substitutorByMap(overriddenInJava.typeParameters.map { it.symbol }.zip(types).toMap())
if (!overriddenInJava.typeParameters.zip(base.typeParameters).all { (a, b) ->
a.bounds.size == b.bounds.size && a.bounds.zip(b.bounds).all { (aBound, bBound) ->
isEqualTypes(aBound, bBound, substitution)

View File

@@ -18,9 +18,8 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.dump.MultiModuleHtmlFirDump
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
import org.jetbrains.kotlin.fir.concurrent.tcReg
import org.jetbrains.kotlin.fir.resolve.transformers.FirStagesTransformerFactory
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils
@@ -29,7 +28,6 @@ import java.io.File
import java.io.PrintStream
import java.text.SimpleDateFormat
import java.util.*
import kotlin.system.measureNanoTime
private const val FAIL_FAST = true
@@ -55,21 +53,16 @@ class FirResolveModularizedTotalKotlinTest : AbstractModularizedTest() {
val session = createSession(environment, scope, librariesScope)
val builder = RawFirBuilder(session, stubMode = false)
val totalTransformer = FirTotalResolveTransformer()
val firFiles = ktFiles.toList().mapNotNull {
var firFile: FirFile? = null
val time = measureNanoTime {
firFile = builder.buildFirFile(it)
(session.service<FirProvider>() as FirProviderImpl).recordFile(firFile!!)
}
bench.countBuilder(builder, time)
firFile
}.toList()
val factory = FirStagesTransformerFactory(session)
val firFiles = bench.buildFiles(
builder,
ktFiles.toList()
)
println("Raw FIR up, files: ${firFiles.size}")
bench.processFiles(firFiles, totalTransformer.transformers)
bench.processFiles(firFiles, factory)
dumpFir(moduleData, firFiles)
dumpFirHtml(moduleData, firFiles)
@@ -128,6 +121,7 @@ class FirResolveModularizedTotalKotlinTest : AbstractModularizedTest() {
bench.report(System.out, errorTypeReports = false)
saveReport()
tcReg.clear()
if (FAIL_FAST) {
bench.throwFailure()
}

View File

@@ -6,7 +6,11 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.fir.types.ConeTypeContext
import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache
private class SessionBasedTypeContext(override val session: FirSession) : ConeTypeContext
private class SessionBasedTypeContext(
override val session: FirSession,
override val correspondingSupertypesCache: FirCorrespondingSupertypesCache?
) : ConeTypeContext
val FirSession.typeContext: ConeTypeContext get() = SessionBasedTypeContext(this)
val FirSession.typeContext: ConeTypeContext get() = SessionBasedTypeContext(this, null)

View File

@@ -0,0 +1,17 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.concurrent
abstract class AbstractLookupCache<K : Any, V> {
abstract fun lookup(key: K, compute: (K) -> V): V
}
abstract class AbstractLateBindingLookupCache<K : Any, V> : AbstractLookupCache<K, V>() {
abstract fun lookup(key: K, compute: (K) -> V, postCompute: (V) -> Unit): V
override fun lookup(key: K, compute: (K) -> V): V {
return lookup(key, compute) {}
}
}

View File

@@ -0,0 +1,17 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.concurrent
import java.util.concurrent.ConcurrentHashMap
class ConcurrentHashMapNonRecursiveComputeCache<K : Any, V>(
val storage: ConcurrentHashMap<K, V> = ConcurrentHashMap()
) : AbstractLookupCache<K, V>() {
override fun lookup(key: K, compute: (K) -> V): V {
return storage.computeIfAbsent(key, compute)
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.concurrent
import java.lang.RuntimeException
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
class NonRecursiveCooperativeComputeCache<K : Any, V> : AbstractLookupCache<K, V>() {
val storage = ReadLockFreeOpenAddressingHashMap<K, Any>()
val index = AtomicInteger()
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
class Computation(val index: Int) {
var completed: Boolean = false
@Synchronized
fun await() {
while (!completed) (this as Object).wait()
}
@Synchronized
fun complete() {
completed = true
(this as Object).notifyAll()
}
}
val lock = ReentrantLock()
private fun Computation.beginCompute(key: K): Any? {
while (true) {
val otherComputation: Computation = lock.withLock {
val nv = storage[key]
when (nv) {
is Computation -> {
if (!nv.completed && nv.index < this.index) {
return@withLock nv
}
storage[key] = this
return null
}
null -> {
storage[key] = this
return nv
}
else -> return nv
}
}
otherComputation.await()
}
}
private fun Computation.commit(key: K, value: Any): Boolean {
return try {
lock.withLock {
if (storage[key] !is Computation) return@withLock false
storage[key] = value
true
}
} finally {
complete()
}
}
override tailrec fun lookup(key: K, compute: (K) -> V): V {
val v = storage[key]
if (v != null && v !is Computation) return unbox(v)
val computation = Computation(index.getAndIncrement())
val nv = computation.beginCompute(key)
val computed: Any
if (nv == null) {
try {
computed = compute(key) ?: NULL
} catch (t: Throwable) {
computation.complete()
throw RuntimeException("Exception in computation", t)
}
if (!computation.commit(key, computed)) {
return lookup(key, compute)
}
} else {
computed = nv
}
return unbox(computed)
}
@Suppress("UNCHECKED_CAST")
private fun unbox(v: Any): V = (if (v === NULL) null else v) as V
}
private val NULL = Any()

View File

@@ -0,0 +1,119 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.concurrent
import java.util.concurrent.atomic.AtomicReferenceArray
import kotlin.math.pow
import kotlin.math.sqrt
class ReadLockFreeOpenAddressingHashMap<K : Any, V> {
@Volatile
private var core = Core(128)
operator fun contains(key: K) = core.getKey(key) === NOT_FOUND
@Suppress("UNCHECKED_CAST")
operator fun get(key: K): V? {
val value = core.getKey(key)
return if (value === NOT_FOUND) null else value as V
}
/**
* Should be externally synchronized
*/
// @Synchronized
operator fun set(key: K, value: V) {
while (core.isOverpopulated() || !core.putKey(key, value))
core = core.rehash(core.length())
}
/**
* Should be externally synchronized
*/
// @Synchronized
fun putAll(map: Map<K, V>) {
for ((k, v) in map) {
set(k, v)
}
}
private class Core(
capacity: Int
) : AtomicReferenceArray<Any?>(2 * capacity) {
init {
require(capacity and (capacity - 1) == 0)
}
private val shift = Integer.numberOfLeadingZeros(capacity) + 1
private val limit: Int = capacity / 8
var size = 0
fun isOverpopulated(): Boolean {
return size > (length() / 2 * DEFAULT_LOAD_FACTOR)
}
fun getKey(key: Any): Any? {
var index = index(key)
repeat(limit) {
when (get(index)) {
null -> return NOT_FOUND
key -> return get(index + 1)
}
index -= 2
if (index < 0) index = length() - 2
}
return NOT_FOUND
}
fun putKey(key: Any, value: Any?): Boolean {
var index = index(key)
repeat(limit) {
when (get(index)) {
null -> {
lazySet(index + 1, value) // must be first!!!
set(index, key)
size++
return true
}
key -> {
set(index + 1, value)
return true
}
}
index -= 2
if (index < 0) index = length() - 2
}
return false
}
fun index(key: Any): Int = (key.hashCode() * MAGIC) ushr shift shl 1
}
private tailrec fun Core.rehash(capacity: Int): Core {
val new = Core(capacity)
for (i in 0 until length() step 2) {
val key = get(i)
if (key != null) {
if (!new.putKey(key, get(i + 1)))
return rehash(capacity * 2)
}
}
return new
}
}
private val MAGIC: Int = ((sqrt(5.0) - 1) * 2.0.pow(31)).toLong().toInt() // golden
private val NOT_FOUND = Any()
private const val DEFAULT_LOAD_FACTOR = 0.5

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.concurrent
import org.jetbrains.kotlin.fir.resolve.getOrPut
class SingleThreadLookupCache<K : Any, V> : AbstractLateBindingLookupCache<K, V>() {
val storage = mutableMapOf<K, Any>()
override fun lookup(key: K, compute: (K) -> V, postCompute: (V) -> Unit): V {
return unbox(
storage.getOrPut(
key,
{ compute(key) ?: NULL },
{ postCompute(unbox(it)) }
)
)
}
@Suppress("UNCHECKED_CAST")
private fun unbox(v: Any): V = (if (v === NULL) null else v) as V
}
private val NULL = Any()

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.concurrent
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
class SynchronizedComputeCache<K : Any, V>(val storage: ReadLockFreeOpenAddressingHashMap<K, Any> = ReadLockFreeOpenAddressingHashMap()) :
AbstractLookupCache<K, V>() {
private val lock = ReentrantLock()
override fun lookup(key: K, compute: (K) -> V): V {
val v = storage[key]
return unbox(
if (v == null) {
assert(!lock.isHeldByCurrentThread) { "SynchronizedComputeCache doesn't support recursive calculation" }
lock.withLock {
val u = storage[key]
if (u == null) {
val computed = compute(key) ?: NULL
storage[key] = computed
computed
} else {
u
}
}
} else v
)
}
@Suppress("UNCHECKED_CAST")
private fun unbox(v: Any): V = (if (v === NULL) null else v) as V
}
private val NULL = Any()

View File

@@ -0,0 +1,159 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.concurrent
import java.lang.RuntimeException
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.getOrSet
import kotlin.concurrent.withLock
val tcReg = mutableListOf<TransactionalCache<*, *>>()
class TransactionalCache<K : Any, V> : AbstractLateBindingLookupCache<K, V>() {
init {
tcReg += this
}
val storage: ReadLockFreeOpenAddressingHashMap<K, Any> =
ReadLockFreeOpenAddressingHashMap()
private var commits = 0L
private var retries = 0L
private var joins = 0L
fun stats(): String {
return "Commits: $commits, Success: ${commits - retries}, Retries: $retries, Joins: $joins"
}
private val transaction = ThreadLocal<Transaction<K>>()
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
class Transaction<K>(
val index: Int,
val transactionStorage: MutableMap<K, Any>
) {
var completed = false
@Synchronized
fun await() {
while (!completed) (this as Object).wait()
}
@Synchronized
fun complete() {
completed = true
(this as Object).notifyAll()
}
}
private val indexCounter = AtomicInteger()
private val lock = ReentrantLock()
private fun beginCompute(currentTransaction: Transaction<K>, key: K): Any? {
while (true) {
val v: Transaction<*> = lock.withLock {
val v = storage[key]
when (v) {
is Transaction<*> -> {
if (v.index < currentTransaction.index && !v.completed) {
joins++
return@withLock v
}
storage[key] = currentTransaction
return null
}
null -> storage[key] = currentTransaction
}
return v
}
v.await()
}
}
private fun Transaction<K>.commit(): Boolean {
return try {
lock.withLock {
commits++
val canCommit = transactionStorage.keys.all {
val v = storage[it]
v is Transaction<*>?
}
transaction.remove()
if (!canCommit) {
retries++
return@withLock false
}
storage.putAll(transactionStorage)
true
}
} finally {
this.complete()
}
}
private fun Transaction<K>.abort() {
this.complete()
transaction.remove()
}
override fun lookup(key: K, compute: (K) -> V): V {
return lookup(key, compute, {})
}
override tailrec fun lookup(key: K, compute: (K) -> V, postCompute: (V) -> Unit): V {
val v = storage[key]
if (v != null && v !is Transaction<*>) return unbox(v)
var startedTransaction = false
val currentTransaction = transaction.getOrSet {
startedTransaction = true
Transaction(indexCounter.getAndIncrement(), mutableMapOf())
}
val computed: Any
val cached = currentTransaction.transactionStorage[key]
if (cached != null)
return unbox(cached)
else {
val nv = beginCompute(currentTransaction, key)
if (nv == null) {
try {
computed = compute(key) as Any? ?: NULL
currentTransaction.transactionStorage[key] = computed
postCompute(unbox(computed))
} catch (t: Throwable) {
currentTransaction.abort()
t.printStackTrace()
throw RuntimeException("Exception in compute", t)
}
} else {
computed = nv
}
}
if (startedTransaction) {
if (!currentTransaction.commit()) {
return lookup(key, compute, postCompute)
}
}
return unbox(computed)
}
@Suppress("UNCHECKED_CAST")
private fun unbox(computed: Any) = (if (computed === NULL) null else computed) as V
}
private val NULL = Any()

View File

@@ -80,7 +80,7 @@ fun resolveSubCallArgument(
) {
val candidate = argument.candidate() ?: return resolvePlainExpressionArgument(csBuilder, argument, expectedType, sink, isReceiver, isSafeCall, typeProvider)
val type = sink.components.returnTypeCalculator.tryCalculateReturnType(candidate.symbol.firUnsafe()).coneTypeUnsafe<ConeKotlinType>()
val argumentType = candidate.substitutor.substituteOrSelf(type)
val argumentType = candidate.substitutor!!.substituteOrSelf(type)
resolvePlainArgumentType(csBuilder, argumentType, expectedType, sink, isReceiver, isSafeCall)
}
@@ -159,7 +159,7 @@ internal fun Candidate.resolveArgument(
private fun Candidate.prepareExpectedType(session: FirSession, argument: FirExpression, parameter: FirValueParameter): ConeKotlinType {
val expectedType = argument.getExpectedType(session, parameter/*, LanguageVersionSettings*/)
return this.substitutor.substituteOrSelf(expectedType)
return this.substitutor!!.substituteOrSelf(expectedType)
}
internal fun FirExpression.getExpectedType(

View File

@@ -33,9 +33,11 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.cast
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.createCoroutineUnintercepted
@@ -88,27 +90,111 @@ class CheckerSinkImpl(override val components: InferenceComponents, var continua
}
}
class CandidatePool {
class Candidate(
val symbol: FirBasedSymbol<*>,
val dispatchReceiverValue: ClassDispatchReceiverValue?,
val implicitExtensionReceiverValue: ImplicitReceiverValue?,
val explicitReceiverKind: ExplicitReceiverKind,
private val inferenceComponents: InferenceComponents,
private val baseSystem: ConstraintStorage,
val callInfo: CallInfo
) {
val system by lazy {
val system = inferenceComponents.createConstraintSystem()
system.addOtherSystem(baseSystem)
system
val pool = ArrayList<PooledCandidate>()
private fun preAlloc(num: Int) {
pool.ensureCapacity(num)
repeat(num) {
pool += PooledCandidate()
}
}
lateinit var substitutor: ConeSubstitutor
fun new(): PooledCandidate {
if (pool.isEmpty()) {
preAlloc(16)
}
return pool.removeAt(pool.lastIndex)
}
fun free(candidate: PooledCandidate) {
candidate.reset()
pool.add(candidate)
}
}
class PooledCandidate() {
var symbol: FirBasedSymbol<*>? = null
var dispatchReceiverValue: ClassDispatchReceiverValue? = null
var implicitExtensionReceiverValue: ImplicitReceiverValue? = null
var explicitReceiverKind: ExplicitReceiverKind? = null
var system: NewConstraintSystemImpl? = null
var callInfo: CallInfo? = null
var substitutor: ConeSubstitutor? = null
var argumentMapping: Map<FirExpression, FirValueParameter>? = null
val postponedAtoms = mutableListOf<PostponedResolvedAtomMarker>()
var baseSystem: ConstraintStorage? = null
var inferenceComponents: InferenceComponents? = null
fun system(): NewConstraintSystemImpl {
return system ?: inferenceComponents!!.createConstraintSystem()?.also {
it.addOtherSystem(baseSystem!!)
system = it
}
}
fun reset() {
symbol = null
dispatchReceiverValue = null
implicitExtensionReceiverValue = null
explicitReceiverKind = null
system = null
callInfo = null
substitutor = null
baseSystem = null
inferenceComponents = null
argumentMapping = null
postponedAtoms.clear()
}
}
inline class Candidate(val pooledCandidate: PooledCandidate) {
val symbol: FirBasedSymbol<*> get() = pooledCandidate.symbol!!
val dispatchReceiverValue: ClassDispatchReceiverValue? get() = pooledCandidate.dispatchReceiverValue
val implicitExtensionReceiverValue: ImplicitReceiverValue? get() = pooledCandidate.implicitExtensionReceiverValue
val explicitReceiverKind: ExplicitReceiverKind get() = pooledCandidate.explicitReceiverKind!!
val callInfo: CallInfo get() = pooledCandidate.callInfo!!
val system get() = pooledCandidate.system()
var substitutor: ConeSubstitutor?
get() = pooledCandidate.substitutor
set(value) {
pooledCandidate.substitutor = value
}
var argumentMapping: Map<FirExpression, FirValueParameter>?
get() = pooledCandidate.argumentMapping
set(value) {
pooledCandidate.argumentMapping = value
}
val postponedAtoms get() = pooledCandidate.postponedAtoms
}
//
//class Candidate(
// val symbol: FirBasedSymbol<*>,
// val dispatchReceiverValue: ClassDispatchReceiverValue?,
// val implicitExtensionReceiverValue: ImplicitReceiverValue?,
// val explicitReceiverKind: ExplicitReceiverKind,
// private val inferenceComponents: InferenceComponents,
// private val baseSystem: ConstraintStorage,
// val callInfo: CallInfo
//) {
// val system by lazy {
// val system = inferenceComponents.createConstraintSystem()
// system.addOtherSystem(baseSystem)
// system
// }
// lateinit var substitutor: ConeSubstitutor
//
// var argumentMapping: Map<FirExpression, FirValueParameter>? = null
// val postponedAtoms = mutableListOf<PostponedResolvedAtomMarker>()
//}
sealed class CallKind {
abstract fun sequence(): List<ResolutionStage>
@@ -394,7 +480,8 @@ abstract class TowerDataConsumer {
fun skipGroup(group: Int, resultCollector: CandidateCollector): Boolean {
if (resultCollector.isSuccess() && stopGroup == Int.MAX_VALUE) {
stopGroup = group
} else if (group > stopGroup) return true
}
if (group >= stopGroup) return true
return false
}
}
@@ -475,20 +562,18 @@ fun createFunctionConsumer(
inferenceComponents,
resultCollector
),
MultiplexerTowerDataConsumer(resultCollector).apply {
addConsumer(
createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Properties,
varCallInfo,
inferenceComponents,
InvokeCandidateCollector(
callResolver,
invokeCallInfo = callInfo,
components = inferenceComponents,
multiplexer = this
)
AccumulatingTowerDataConsumer(resultCollector).apply {
initialConsumer = createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Properties,
varCallInfo,
inferenceComponents,
InvokeReceiverCandidateCollector(
callResolver,
invokeCallInfo = callInfo,
components = inferenceComponents,
invokeConsumer = this
)
)
}
@@ -552,16 +637,19 @@ class PrioritizedTowerDataConsumer(
}
}
class MultiplexerTowerDataConsumer(
val resultCollector: CandidateCollector
// Yet is used exclusively for invokes:
// - initialConsumer consumes property which is invoke receiver
// - additionalConsumers consume invoke calls themselves
class AccumulatingTowerDataConsumer(
private val resultCollector: CandidateCollector
) : TowerDataConsumer() {
val consumers = mutableListOf<TowerDataConsumer>()
val newConsumers = mutableListOf<TowerDataConsumer>()
lateinit var initialConsumer: TowerDataConsumer
private val additionalConsumers = mutableListOf<TowerDataConsumer>()
data class TowerData(val kind: TowerDataKind, val level: TowerScopeLevel, val group: Int)
private data class TowerData(val kind: TowerDataKind, val level: TowerScopeLevel, val group: Int)
val datas = mutableListOf<TowerData>()
private val accumulatedTowerData = mutableListOf<TowerData>()
override fun consume(
kind: TowerDataKind,
@@ -569,11 +657,12 @@ class MultiplexerTowerDataConsumer(
group: Int
): ProcessorAction {
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
consumers += newConsumers
newConsumers.clear()
datas += TowerData(kind, towerScopeLevel, group)
accumulatedTowerData += TowerData(kind, towerScopeLevel, group)
for (consumer in consumers) {
if (initialConsumer.consume(kind, towerScopeLevel, group).stop()) {
return ProcessorAction.STOP
}
for (consumer in additionalConsumers) {
val action = consumer.consume(kind, towerScopeLevel, group)
if (action.stop()) {
return ProcessorAction.STOP
@@ -582,20 +671,17 @@ class MultiplexerTowerDataConsumer(
return ProcessorAction.NEXT
}
fun addConsumer(consumer: TowerDataConsumer): ProcessorAction =
run {
for ((kind, level, group) in datas) {
if (consumer.consume(kind, level, group).stop()) {
return@run ProcessorAction.STOP
}
fun addConsumer(consumer: TowerDataConsumer): ProcessorAction {
additionalConsumers += consumer
for ((kind, level, group) in accumulatedTowerData) {
if (consumer.consume(kind, level, group).stop()) {
return ProcessorAction.STOP
}
return@run ProcessorAction.NEXT
}.also {
newConsumers += consumer
}
return ProcessorAction.NEXT
}
}
class ExplicitReceiverTowerDataConsumer<T : FirBasedSymbol<*>>(
val session: FirSession,
val name: Name,
@@ -782,7 +868,11 @@ class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: Inf
return group
}
val collector by lazy { CandidateCollector(components) }
fun reset() {
collector.newDataSet()
}
val collector = CandidateCollector(components)
lateinit var towerDataConsumer: TowerDataConsumer
private lateinit var implicitReceiverValues: List<ImplicitReceiverValue>
@@ -831,7 +921,7 @@ enum class CandidateApplicability {
open class CandidateCollector(val components: InferenceComponents) {
val groupNumbers = mutableListOf<Int>()
val candidates = mutableListOf<Candidate>()
val candidates = mutableListOf<PooledCandidate>()
var currentApplicability = CandidateApplicability.HIDDEN
@@ -881,13 +971,14 @@ open class CandidateCollector(val components: InferenceComponents) {
if (applicability > currentApplicability) {
groupNumbers.clear()
candidates.forEach { components.candidatePool.free(it) }
candidates.clear()
currentApplicability = applicability
}
if (applicability == currentApplicability) {
candidates.add(candidate)
candidates.add(candidate.pooledCandidate)
groupNumbers.add(group)
}
@@ -897,7 +988,7 @@ open class CandidateCollector(val components: InferenceComponents) {
fun bestCandidates(): List<Candidate> {
if (groupNumbers.isEmpty()) return emptyList()
if (groupNumbers.size == 1) return candidates
//if (groupNumbers.size == 1) return listOf(Candidate(candidates.first()))
val result = mutableListOf<Candidate>()
var bestGroup = groupNumbers.first()
for ((index, candidate) in candidates.withIndex()) {
@@ -907,7 +998,7 @@ open class CandidateCollector(val components: InferenceComponents) {
result.clear()
}
if (bestGroup == group) {
result.add(candidate)
result.add(Candidate(candidate))
}
}
return result
@@ -918,11 +1009,13 @@ open class CandidateCollector(val components: InferenceComponents) {
}
}
class InvokeCandidateCollector(
// Collects properties that potentially could be invoke receivers, like 'propertyName()',
// and initiates further invoke resolution by adding property-bound invoke consumers
class InvokeReceiverCandidateCollector(
val callResolver: CallResolver,
val invokeCallInfo: CallInfo,
components: InferenceComponents,
val multiplexer: MultiplexerTowerDataConsumer
val invokeConsumer: AccumulatingTowerDataConsumer
) : CandidateCollector(components) {
override fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
val applicability = super.consumeCandidate(group, candidate)
@@ -949,10 +1042,13 @@ class InvokeCandidateCollector(
invokeCallInfo.container,
invokeCallInfo.typeProvider
)
val invokeConsumer =
createSimpleFunctionConsumer(session, Name.identifier("invoke"), boundInvokeCallInfo, components, callResolver.collector)
multiplexer.addConsumer(invokeConsumer)
invokeConsumer.addConsumer(
createSimpleFunctionConsumer(
session, OperatorNameConventions.INVOKE,
boundInvokeCallInfo, components, callResolver.collector
)
)
}
return applicability

View File

@@ -33,9 +33,17 @@ class CandidateFactory(
implicitExtensionReceiverValue: ImplicitReceiverValue?,
explicitReceiverKind: ExplicitReceiverKind
): Candidate {
return Candidate(
symbol, dispatchReceiverValue, implicitExtensionReceiverValue,
explicitReceiverKind, inferenceComponents, baseSystem, callInfo
inferenceComponents.candidatePool.new().also {
it.symbol = symbol
it.dispatchReceiverValue = dispatchReceiverValue
it.implicitExtensionReceiverValue = implicitExtensionReceiverValue
it.explicitReceiverKind = explicitReceiverKind
it.inferenceComponents = inferenceComponents
it.baseSystem = baseSystem
it.callInfo = callInfo
}
)
}
}

View File

@@ -82,7 +82,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext,
}
override fun newBaseTypeCheckerContext(errorTypesEqualToAnything: Boolean): AbstractTypeCheckerContext {
return ConeTypeCheckerContext(errorTypesEqualToAnything, session)
return ConeTypeCheckerContext(errorTypesEqualToAnything, session, correspondingSupertypesCache)
}
override fun KotlinTypeMarker.canHaveUndefinedNullability(): Boolean {
@@ -248,6 +248,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext,
}
override fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): TypeSubstitutorMarker {
if (map.isEmpty()) return ConeSubstitutor.Empty
return object : AbstractConeSubstitutor(),
TypeSubstitutorMarker {
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {

View File

@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.resolve.constructType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.invoke
@@ -92,7 +92,7 @@ fun createToFreshVariableSubstitutorAndAddInitialConstraints(
val freshTypeVariables = typeParameters.map { TypeParameterBasedTypeVariable(it.symbol) }
val toFreshVariables = ConeSubstitutorByMap(freshTypeVariables.associate { it.typeParameterSymbol to it.defaultType })
val toFreshVariables = substitutorByMap(freshTypeVariables.associate { it.typeParameterSymbol to it.defaultType })
for (freshVariable in freshTypeVariables) {
csBuilder.registerVariable(freshVariable)

View File

@@ -7,8 +7,12 @@ package org.jetbrains.kotlin.fir.resolve.calls
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
import org.jetbrains.kotlin.name.Name
class FirNamedReferenceWithCandidate(session: FirSession, psi: PsiElement?, name: Name, val candidate: Candidate) :
FirResolvedCallableReferenceImpl(session, psi, name, candidate.symbol)
FirSimpleNamedReference(session, psi, name) {
override val candidateSymbol: ConeSymbol
get() = candidate.symbol
}

View File

@@ -57,7 +57,8 @@ class InferenceComponents(
val ctx: TypeSystemInferenceExtensionContextDelegate,
val session: FirSession,
val returnTypeCalculator: ReturnTypeCalculator,
val scopeSession: ScopeSession
val scopeSession: ScopeSession,
val candidatePool: CandidatePool
) {
private val approximator = object : AbstractTypeApproximator(ctx) {
override fun createErrorType(message: String): SimpleTypeMarker {

View File

@@ -7,9 +7,11 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirNamedFunction
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.arrayElementType
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.resolve.OverloadabilitySpecificityCallbacks
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
@@ -60,7 +62,7 @@ class ConeOverloadConflictResolver(
return FlatSignature(
call,
constructor.typeParameters.map { it.symbol },
call.argumentMapping!!.map { it.value.returnTypeRef.coneTypeUnsafe() },
call.argumentMapping!!.map { it.value.argumentType() },
//constructor.receiverTypeRef != null,
false,
constructor.valueParameters.any { it.isVararg },
@@ -70,12 +72,18 @@ class ConeOverloadConflictResolver(
)
}
private fun FirValueParameter.argumentType(): ConeKotlinType {
val type = returnTypeRef.coneTypeUnsafe<ConeKotlinType>()
if (isVararg) return type.arrayElementType(inferenceComponents.session)!!
return type
}
private fun createFlatSignature(call: Candidate, function: FirNamedFunction): FlatSignature<Candidate> {
return FlatSignature(
call,
function.typeParameters.map { it.symbol },
listOfNotNull<ConeKotlinType>(function.receiverTypeRef?.coneTypeUnsafe()) +
call.argumentMapping!!.map { it.value.returnTypeRef.coneTypeUnsafe() },
call.argumentMapping!!.map { it.value.argumentType() },
function.receiverTypeRef != null,
function.valueParameters.any { it.isVararg },
function.valueParameters.count { it.defaultValue != null },
@@ -211,7 +219,7 @@ class ConeSimpleConstraintSystemImpl(val system: NewConstraintSystemImpl) : Simp
it to variable.defaultType
}
val substitutor = ConeSubstitutorByMap(substitutionMap.cast())
val substitutor = substitutorByMap(substitutionMap.cast())
for (typeParameter in typeParameters) {
require(typeParameter is FirTypeParameterSymbol)
for (upperBound in typeParameter.fir.bounds) {

View File

@@ -103,7 +103,7 @@ internal sealed class CheckReceivers : ResolutionStage() {
resolveArgumentExpression(
candidate.csBuilder,
argument = explicitReceiverExpression,
expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverParameterValue.type),
expectedType = candidate.substitutor!!.substituteOrSelf(expectedReceiverParameterValue.type),
expectedTypeRef = explicitReceiverExpression.typeRef,
sink = sink,
isReceiver = true,
@@ -118,7 +118,7 @@ internal sealed class CheckReceivers : ResolutionStage() {
resolvePlainArgumentType(
candidate.csBuilder,
argumentType = argumentExtensionReceiverValue.type,
expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverParameterValue.type),
expectedType = candidate.substitutor!!.substituteOrSelf(expectedReceiverParameterValue.type),
sink = sink,
isReceiver = true,
isSafeCall = callInfo.isSafeCall

View File

@@ -29,23 +29,21 @@ class FirDependenciesSymbolProviderImpl(val session: FirSession) : AbstractFirSy
}
override fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List<FirCallableSymbol<*>> {
return topLevelCallableCache.lookupCacheOrCalculate(CallableId(packageFqName, null, name)) {
dependencyProviders.flatMap { provider -> provider.getTopLevelCallableSymbols(packageFqName, name) }
} ?: emptyList()
return dependencyProviders.flatMap { provider -> provider.getTopLevelCallableSymbols(packageFqName, name) }
}
override fun getClassDeclaredMemberScope(classId: ClassId) =
dependencyProviders.firstNotNullResult { it.getClassDeclaredMemberScope(classId) }
override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? {
return classCache.lookupCacheOrCalculate(classId) {
for (provider in dependencyProviders) {
provider.getClassLikeSymbolByFqName(classId)?.let {
return@lookupCacheOrCalculate it
}
for (provider in dependencyProviders) {
provider.getClassLikeSymbolByFqName(classId)?.let {
return it
}
null
}
return null
}
override fun getClassUseSiteMemberScope(
@@ -57,14 +55,12 @@ class FirDependenciesSymbolProviderImpl(val session: FirSession) : AbstractFirSy
}
override fun getPackage(fqName: FqName): FqName? {
return packageCache.lookupCacheOrCalculate(fqName) {
for (provider in dependencyProviders) {
provider.getPackage(fqName)?.let {
return@lookupCacheOrCalculate it
}
for (provider in dependencyProviders) {
provider.getPackage(fqName)?.let {
return it
}
null
}
return null
}
override fun getAllCallableNamesInPackage(fqName: FqName): Set<Name> {

View File

@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.*
import org.jetbrains.kotlin.fir.deserialization.FirBuiltinAnnotationDeserializer
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
import org.jetbrains.kotlin.fir.concurrent.TransactionalCache
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScope
@@ -39,9 +40,10 @@ import org.jetbrains.kotlin.serialization.deserialization.ProtoBasedClassDataFin
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.serialization.deserialization.getName
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import java.io.InputStream
import java.util.concurrent.ConcurrentHashMap
class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider() {
private class BuiltInsPackageFragment(stream: InputStream, val fqName: FqName, val session: FirSession) {
@@ -74,7 +76,7 @@ class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider(
).memberDeserializer
}
val lookup = mutableMapOf<ClassId, FirClassSymbol>()
val classCache = TransactionalCache<ClassId, FirClassSymbol>()
fun getClassLikeSymbolByFqName(classId: ClassId): FirClassSymbol? =
findAndDeserializeClass(classId)
@@ -93,7 +95,7 @@ class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider(
return null
}
}
return lookup.getOrPut(classId, { FirClassSymbol(classId) }) { symbol ->
return classCache.lookup(classId, { FirClassSymbol(classId) }) { symbol ->
if (shouldBeEnumEntry) {
FirEnumEntryImpl(session, null, symbol, classId.shortClassName)
} else {
@@ -152,7 +154,7 @@ class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider(
private val allPackageFragments = loadBuiltIns().groupBy { it.fqName }
private val fictitiousFunctionSymbols = mutableMapOf<Int, FirClassSymbol>()
private val fictitiousFunctionSymbols = ConcurrentHashMap<Int, FirClassSymbol>()
override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassSymbol? {
return allPackageFragments[classId.packageFqName]?.firstNotNullResult {
@@ -162,7 +164,7 @@ class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider(
val kind = FunctionClassDescriptor.Kind.byClassNamePrefix(packageFqName, className) ?: return@with null
val prefix = kind.classNamePrefix
val arity = className.substring(prefix.length).toIntOrNull() ?: return null
fictitiousFunctionSymbols.getOrPut(arity) {
fictitiousFunctionSymbols.computeIfAbsent(arity) {
FirClassSymbol(this).apply {
FirClassImpl(
session,
@@ -199,7 +201,7 @@ class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider(
false
)
)
val name = Name.identifier("invoke")
val name = OperatorNameConventions.INVOKE
addDeclaration(
FirMemberFunctionImpl(
session,

View File

@@ -13,11 +13,11 @@ import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
interface ConeSubstitutor : TypeSubstitutorMarker {
fun substituteOrSelf(type: ConeKotlinType): ConeKotlinType
fun substituteOrNull(type: ConeKotlinType): ConeKotlinType?
abstract class ConeSubstitutor : TypeSubstitutorMarker {
abstract fun substituteOrSelf(type: ConeKotlinType): ConeKotlinType
abstract fun substituteOrNull(type: ConeKotlinType): ConeKotlinType?
object Empty : ConeSubstitutor {
object Empty : ConeSubstitutor() {
override fun substituteOrSelf(type: ConeKotlinType): ConeKotlinType {
return type
}
@@ -33,7 +33,7 @@ fun ConeSubstitutor.substituteOrNull(type: ConeKotlinType?): ConeKotlinType? {
return type?.let { substituteOrNull(it) }
}
abstract class AbstractConeSubstitutor : ConeSubstitutor {
abstract class AbstractConeSubstitutor : ConeSubstitutor() {
private fun wrapProjection(old: ConeKotlinTypeProjection, newType: ConeKotlinType): ConeKotlinTypeProjection {
return when (old) {
is ConeStarProjection -> old
@@ -130,6 +130,11 @@ abstract class AbstractConeSubstitutor : ConeSubstitutor {
}
fun substitutorByMap(substitution: Map<ConeTypeParameterSymbol, ConeKotlinType>): ConeSubstitutor {
if (substitution.isEmpty()) return ConeSubstitutor.Empty
return ConeSubstitutorByMap(substitution)
}
class ConeSubstitutorByMap(val substitution: Map<ConeTypeParameterSymbol, ConeKotlinType>) : AbstractConeSubstitutor() {
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {

View File

@@ -12,9 +12,10 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedQualifierImpl
import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.references.FirBackingFieldReferenceImpl
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.*
@@ -25,8 +26,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.scopes.impl.FirTopLevelDeclaredMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
@@ -74,11 +74,6 @@ open class FirBodyResolveTransformer(
private var primaryConstructorParametersScope: FirLocalScope? = null
override fun transformConstructor(constructor: FirConstructor, data: Any?): CompositeTransformResult<FirDeclaration> {
if (constructor.isPrimary) {
primaryConstructorParametersScope = FirLocalScope().apply {
constructor.valueParameters.forEach { this.storeDeclaration(it) }
}
}
if (implicitTypeOnly) return constructor.compose()
return super.transformConstructor(constructor, data)
}
@@ -131,6 +126,12 @@ open class FirBodyResolveTransformer(
scopes.addIfNotNull(symbolProvider.getClassUseSiteMemberScope(companionObject.classId, session, scopeSession))
}
val result = withLabelAndReceiverType(regularClass.name, regularClass, type) {
val constructor = regularClass.declarations.firstOrNull() as? FirConstructor
if (constructor?.isPrimary == true) {
primaryConstructorParametersScope = FirLocalScope().apply {
constructor.valueParameters.forEach { this.storeDeclaration(it) }
}
}
super.transformRegularClass(regularClass, data)
}
primaryConstructorParametersScope = oldConstructorScope
@@ -200,39 +201,51 @@ open class FirBodyResolveTransformer(
access.resultType = typeFromCallee(access)
}
private fun typeFromSymbol(symbol: ConeSymbol, makeNullable: Boolean): FirResolvedTypeRef {
return when (symbol) {
is FirCallableSymbol<*> -> {
val returnType = jump.tryCalculateReturnType(symbol.fir)
if (makeNullable) {
returnType.withReplacedConeType(
session,
returnType.coneTypeUnsafe<ConeKotlinType>().withNullability(ConeNullability.NULLABLE)
)
} else {
returnType
}
}
is ConeClassifierSymbol -> {
val fir = (symbol as? FirBasedSymbol<*>)?.fir
// TODO: unhack
if (fir is FirEnumEntry) {
(fir.superTypeRefs.firstOrNull() as? FirResolvedTypeRef) ?: FirErrorTypeRefImpl(
session,
null,
"no enum item supertype"
)
} else
FirResolvedTypeRefImpl(
session, null, symbol.constructType(emptyArray(), isNullable = false),
annotations = emptyList()
)
}
else -> error("WTF ! $symbol")
}
}
private fun <T> typeFromCallee(access: T): FirResolvedTypeRef where T : FirQualifiedAccess {
val makeNullable: Boolean by lazy {
access.safe && access.explicitReceiver!!.resultType.coneTypeUnsafe<ConeKotlinType>().isNullable
}
return when (val newCallee = access.calleeReference) {
is FirErrorNamedReference ->
FirErrorTypeRefImpl(session, access.psi, newCallee.errorReason)
is FirNamedReferenceWithCandidate -> {
typeFromSymbol(newCallee.candidateSymbol, makeNullable)
}
is FirResolvedCallableReference -> {
val symbol = newCallee.coneSymbol
if (symbol is FirCallableSymbol<*>) {
val returnType = jump.tryCalculateReturnType(symbol.fir)
if (access.safe && access.explicitReceiver!!.resultType.coneTypeUnsafe<ConeKotlinType>().isNullable) {
returnType.withReplacedConeType(
session,
returnType.coneTypeUnsafe<ConeKotlinType>().withNullability(ConeNullability.NULLABLE)
)
} else {
returnType
}
} else if (symbol is ConeClassifierSymbol && symbol is FirBasedSymbol<*>) {
val fir = symbol.fir
// TODO: unhack
if (fir is FirEnumEntry) {
(fir.superTypeRefs.firstOrNull() as? FirResolvedTypeRef) ?: FirErrorTypeRefImpl(
session,
null,
"no enum item supertype"
)
} else
FirResolvedTypeRefImpl(
session, null, symbol.constructType(emptyArray(), isNullable = false),
annotations = emptyList()
)
} else {
error("WTF ! $symbol")
}
typeFromSymbol(newCallee.coneSymbol, makeNullable)
}
is FirThisReference -> {
val labelName = newCallee.labelName
@@ -329,17 +342,17 @@ open class FirBodyResolveTransformer(
file,
container!!
) { it.resultType }
val resolver = CallResolver(jump, inferenceComponents)
resolver.callInfo = info
resolver.scopes = (scopes + localScopes).asReversed()
callResolver.reset()
callResolver.callInfo = info
callResolver.scopes = (scopes + localScopes).asReversed()
val consumer = createVariableAndObjectConsumer(
session,
callee.name,
info, inferenceComponents,
resolver.collector
callResolver.collector
)
val result = resolver.runTowerResolver(consumer, implicitReceiverStack.asReversed())
val result = callResolver.runTowerResolver(consumer, implicitReceiverStack.asReversed())
val candidates = result.bestCandidates()
val nameReference = createResolvedNamedReference(
@@ -354,12 +367,14 @@ open class FirBodyResolveTransformer(
tryResolveAsQualifier()?.let { return it }
}
if (nameReference is FirResolvedCallableReference) {
val symbol = nameReference.coneSymbol as? ConeClassLikeSymbol
if (symbol != null) {
return FirResolvedQualifierImpl(session, nameReference.psi, symbol.classId).apply {
resultType = typeForQualifier(this)
}
val referencedSymbol = when (nameReference) {
is FirResolvedCallableReference -> nameReference.coneSymbol
is FirNamedReferenceWithCandidate -> nameReference.candidateSymbol
else -> null
}
if (referencedSymbol is ConeClassLikeSymbol) {
return FirResolvedQualifierImpl(session, nameReference.psi, referencedSymbol.classId).apply {
resultType = typeForQualifier(this)
}
}
@@ -385,6 +400,7 @@ open class FirBodyResolveTransformer(
val types = if (labelName == null) labels.values() else labels[Name.identifier(labelName)]
val type = types.lastOrNull() ?: ConeKotlinErrorType("Unresolved this@$labelName")
qualifiedAccessExpression.resultType = FirResolvedTypeRefImpl(session, null, type, emptyList())
return qualifiedAccessExpression.compose()
}
is FirSuperReference -> {
if (callee.superTypeRef is FirResolvedTypeRef) {
@@ -396,14 +412,23 @@ open class FirBodyResolveTransformer(
qualifiedAccessExpression.resultType = superTypeRef
callee.replaceSuperTypeRef(superTypeRef)
}
return qualifiedAccessExpression.compose()
}
is FirResolvedCallableReference -> {
if (qualifiedAccessExpression.typeRef !is FirResolvedTypeRef) {
storeTypeFromCallee(qualifiedAccessExpression)
}
return qualifiedAccessExpression.compose()
}
}
return transformCallee(qualifiedAccessExpression).compose()
val transformedCallee = transformCallee(qualifiedAccessExpression)
// NB: here we can get raw expression because of dropped qualifiers (see transform callee),
// so candidate existence must be checked before calling completion
return if (transformedCallee is FirQualifiedAccessExpression && transformedCallee.candidate() != null) {
completeTypeInference(transformedCallee, data as? FirTypeRef).compose()
} else {
transformedCallee.compose()
}
}
override fun transformVariableAssignment(
@@ -522,7 +547,11 @@ open class FirBodyResolveTransformer(
}
private val noExpectedType = FirImplicitTypeRefImpl(session, null)
private val inferenceComponents = inferenceComponents(session, jump, scopeSession)
private val pool = CandidatePool()
private val inferenceComponents = inferenceComponents(session, jump, scopeSession, pool)
private val callResolver = CallResolver(jump, inferenceComponents)
private val conflictResolver = ConeOverloadConflictResolver(TypeSpecificityComparator.NONE, inferenceComponents)
val completer = ConstraintSystemCompleter(inferenceComponents)
private fun resolveCallAndSelectCandidate(functionCall: FirFunctionCall, expectedTypeRef: FirTypeRef?): FirFunctionCall {
@@ -548,19 +577,19 @@ open class FirBodyResolveTransformer(
file,
container!!
) { it.resultType }
val resolver = CallResolver(jump, inferenceComponents)
resolver.callInfo = info
resolver.scopes = (scopes + localScopes).asReversed()
callResolver.reset()
callResolver.callInfo = info
callResolver.scopes = (scopes + localScopes).asReversed()
val consumer = createFunctionConsumer(session, name, info, inferenceComponents, resolver.collector, resolver)
val result = resolver.runTowerResolver(consumer, implicitReceiverStack.asReversed())
val bestCandidates = result.bestCandidates()
val consumer = createFunctionConsumer(session, name, info, inferenceComponents, callResolver.collector, callResolver)
val result = callResolver.runTowerResolver(consumer, implicitReceiverStack.asReversed())
val bestCandidates = result.bestCandidates().toSet()
val reducedCandidates = if (result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED) {
bestCandidates.toSet()
bestCandidates
} else {
ConeOverloadConflictResolver(TypeSpecificityComparator.NONE, inferenceComponents)
.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = false)
conflictResolver.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = false)
}
(bestCandidates - reducedCandidates).forEach { pool.free(it.pooledCandidate) }
// fun isInvoke()
@@ -628,7 +657,7 @@ open class FirBodyResolveTransformer(
return qualifiedAccess
}
val candidate = qualifiedAccess.candidate() ?: return qualifiedAccess
val initialSubstitutor = candidate.substitutor
val initialSubstitutor = candidate.substitutor!!
val initialType = initialSubstitutor.substituteOrSelf(typeRef.type)
@@ -637,7 +666,7 @@ open class FirBodyResolveTransformer(
}
val completionMode = candidate.computeCompletionMode(inferenceComponents, expectedTypeRef, initialType)
val completer = ConstraintSystemCompleter(inferenceComponents)
val replacements = mutableMapOf<FirExpression, FirExpression>()
val analyzer = PostponedArgumentsAnalyzer(object : LambdaAnalyzer {
@@ -695,14 +724,14 @@ open class FirBodyResolveTransformer(
)
}
qualifiedAccess.transformChildren(ReplaceInArguments, replacements.toMap())
qualifiedAccess.transformChildren(MapArguments, replacements.toMap())
if (completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL) {
val finalSubstitutor =
candidate.system.asReadOnlyStorage().buildAbstractResultingSubstitutor(inferenceComponents.ctx) as ConeSubstitutor
return qualifiedAccess.transformSingle(
FirCallCompleterTransformer(session, finalSubstitutor, jump),
FirCallCompleterTransformer(session, finalSubstitutor, pool, jump),
null
)
}
@@ -733,7 +762,13 @@ open class FirBodyResolveTransformer(
val expectedTypeRef = data as FirTypeRef?
val completeInference =
try {
val initialExplicitReceiver = functionCall.explicitReceiver
val resultExpression = resolveCallAndSelectCandidate(functionCall, expectedTypeRef)
val resultExplicitReceiver = resultExpression.explicitReceiver
if (initialExplicitReceiver !== resultExplicitReceiver && resultExplicitReceiver is FirQualifiedAccess) {
// name.invoke() case
completeTypeInference(resultExplicitReceiver, null)
}
completeTypeInference(resultExpression, expectedTypeRef)
} catch (e: Throwable) {
throw RuntimeException("While resolving call ${functionCall.render()}", e)
@@ -773,10 +808,13 @@ open class FirBodyResolveTransformer(
}
candidates.size == 1 -> {
val candidate = candidates.single()
if (candidate.symbol is FirBackingFieldSymbol) {
FirBackingFieldReferenceImpl(firSession, psi, candidate.symbol)
} else {
FirNamedReferenceWithCandidate(firSession, psi, name, candidate)
val coneSymbol = candidate.symbol
when {
coneSymbol is FirBackingFieldSymbol -> FirBackingFieldReferenceImpl(firSession, psi, coneSymbol)
coneSymbol is FirVariableSymbol &&
(coneSymbol !is FirPropertySymbol || coneSymbol.firUnsafe<FirMemberDeclaration>().typeParameters.isEmpty()) ->
FirResolvedCallableReferenceImpl(firSession, psi, name, coneSymbol)
else -> FirNamedReferenceWithCandidate(firSession, psi, name, candidate)
}
}
else -> FirErrorNamedReference(
@@ -987,15 +1025,18 @@ open class FirBodyResolveTransformer(
)
}
variable.delegate != null -> {
// TODO: type from delegate
variable.transformReturnTypeRef(
this,
FirErrorTypeRefImpl(
session,
null,
"Not supported: type from delegate"
val fakeInitializer = FirFunctionCallImpl(session, null).apply {
explicitReceiver = variable.delegate
calleeReference = FirSimpleNamedReference(this@FirBodyResolveTransformer.session, null, GET_VALUE)
arguments += FirConstExpressionImpl(this@FirBodyResolveTransformer.session, null, IrConstKind.Null, null)
arguments += FirThrowExpressionImpl(
this@FirBodyResolveTransformer.session, null,
FirConstExpressionImpl(this@FirBodyResolveTransformer.session, null, IrConstKind.Null, null)
)
)
}
val result = transformFunctionCall(fakeInitializer, variable.returnTypeRef).single as FirFunctionCall
variable.replaceDelegate(result.explicitReceiver)
variable.transformReturnTypeRef(this, result.typeRef)
}
variable is FirProperty && variable.getter !is FirDefaultPropertyAccessor -> {
variable.transformReturnTypeRef(
@@ -1034,11 +1075,14 @@ open class FirBodyResolveTransformer(
override fun transformProperty(property: FirProperty, data: Any?): CompositeTransformResult<FirDeclaration> {
val returnTypeRef = property.returnTypeRef
if (returnTypeRef !is FirImplicitTypeRef && implicitTypeOnly) return property.compose()
if (returnTypeRef is FirImplicitTypeRef) {
property.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef)
}
return withScopeCleanup(localScopes) {
localScopes.addIfNotNull(primaryConstructorParametersScope)
withContainer(property) {
property.transformChildrenWithoutAccessors(this, returnTypeRef)
if (property.returnTypeRef is FirImplicitTypeRef && property.initializer != null) {
if (property.initializer != null || property.delegate != null) {
storeVariableReturnType(property)
}
withScopeCleanup(localScopes) {
@@ -1107,9 +1151,18 @@ open class FirBodyResolveTransformer(
)
return transformedGetClassCall.compose()
}
companion object {
private val GET_VALUE = Name.identifier("getValue")
}
}
private fun inferenceComponents(session: FirSession, jump: ReturnTypeCalculatorWithJump, scopeSession: ScopeSession) =
private fun inferenceComponents(
session: FirSession,
jump: ReturnTypeCalculatorWithJump,
scopeSession: ScopeSession,
candidatePool: CandidatePool
) =
InferenceComponents(object : ConeInferenceContext, TypeSystemInferenceExtensionContextDelegate {
override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker? {
//TODO wtf
@@ -1120,34 +1173,22 @@ private fun inferenceComponents(session: FirSession, jump: ReturnTypeCalculatorW
TODO("not implemented")
}
override val correspondingSupertypesCache = FirCorrespondingSupertypesCache(session)
override val session: FirSession
get() = session
override fun KotlinTypeMarker.removeExactAnnotation(): KotlinTypeMarker {
return this
}
}, session, jump, scopeSession)
}, session, jump, scopeSession, candidatePool)
class ReturnTypeCalculatorWithJump(val session: FirSession, val scopeSession: ScopeSession) : ReturnTypeCalculator {
val storeType = object : FirTransformer<FirTypeRef>() {
override fun <E : FirElement> transformElement(element: E, data: FirTypeRef): CompositeTransformResult<E> {
return element.compose()
}
override fun transformImplicitTypeRef(
implicitTypeRef: FirImplicitTypeRef,
data: FirTypeRef
): CompositeTransformResult<FirTypeRef> {
return data.compose()
}
}
private fun cycleErrorType(declaration: FirTypedDeclaration): FirResolvedTypeRef? {
if (declaration.returnTypeRef is FirComputingImplicitTypeRef) {
declaration.transformReturnTypeRef(storeType, FirErrorTypeRefImpl(session, null, "cycle"))
declaration.transformReturnTypeRef(TransformImplicitType, FirErrorTypeRefImpl(session, null, "cycle"))
return declaration.returnTypeRef as FirResolvedTypeRef
}
return null
@@ -1157,7 +1198,7 @@ class ReturnTypeCalculatorWithJump(val session: FirSession, val scopeSession: Sc
if (declaration is FirValueParameter && declaration.returnTypeRef is FirImplicitTypeRef) {
// TODO?
declaration.transformReturnTypeRef(storeType, FirErrorTypeRefImpl(session, null, "Unsupported: implicit VP type"))
declaration.transformReturnTypeRef(TransformImplicitType, FirErrorTypeRefImpl(session, null, "Unsupported: implicit VP type"))
}
val returnTypeRef = declaration.returnTypeRef
if (returnTypeRef is FirResolvedTypeRef) return returnTypeRef
@@ -1182,11 +1223,11 @@ class ReturnTypeCalculatorWithJump(val session: FirSession, val scopeSession: Sc
"I don't know what todo"
)
declaration.transformReturnTypeRef(storeType, FirComputingImplicitTypeRef)
declaration.transformReturnTypeRef(TransformImplicitType, FirComputingImplicitTypeRef)
val transformer = FirDesignatedBodyResolveTransformer(
(listOf(file) + outerClasses.filterNotNull().asReversed() + listOf(declaration)).iterator(),
file.session,
file.fileSession,
scopeSession
)
@@ -1195,7 +1236,9 @@ class ReturnTypeCalculatorWithJump(val session: FirSession, val scopeSession: Sc
val newReturnTypeRef = declaration.returnTypeRef
cycleErrorType(declaration)?.let { return it }
require(newReturnTypeRef is FirResolvedTypeRef) { declaration.render() }
require(newReturnTypeRef is FirResolvedTypeRef) {
declaration.render()
}
return newReturnTypeRef
}
}
@@ -1215,26 +1258,28 @@ class FirDesignatedBodyResolveTransformer(val designation: Iterator<FirElement>,
@Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")"))
class FirImplicitTypeBodyResolveTransformerAdapter : FirTransformer<Nothing?>() {
class FirImplicitTypeBodyResolveTransformerAdapter(session: FirSession) : FirTransformer<Nothing?>() {
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
return element.compose()
}
val transformer = FirBodyResolveTransformer(session, implicitTypeOnly = true)
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
val transformer = FirBodyResolveTransformer(file.session, implicitTypeOnly = true)
return file.transform(transformer, null)
}
}
@Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")"))
class FirBodyResolveTransformerAdapter : FirTransformer<Nothing?>() {
class FirBodyResolveTransformerAdapter(session: FirSession) : FirTransformer<Nothing?>() {
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
return element.compose()
}
val transformer = FirBodyResolveTransformer(session, implicitTypeOnly = false)
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
val transformer = FirBodyResolveTransformer(file.session, implicitTypeOnly = false)
return file.transform(transformer, null)
}
}
@@ -1261,57 +1306,4 @@ interface ReturnTypeCalculator {
fun tryCalculateReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef
}
private object StoreNameReference : FirTransformer<FirNamedReference>() {
override fun <E : FirElement> transformElement(element: E, data: FirNamedReference): CompositeTransformResult<E> {
return element.compose()
}
override fun transformNamedReference(
namedReference: FirNamedReference,
data: FirNamedReference
): CompositeTransformResult<FirNamedReference> {
return data.compose()
}
}
internal object StoreType : FirTransformer<FirTypeRef>() {
override fun <E : FirElement> transformElement(element: E, data: FirTypeRef): CompositeTransformResult<E> {
return element.compose()
}
override fun transformTypeRef(typeRef: FirTypeRef, data: FirTypeRef): CompositeTransformResult<FirTypeRef> {
return data.compose()
}
}
internal object StoreExplicitReceiver : FirTransformer<FirExpression>() {
override fun <E : FirElement> transformElement(element: E, data: FirExpression): CompositeTransformResult<E> {
return element.compose()
}
override fun transformExpression(expression: FirExpression, data: FirExpression): CompositeTransformResult<FirStatement> {
return data.compose()
}
}
private object ReplaceInArguments : FirTransformer<Map<FirElement, FirElement>>() {
override fun <E : FirElement> transformElement(element: E, data: Map<FirElement, FirElement>): CompositeTransformResult<E> {
return ((data[element] ?: element) as E).compose()
}
override fun transformFunctionCall(
functionCall: FirFunctionCall,
data: Map<FirElement, FirElement>
): CompositeTransformResult<FirStatement> {
return (functionCall.transformChildren(this, data) as FirStatement).compose()
}
override fun transformWrappedArgumentExpression(
wrappedArgumentExpression: FirWrappedArgumentExpression,
data: Map<FirElement, FirElement>
): CompositeTransformResult<FirStatement> {
return (wrappedArgumentExpression.transformChildren(this, data) as FirStatement).compose()
}
}

View File

@@ -10,9 +10,11 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.resolve.calls.CandidatePool
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.constructFunctionalTypeRef
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
@@ -27,25 +29,43 @@ import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.types.Variance
object StoreCalleeReference : FirTransformer<FirResolvedCallableReference>() {
override fun <E : FirElement> transformElement(element: E, data: FirResolvedCallableReference): CompositeTransformResult<E> {
return element.compose()
}
override fun transformResolvedCallableReference(
resolvedCallableReference: FirResolvedCallableReference,
data: FirResolvedCallableReference
): CompositeTransformResult<FirNamedReference> {
return data.compose()
}
}
class FirCallCompleterTransformer(
val session: FirSession,
private val finalSubstitutor: ConeSubstitutor,
private val candidatePool: CandidatePool,
private val typeCalculator: ReturnTypeCalculator
) : FirAbstractTreeTransformer() {
override fun transformQualifiedAccessExpression(
qualifiedAccessExpression: FirQualifiedAccessExpression,
data: Nothing?
): CompositeTransformResult<FirStatement> {
val calleeReference =
qualifiedAccessExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return qualifiedAccessExpression.compose()
val candidate = calleeReference.candidate
val typeRef = typeCalculator.tryCalculateReturnType(calleeReference.candidateSymbol.firUnsafe())
val initialType = candidate.substitutor!!.substituteOrNull(typeRef.type)
val finalType = finalSubstitutor.substituteOrNull(initialType)
val resultType = typeRef.withReplacedConeType(session, finalType)
qualifiedAccessExpression.replaceTypeRef(resultType)
return qualifiedAccessExpression.transformCalleeReference(
StoreCalleeReference,
FirResolvedCallableReferenceImpl(
calleeReference.session,
calleeReference.psi,
calleeReference.name,
calleeReference.candidateSymbol
)
).compose().also {
candidatePool.free(calleeReference.candidate.pooledCandidate)
}
}
override fun transformVariableAssignment(
variableAssignment: FirVariableAssignment,
data: Nothing?
@@ -58,9 +78,11 @@ class FirCallCompleterTransformer(
calleeReference.session,
calleeReference.psi,
calleeReference.name,
calleeReference.coneSymbol
calleeReference.candidateSymbol
)
).compose()
).compose().also {
candidatePool.free(calleeReference.candidate.pooledCandidate)
}
}
override fun transformFunctionCall(functionCall: FirFunctionCall, data: Nothing?): CompositeTransformResult<FirStatement> {
@@ -70,7 +92,7 @@ class FirCallCompleterTransformer(
val subCandidate = calleeReference.candidate
val declaration = subCandidate.symbol.firUnsafe<FirCallableMemberDeclaration<*>>()
val newTypeParameters = declaration.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }
.map { subCandidate.substitutor.substituteOrSelf(it) }
.map { subCandidate.substitutor!!.substituteOrSelf(it) }
.map { finalSubstitutor.substituteOrSelf(it) }
.mapIndexed { index, type ->
when (val argument = functionCall.typeArguments.getOrNull(index)) {
@@ -96,7 +118,7 @@ class FirCallCompleterTransformer(
val typeRef = typeCalculator.tryCalculateReturnType(declaration)
val initialType = subCandidate.substitutor.substituteOrNull(typeRef.type)
val initialType = subCandidate.substitutor!!.substituteOrNull(typeRef.type)
val finalType = finalSubstitutor.substituteOrNull(initialType)
val resultType = typeRef.withReplacedConeType(session, finalType)
@@ -108,9 +130,11 @@ class FirCallCompleterTransformer(
calleeReference.session,
calleeReference.psi,
calleeReference.name,
calleeReference.coneSymbol
calleeReference.candidateSymbol
)
).compose()
).compose().also {
candidatePool.free(calleeReference.candidate.pooledCandidate)
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.visitors.FirTransformer
class FirStagesTransformerFactory(session: FirSession) {
val resolveStages: List<FirResolveStage> = listOf(
ImportResolveStage,
SuperTypeResolveStage,
TypeResolveStage,
StatusResolveStage,
ImplicitTypeBodyResolveStage(session),
BodyResolveStage(session)
)
val stageCount = resolveStages.size
fun createStageTransformer(stage: Int): FirTransformer<Nothing?> {
return resolveStages[stage].createTransformer()
}
fun processFiles(files: List<FirFile>) {
for (resolveStage in resolveStages) {
val transformer = resolveStage.createTransformer()
for (firFile in files) {
firFile.transform<FirFile, Nothing?>(transformer, null)
}
}
}
}
sealed class FirResolveStage() {
abstract val isParallel: Boolean
abstract fun createTransformer(): FirTransformer<Nothing?>
}
object ImportResolveStage : FirResolveStage() {
override val isParallel: Boolean
get() = true
override fun createTransformer(): FirTransformer<Nothing?> {
return FirImportResolveTransformer()
}
}
object SuperTypeResolveStage : FirResolveStage() {
override val isParallel: Boolean
get() = false
override fun createTransformer(): FirTransformer<Nothing?> {
return FirSupertypeResolverTransformer()
}
}
object TypeResolveStage : FirResolveStage() {
override val isParallel: Boolean
get() = true
override fun createTransformer(): FirTransformer<Nothing?> {
return FirTypeResolveTransformer()
}
}
object StatusResolveStage : FirResolveStage() {
override val isParallel: Boolean
get() = true
override fun createTransformer(): FirTransformer<Nothing?> {
return FirStatusResolveTransformer()
}
}
class ImplicitTypeBodyResolveStage(val session: FirSession) : FirResolveStage() {
override val isParallel: Boolean
get() = false
override fun createTransformer(): FirTransformer<Nothing?> {
return FirImplicitTypeBodyResolveTransformerAdapter(session)
}
}
class BodyResolveStage(val session: FirSession) : FirResolveStage() {
override val isParallel: Boolean
get() = true
override fun createTransformer(): FirTransformer<Nothing?> {
return FirBodyResolveTransformerAdapter(session)
}
}

View File

@@ -1,29 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.visitors.FirTransformer
class FirTotalResolveTransformer {
val transformers: List<FirTransformer<Nothing?>> = listOf(
FirImportResolveTransformer(),
FirSupertypeResolverTransformer(),
FirTypeResolveTransformer(),
FirStatusResolveTransformer(),
FirImplicitTypeBodyResolveTransformerAdapter(),
FirBodyResolveTransformerAdapter()
)
fun processFiles(files: List<FirFile>) {
for (transformer in transformers) {
for (firFile in files) {
firFile.transform<FirFile, Nothing?>(transformer, null)
}
}
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirNamedReference
import org.jetbrains.kotlin.fir.FirResolvedCallableReference
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.FirWrappedArgumentExpression
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.compose
internal object MapArguments : FirTransformer<Map<FirElement, FirElement>>() {
override fun <E : FirElement> transformElement(element: E, data: Map<FirElement, FirElement>): CompositeTransformResult<E> {
return ((data[element] ?: element) as E).compose()
}
override fun transformFunctionCall(
functionCall: FirFunctionCall,
data: Map<FirElement, FirElement>
): CompositeTransformResult<FirStatement> {
return (functionCall.transformChildren(this, data) as FirStatement).compose()
}
override fun transformWrappedArgumentExpression(
wrappedArgumentExpression: FirWrappedArgumentExpression,
data: Map<FirElement, FirElement>
): CompositeTransformResult<FirStatement> {
return (wrappedArgumentExpression.transformChildren(this, data) as FirStatement).compose()
}
}
internal object StoreType : FirTransformer<FirTypeRef>() {
override fun <E : FirElement> transformElement(element: E, data: FirTypeRef): CompositeTransformResult<E> {
return element.compose()
}
override fun transformTypeRef(typeRef: FirTypeRef, data: FirTypeRef): CompositeTransformResult<FirTypeRef> {
return data.compose()
}
}
internal object TransformImplicitType : FirTransformer<FirTypeRef>() {
override fun <E : FirElement> transformElement(element: E, data: FirTypeRef): CompositeTransformResult<E> {
return element.compose()
}
override fun transformImplicitTypeRef(
implicitTypeRef: FirImplicitTypeRef,
data: FirTypeRef
): CompositeTransformResult<FirTypeRef> {
return data.compose()
}
}
internal object StoreNameReference : FirTransformer<FirNamedReference>() {
override fun <E : FirElement> transformElement(element: E, data: FirNamedReference): CompositeTransformResult<E> {
return element.compose()
}
override fun transformNamedReference(
namedReference: FirNamedReference,
data: FirNamedReference
): CompositeTransformResult<FirNamedReference> {
return data.compose()
}
}
internal object StoreCalleeReference : FirTransformer<FirResolvedCallableReference>() {
override fun <E : FirElement> transformElement(element: E, data: FirResolvedCallableReference): CompositeTransformResult<E> {
return element.compose()
}
override fun transformNamedReference(
namedReference: FirNamedReference,
data: FirResolvedCallableReference
): CompositeTransformResult<FirNamedReference> {
return data.compose()
}
override fun transformResolvedCallableReference(
resolvedCallableReference: FirResolvedCallableReference,
data: FirResolvedCallableReference
): CompositeTransformResult<FirNamedReference> {
return data.compose()
}
}

View File

@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
@@ -38,7 +38,7 @@ abstract class AbstractFirOverrideScope(val session: FirSession) : FirScope() {
val types = self.typeParameters.map {
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
}
val substitution = ConeSubstitutorByMap(member.typeParameters.map { it.symbol }.zip(types).toMap())
val substitution = substitutorByMap(member.typeParameters.map { it.symbol }.zip(types).toMap())
if (!member.typeParameters.zip(self.typeParameters).all { (a, b) ->
a.bounds.size == b.bounds.size &&
a.bounds.zip(b.bounds).all { (aBound, bBound) -> isEqualTypes(aBound, bBound, substitution) }

View File

@@ -19,12 +19,13 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.name.Name
import java.util.concurrent.ConcurrentHashMap
class FirClassDeclaredMemberScopeProvider {
val cache = mutableMapOf<FirRegularClass, FirClassDeclaredMemberScope>()
val cache = ConcurrentHashMap<FirRegularClass, FirClassDeclaredMemberScope>()
fun declaredMemberScope(klass: FirRegularClass): FirClassDeclaredMemberScope {
return cache.getOrPut(klass) {
return cache.computeIfAbsent(klass) {
FirClassDeclaredMemberScope(klass)
}
}

View File

@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirMemberFunctionImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorWithJump
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
@@ -33,7 +33,7 @@ class FirClassSubstitutionScope(
private val fakeOverrides = mutableMapOf<FirFunctionSymbol<*>, FirFunctionSymbol<*>>()
private val substitutor = ConeSubstitutorByMap(substitution)
private val substitutor = substitutorByMap(substitution)
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
useSiteScope.processFunctionsByName(name) process@{ original ->

View File

@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.ConeTypeVariableTypeConstructor
import org.jetbrains.kotlin.fir.resolve.calls.hasNullableSuperType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.fir.symbols.*
@@ -33,6 +33,7 @@ class ErrorTypeConstructor(reason: String) : TypeConstructorMarker
interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext {
val session: FirSession
val correspondingSupertypesCache: FirCorrespondingSupertypesCache?
override fun TypeConstructorMarker.isIntegerLiteralTypeConstructor(): Boolean {
// TODO()
@@ -45,7 +46,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext {
override fun SimpleTypeMarker.fastCorrespondingSupertypes(constructor: TypeConstructorMarker): List<SimpleTypeMarker>? {
require(this is ConeKotlinType)
return session.correspondingSupertypesCache.getCorrespondingSupertypes(this, constructor)
return correspondingSupertypesCache?.getCorrespondingSupertypes(this, constructor)
}
override fun SimpleTypeMarker.isIntegerLiteralType(): Boolean {
@@ -419,7 +420,10 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext {
}
}
class ConeTypeCheckerContext(override val isErrorTypeEqualsToAnything: Boolean, override val session: FirSession) :
class ConeTypeCheckerContext(
override val isErrorTypeEqualsToAnything: Boolean, override val session: FirSession,
override val correspondingSupertypesCache: FirCorrespondingSupertypesCache?
) :
AbstractTypeCheckerContext(), ConeTypeContext {
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy {
if (type.argumentsCount() == 0) return SupertypesPolicy.LowerIfFlexible
@@ -435,7 +439,7 @@ class ConeTypeCheckerContext(override val isErrorTypeEqualsToAnything: Boolean,
parameter.symbol as ConeTypeParameterSymbol to ((argument as? ConeTypedProjection)?.type
?: StandardClassIds.Any(session.firSymbolProvider).constructType(emptyArray(), isNullable = true))
}
ConeSubstitutorByMap(substitution)
substitutorByMap(substitution)
} else {
ConeSubstitutor.Empty
}

View File

@@ -15,15 +15,20 @@ import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import org.jetbrains.kotlin.types.model.CaptureStatus
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
class FirCorrespondingSupertypesCache(private val session: FirSession) {
private val context = ConeTypeCheckerContext(false, session)
private val context = ConeTypeCheckerContext(false, session, null)
private val cache = HashMap<ConeClassLikeSymbol, Map<ConeClassLikeSymbol, List<ConeClassLikeType>>?>(1000, 0.5f)
private val lock = ReentrantLock()
fun getCorrespondingSupertypes(
type: ConeKotlinType,
supertypeConstructor: TypeConstructorMarker
): List<ConeClassLikeType>? {
if (type !is ConeClassLikeType || supertypeConstructor !is ConeClassLikeSymbol) return null
val symbol = type.lookupTag.toSymbol(session) as? ConeClassLikeSymbol ?: return null

View File

@@ -0,0 +1,3 @@
class Bar(name: () -> String) {
val name = name()
}

View File

@@ -0,0 +1,10 @@
FILE: propertyFromParameter.kt
public final class Bar : R|kotlin/Any| {
public constructor(name: R|kotlin/Function0<kotlin/String>|): R|Bar| {
super<R|kotlin/Any|>()
}
public final val name: R|kotlin/String| = R|<local>/name|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/String|>|()
public get(): R|kotlin/String|
}

View File

@@ -0,0 +1,11 @@
class Foo(name: () -> String) {
val result = run { name() }
val name = result.length
}
fun bar(name: () -> String) {
val result = run { name() }
val name = result.length
}

View File

@@ -0,0 +1,23 @@
FILE: recursiveBug.kt
public final class Foo : R|kotlin/Any| {
public constructor(name: R|kotlin/Function0<kotlin/String>|): R|Foo| {
super<R|kotlin/Any|>()
}
public final val result: R|kotlin/String| = R|kotlin/run|<R|kotlin/String|>(<L> = run@fun <anonymous>(): R|kotlin/String| {
R|<local>/name|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/String|>|()
}
)
public get(): R|kotlin/String|
public final val name: R|kotlin/Int| = R|/Foo.result|.R|kotlin/String.length|
public get(): R|kotlin/Int|
}
public final fun bar(name: R|kotlin/Function0<kotlin/String>|): R|kotlin/Unit| {
lval result: R|kotlin/String| = R|kotlin/run|<R|kotlin/String|>(<L> = run@fun <anonymous>(): R|kotlin/String| {
R|<local>/name|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/String|>|()
}
)
lval name: R|kotlin/Int| = R|<local>/result|.R|kotlin/String.length|
}

View File

@@ -0,0 +1,9 @@
//val x = lazy { "Hello" }.getValue(null, throw null)
val x by lazy { "Hello" }
fun foo() {
x.length
val y by lazy { "Bye" }
y.length
}

View File

@@ -0,0 +1,14 @@
FILE: simpleLazy.kt
public final val x: R|kotlin/String|by R|kotlin/lazy|<R|kotlin/String|>(<L> = lazy@fun <anonymous>(): R|kotlin/String| {
String(Hello)
}
)
public get(): R|kotlin/String|
public final fun foo(): R|kotlin/Unit| {
R|/x|.R|kotlin/String.length|
lval y: R|kotlin/String|by R|kotlin/lazy|<R|kotlin/String|>(<L> = lazy@fun <anonymous>(): R|kotlin/String| {
String(Bye)
}
)
R|<local>/y|.R|kotlin/String.length|
}

View File

@@ -13,7 +13,7 @@ FILE: topLevelResolve.kt
lval setAndList: R|kotlin/collections/Set<kotlin/Int>| = R|kotlin/collections/setOf|<R|kotlin/Int|>(Int(0)).R|kotlin/collections/plus|<R|kotlin/Int|>(R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(1), Int(2)))
lval stringAndList: R|kotlin/String| = String().R|kotlin/String.plus|(R|kotlin/collections/emptyList|<R|kotlin/Boolean|>())
lval map: R|kotlin/collections/Map<kotlin/String, kotlin/Int>| = R|kotlin/collections/mapOf|<R|kotlin/String|, R|kotlin/Int|>(String().R|kotlin/to|<R|kotlin/String|, R|kotlin/Int|>(Int(1)), String(.).R|kotlin/to|<R|kotlin/String|, R|kotlin/Int|>(Int(2))).R|kotlin/collections/plus|<R|kotlin/String|, R|kotlin/Int|>(String(..).R|kotlin/to|<R|kotlin/String|, R|kotlin/Int|>(Int(3)))
lval mapAndMap: <ERROR TYPE REF: Ambiguity: plus, [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]> = <Ambiguity: mapOf, [kotlin/collections/mapOf, kotlin/collections/mapOf]>#(String(-).R|kotlin/to|(Int(4))).<Ambiguity: plus, [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]>#(<Ambiguity: mapOf, [kotlin/collections/mapOf, kotlin/collections/mapOf]>#(String(_).R|kotlin/to|(Int(5))))
lval mapAndMap: R|kotlin/collections/Map<kotlin/String, kotlin/Int>| = R|kotlin/collections/mapOf|<R|kotlin/String|, R|kotlin/Int|>(String(-).R|kotlin/to|<R|kotlin/String|, R|kotlin/Int|>(Int(4))).R|kotlin/collections/plus|<R|kotlin/String|, R|kotlin/Int|>(R|kotlin/collections/mapOf|<R|kotlin/String|, R|kotlin/Int|>(String(_).R|kotlin/to|<R|kotlin/String|, R|kotlin/Int|>(Int(5))))
}
public final fun <T> id(arg: R|T|): R|T| {
^id R|<local>/arg|

View File

@@ -0,0 +1 @@
val x by lazy { 42 }

View File

@@ -0,0 +1,6 @@
FILE: typeFromDelegate.kt
public final val x: R|kotlin/Int|by R|kotlin/lazy|<R|kotlin/Int|>(<L> = lazy@fun <anonymous>(): R|kotlin/Int| {
Int(42)
}
)
public get(): R|kotlin/Int|

View File

@@ -20,13 +20,10 @@ import org.jetbrains.kotlin.fir.java.FirLibrarySession
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.FirStagesTransformerFactory
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.CommonPlatforms
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.platform.konan.KonanPlatforms
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import java.io.File
@@ -72,7 +69,7 @@ abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() {
FirJavaModuleBasedSession(info, sessionProvider, scope)
}
val firFiles = mutableListOf<FirFile>()
val firFilesPerSession = mutableMapOf<FirSession, MutableList<FirFile>>()
for ((testModule, testFilesInModule) in groupedByModule) {
val ktFiles = getKtFiles(testFilesInModule, true)
@@ -82,7 +79,8 @@ abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() {
val firBuilder = RawFirBuilder(session, false)
ktFiles.mapTo(firFiles) {
val files = firFilesPerSession.getOrPut(session) { mutableListOf() }
ktFiles.mapTo(files) {
val firFile = firBuilder.buildFirFile(it)
(session.service<FirProvider>() as FirProviderImpl).recordFile(firFile)
@@ -91,7 +89,9 @@ abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() {
}
}
doFirResolveTestBench(firFiles, FirTotalResolveTransformer().transformers, gc = false)
for ((session, files) in firFilesPerSession) {
doFirResolveTestBench(files, FirStagesTransformerFactory(session), gc = false)
}
}

View File

@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.FirStagesTransformerFactory
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils
@@ -31,7 +31,7 @@ abstract class AbstractFirResolveTestCase : AbstractFirResolveWithSessionTestCas
val builder = RawFirBuilder(session, stubMode = false)
val transformer = FirTotalResolveTransformer()
val transformer = FirStagesTransformerFactory(session)
return ktFiles.map {
val firFile = builder.buildFirFile(it)
(session.service<FirProvider>() as FirProviderImpl).recordFile(firFile)

View File

@@ -372,6 +372,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/implicitTypeOrder.kt");
}
@TestMetadata("propertyFromParameter.kt")
public void testPropertyFromParameter() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/propertyFromParameter.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/simple.kt");

View File

@@ -84,11 +84,21 @@ public class FirResolveTestCaseWithStdlibGenerated extends AbstractFirResolveTes
runTest("compiler/fir/resolve/testData/resolve/stdlib/mapList.kt");
}
@TestMetadata("recursiveBug.kt")
public void testRecursiveBug() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/recursiveBug.kt");
}
@TestMetadata("reflectionClass.kt")
public void testReflectionClass() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/reflectionClass.kt");
}
@TestMetadata("simpleLazy.kt")
public void testSimpleLazy() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/simpleLazy.kt");
}
@TestMetadata("topLevelResolve.kt")
public void testTopLevelResolve() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/topLevelResolve.kt");
@@ -99,6 +109,11 @@ public class FirResolveTestCaseWithStdlibGenerated extends AbstractFirResolveTes
runTest("compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.kt");
}
@TestMetadata("typeFromDelegate.kt")
public void testTypeFromDelegate() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/typeFromDelegate.kt");
}
@TestMetadata("unaryOperators.kt")
public void testUnaryOperators() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/unaryOperators.kt");

View File

@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.FirStagesTransformerFactory
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestJdkKind
@@ -69,7 +69,7 @@ class FirResolveTestTotalKotlin : AbstractFirResolveWithSessionTestCase() {
val session = createSession(environment, scope)
val builder = RawFirBuilder(session, stubMode = false)
val totalTransformer = FirTotalResolveTransformer()
val totalTransformer = FirStagesTransformerFactory(session)
val firFiles = ktFiles.toList().progress("Loading FIR").map {
val firFile = builder.buildFirFile(it)
(session.service<FirProvider>() as FirProviderImpl).recordFile(firFile)
@@ -79,6 +79,6 @@ class FirResolveTestTotalKotlin : AbstractFirResolveWithSessionTestCase() {
println("Raw FIR up, files: ${firFiles.size}")
doFirResolveTestBench(firFiles, totalTransformer.transformers, withProgress = true)
doFirResolveTestBench(firFiles, totalTransformer, withProgress = true)
}
}

View File

@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.Name
@@ -12,6 +13,8 @@ import org.jetbrains.kotlin.name.Name
interface FirNamedReference : FirReference {
val name: Name
val candidateSymbol: ConeSymbol? get() = null
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitNamedReference(this, data)
}

View File

@@ -783,10 +783,18 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
}
override fun visitNamedReference(namedReference: FirNamedReference) {
if (namedReference is FirErrorNamedReference) {
print("<${namedReference.errorReason}>#")
} else {
print("${namedReference.name}#")
val symbol = namedReference.candidateSymbol
when {
symbol != null -> {
print("R?C|")
if (symbol is ConeCallableSymbol)
print(symbol.callableId)
else if (symbol is ConeClassLikeSymbol)
print(symbol.classId)
print("|")
}
namedReference is FirErrorNamedReference -> print("<${namedReference.errorReason}>#")
else -> print("${namedReference.name}#")
}
}

View File

@@ -21,8 +21,12 @@ abstract class FirSession(val sessionProvider: FirSessionProvider?) {
var _correspondingSupertypesCache: Any? = null
fun <T : Any> getService(kclass: KClass<T>): T =
components[kclass] as T
fun <T : Any> getService(kclass: KClass<T>): T {
val any = components[kclass] ?: error(
"Couldn't find $kclass in session: '${this}', available: $components"
)
return any as T
}
protected fun <T : Any> registerComponent(tClass: KClass<T>, t: T) {
assert(tClass !in components) { "Already registered component" }

View File

@@ -29,8 +29,6 @@ interface FirProperty :
val backingFieldSymbol: FirBackingFieldSymbol
fun <D> transformChildrenWithoutAccessors(transformer: FirTransformer<D>, data: D)
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitProperty(this, data)

View File

@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.VisitedSupertype
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirVariable
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
@BaseTransformedType
@@ -24,6 +25,10 @@ interface FirValueParameter : @VisitedSupertype FirDeclaration, FirTypedDeclarat
override val symbol: FirVariableSymbol<FirValueParameter>
override fun <D> transformChildrenWithoutAccessors(transformer: FirTransformer<D>, data: D) {
transformChildren(transformer, data)
}
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitValueParameter(this, data)

View File

@@ -52,9 +52,12 @@ class FirMemberPropertyImpl(
status.isLateInit = isLateInit
}
override fun replaceDelegate(newDelegate: FirExpression?) {
delegate = newDelegate
}
override fun <D> transformChildrenWithoutAccessors(transformer: FirTransformer<D>, data: D) {
initializer = initializer?.transformSingle(transformer, data)
delegate = delegate?.transformSingle(transformer, data)
receiverTypeRef = receiverTypeRef?.transformSingle(transformer, data)
returnTypeRef = returnTypeRef.transformSingle(transformer, data)
typeParameters.transformInplace(transformer, data)
@@ -65,6 +68,7 @@ class FirMemberPropertyImpl(
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
getter = getter.transformSingle(transformer, data)
setter = setter?.transformSingle(transformer, data)
delegate = delegate?.transformSingle(transformer, data)
transformChildrenWithoutAccessors(transformer, data)
// Everything other (annotations, etc.) is done above
return this

View File

@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirVariable
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.transformInplace
import org.jetbrains.kotlin.fir.transformSingle
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.FirTransformer
@@ -34,12 +35,21 @@ class FirVariableImpl(
override val receiverTypeRef: FirTypeRef?
get() = null
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
override fun replaceDelegate(newDelegate: FirExpression?) {
delegate = newDelegate
}
override fun <D> transformChildrenWithoutAccessors(transformer: FirTransformer<D>, data: D) {
returnTypeRef = returnTypeRef.transformSingle(transformer, data)
initializer = initializer?.transformSingle(transformer, data)
delegate = delegate?.transformSingle(transformer, data)
annotations.transformInplace(transformer, data)
}
return super<FirAbstractNamedAnnotatedDeclaration>.transformChildren(transformer, data)
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
delegate = delegate?.transformSingle(transformer, data)
transformChildrenWithoutAccessors(transformer, data)
return this
}
override fun <D> transformReturnTypeRef(transformer: FirTransformer<D>, data: D) {

View File

@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.expressions
import org.jetbrains.kotlin.fir.VisitedSupertype
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
interface FirVariable<F : FirVariable<F>> :
@@ -23,6 +24,10 @@ interface FirVariable<F : FirVariable<F>> :
override val symbol: FirVariableSymbol<F>
fun replaceDelegate(newDelegate: FirExpression?) {}
fun <D> transformChildrenWithoutAccessors(transformer: FirTransformer<D>, data: D)
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitVariable(this, data)

View File

@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
import org.jetbrains.kotlin.name.Name
open class FirResolvedCallableReferenceImpl(
class FirResolvedCallableReferenceImpl(
session: FirSession,
psi: PsiElement?,
override val name: Name,

View File

@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.FirNamedReference
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.name.Name
class FirSimpleNamedReference(
open class FirSimpleNamedReference(
session: FirSession,
psi: PsiElement?,
override val name: Name

View File

@@ -151,7 +151,7 @@ class BinaryJavaAnnotation private constructor(
}
}
private val classifierResolutionResult by lazy(LazyThreadSafetyMode.NONE) {
private val classifierResolutionResult by lazy(LazyThreadSafetyMode.PUBLICATION) {
context.resolveByInternalName(Type.getType(desc).internalName)
}

View File

@@ -28,6 +28,8 @@ import org.jetbrains.kotlin.utils.compact
import org.jetbrains.org.objectweb.asm.Type
import java.text.CharacterIterator
import java.text.StringCharacterIterator
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
/**
* Take a look at com.intellij.psi.impl.compiled.SignatureParsing
@@ -38,6 +40,7 @@ import java.text.StringCharacterIterator
class BinaryClassSignatureParser {
private val canonicalNameInterner = StringInterner()
private val internerLock = ReentrantLock()
fun parseTypeParametersDeclaration(signature: CharacterIterator, context: ClassifierResolutionContext): List<JavaTypeParameter> {
if (signature.current() != '<') {
@@ -99,7 +102,7 @@ class BinaryClassSignatureParser {
signature.next()
}
val parameterName = canonicalNameInterner.intern(id.toString())
val parameterName = internerLock.withLock { canonicalNameInterner.intern(id.toString()) }
return PlainJavaClassifierType({ context.resolveTypeParameter(parameterName) }, emptyList())
}
@@ -136,7 +139,9 @@ class BinaryClassSignatureParser {
}
signature.next()
val internalName = canonicalNameInterner.intern(canonicalName.toString().replace('.', '$'))
val internalName = internerLock.withLock {
canonicalNameInterner.intern(canonicalName.toString().replace('.', '$'))
}
return PlainJavaClassifierType(
{ context.resolveByInternalName(internalName) },
argumentGroups.reversed().flattenTo(arrayListOf()).compact()

View File

@@ -33,7 +33,7 @@ internal class PlainJavaClassifierType(
classifierComputation: () -> ClassifierResolutionContext.Result,
override val typeArguments: List<JavaType>
) : JavaClassifierType {
private val classifierResolverResult by lazy(LazyThreadSafetyMode.NONE, classifierComputation)
private val classifierResolverResult by lazy(LazyThreadSafetyMode.PUBLICATION, classifierComputation)
override val classifier get() = classifierResolverResult.classifier
override val isRaw

View File

@@ -18,10 +18,9 @@ FILE fqName:<root> fileName:/delegateFieldWithAnnotations.kt
PROPERTY name:test1 visibility:public modality:FINAL [delegated,val]
annotations:
Ann
FIELD PROPERTY_BACKING_FIELD name:test1 type:IrErrorType visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:IrErrorType
FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Int visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [delegated,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test1> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-test1> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Int visibility:public [final,static] ' type=kotlin.Int origin=null

View File

@@ -84,27 +84,26 @@ FILE fqName:<root> fileName:/delegatedPropertyAccessorsWithAnnotations.kt
PROPERTY name:test1 visibility:public modality:FINAL [delegated,val]
annotations:
A(x = 'test1.get')
FIELD PROPERTY_BACKING_FIELD name:test1 type:IrErrorType visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:IrErrorType
FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Int visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [delegated,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test1> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-test1> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Int visibility:public [final,static] ' type=kotlin.Int origin=null
PROPERTY name:test2 visibility:public modality:FINAL [delegated,var]
annotations:
A(x = 'test2.get')
A(x = 'test2.set')
A(x = 'test2.set.param')
FIELD PROPERTY_BACKING_FIELD name:test2 type:IrErrorType visibility:public [static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test2> visibility:public modality:FINAL <> () returnType:IrErrorType
FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Int visibility:public [static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test2> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:test2 visibility:public modality:FINAL [delegated,var]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test2> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:IrErrorType visibility:public [static] ' type=IrErrorType origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<set-test2> visibility:public modality:FINAL <> (<set-?>:IrErrorType) returnType:kotlin.Unit
RETURN type=kotlin.Nothing from='public final fun <get-test2> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Int visibility:public [static] ' type=kotlin.Int origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<set-test2> visibility:public modality:FINAL <> (<set-?>:kotlin.Int) returnType:kotlin.Unit
correspondingProperty: PROPERTY name:test2 visibility:public modality:FINAL [delegated,var]
VALUE_PARAMETER name:<set-?> index:0 type:IrErrorType
VALUE_PARAMETER name:<set-?> index:0 type:kotlin.Int
BLOCK_BODY
SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:IrErrorType visibility:public [static] ' type=kotlin.Unit origin=null
value: GET_VAR '<set-?>: IrErrorType declared in <root>.<set-test2>' type=IrErrorType origin=null
SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Int visibility:public [static] ' type=kotlin.Unit origin=null
value: GET_VAR '<set-?>: kotlin.Int declared in <root>.<set-test2>' type=kotlin.Int origin=null

View File

@@ -30,5 +30,4 @@ FILE fqName:<root> fileName:/localDelegatedPropertiesWithAnnotations.kt
FUN name:foo visibility:public modality:FINAL <> (m:kotlin.collections.Map<kotlin.String, kotlin.Int>) returnType:kotlin.Unit
VALUE_PARAMETER name:m index:0 type:kotlin.collections.Map<kotlin.String, kotlin.Int>
BLOCK_BODY
VAR name:test type:IrErrorType [val]
VAR name:test type:kotlin.Int [val]

View File

@@ -83,13 +83,13 @@ FILE fqName:<root> fileName:/classLevelProperties.kt
correspondingProperty: PROPERTY name:test6 visibility:public modality:FINAL [val]
$this: VALUE_PARAMETER name:<this> type:<root>.C
PROPERTY name:test7 visibility:public modality:FINAL [delegated,val]
FIELD PROPERTY_BACKING_FIELD name:test7 type:IrErrorType visibility:public [final]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test7> visibility:public modality:FINAL <> ($this:<root>.C) returnType:IrErrorType
FIELD PROPERTY_BACKING_FIELD name:test7 type:kotlin.Int visibility:public [final]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test7> visibility:public modality:FINAL <> ($this:<root>.C) returnType:kotlin.Int
correspondingProperty: PROPERTY name:test7 visibility:public modality:FINAL [delegated,val]
$this: VALUE_PARAMETER name:<this> type:<root>.C
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test7> (): IrErrorType declared in <root>.C'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test7 type:IrErrorType visibility:public [final] ' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-test7> (): kotlin.Int declared in <root>.C'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test7 type:kotlin.Int visibility:public [final] ' type=kotlin.Int origin=null
receiver: GET_VAR '<this>: <root>.C declared in <root>.C.<get-test7>' type=<root>.C origin=null
PROPERTY name:test8 visibility:public modality:FINAL [delegated,var]
FIELD PROPERTY_BACKING_FIELD name:test8 type:IrErrorType visibility:public

View File

@@ -1,11 +1,11 @@
FILE fqName:<root> fileName:/delegatedProperties.kt
PROPERTY name:test1 visibility:public modality:FINAL [delegated,val]
FIELD PROPERTY_BACKING_FIELD name:test1 type:IrErrorType visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:IrErrorType
FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Int visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [delegated,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test1> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-test1> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Int visibility:public [final,static] ' type=kotlin.Int origin=null
CLASS CLASS name:C modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.C
CONSTRUCTOR visibility:public <> (map:kotlin.collections.MutableMap<kotlin.String, kotlin.Any>) returnType:<root>.C [primary]
@@ -25,13 +25,13 @@ FILE fqName:<root> fileName:/delegatedProperties.kt
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:map type:kotlin.collections.MutableMap<kotlin.String, kotlin.Any> visibility:public [final] ' type=kotlin.collections.MutableMap<kotlin.String, kotlin.Any> origin=null
receiver: GET_VAR '<this>: <root>.C declared in <root>.C.<get-map>' type=<root>.C origin=null
PROPERTY name:test2 visibility:public modality:FINAL [delegated,val]
FIELD PROPERTY_BACKING_FIELD name:test2 type:IrErrorType visibility:public [final]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test2> visibility:public modality:FINAL <> ($this:<root>.C) returnType:IrErrorType
FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Int visibility:public [final]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test2> visibility:public modality:FINAL <> ($this:<root>.C) returnType:kotlin.Int
correspondingProperty: PROPERTY name:test2 visibility:public modality:FINAL [delegated,val]
$this: VALUE_PARAMETER name:<this> type:<root>.C
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test2> (): IrErrorType declared in <root>.C'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:IrErrorType visibility:public [final] ' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-test2> (): kotlin.Int declared in <root>.C'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Int visibility:public [final] ' type=kotlin.Int origin=null
receiver: GET_VAR '<this>: <root>.C declared in <root>.C.<get-test2>' type=<root>.C origin=null
PROPERTY name:test3 visibility:public modality:FINAL [delegated,var]
FIELD PROPERTY_BACKING_FIELD name:test3 type:IrErrorType visibility:public

View File

@@ -1,9 +1,9 @@
FILE fqName:<root> fileName:/localDelegatedProperties.kt
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
VAR name:x type:IrErrorType [val]
ERROR_CALL 'Unresolved reference: <Ambiguity: println, [kotlin/io/println, kotlin/io/println, kotlin/io/println, kotlin/io/println, kotlin/io/println, kotlin/io/println, kotlin/io/println, kotlin/io/println, kotlin/io/println, kotlin/io/println]>#' type=IrErrorType
GET_VAR 'val x: IrErrorType [val] declared in <root>.test1' type=IrErrorType origin=null
VAR name:x type:kotlin.Int [val]
CALL 'public final fun println (message: kotlin.Int): kotlin.Unit [inline] declared in kotlin.io' type=kotlin.Unit origin=null
message: GET_VAR 'val x: kotlin.Int [val] declared in <root>.test1' type=kotlin.Int origin=null
FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
VAR name:x type:IrErrorType [var]

View File

@@ -63,12 +63,12 @@ FILE fqName:<root> fileName:/packageLevelProperties.kt
FUN name:<get-test6> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:test6 visibility:public modality:FINAL [val]
PROPERTY name:test7 visibility:public modality:FINAL [delegated,val]
FIELD PROPERTY_BACKING_FIELD name:test7 type:IrErrorType visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test7> visibility:public modality:FINAL <> () returnType:IrErrorType
FIELD PROPERTY_BACKING_FIELD name:test7 type:kotlin.Int visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test7> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:test7 visibility:public modality:FINAL [delegated,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test7> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test7 type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-test7> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test7 type:kotlin.Int visibility:public [final,static] ' type=kotlin.Int origin=null
PROPERTY name:test8 visibility:public modality:FINAL [delegated,var]
FIELD PROPERTY_BACKING_FIELD name:test8 type:IrErrorType visibility:public [static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test8> visibility:public modality:FINAL <> () returnType:IrErrorType

View File

@@ -51,17 +51,17 @@ FILE fqName:<root> fileName:/differentReceivers.kt
RETURN type=kotlin.Nothing from='public final fun <get-testO> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:testO type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null
PROPERTY name:testK visibility:public modality:FINAL [delegated,val]
FIELD PROPERTY_BACKING_FIELD name:testK type:IrErrorType visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-testK> visibility:public modality:FINAL <> () returnType:IrErrorType
FIELD PROPERTY_BACKING_FIELD name:testK type:kotlin.String visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-testK> visibility:public modality:FINAL <> () returnType:kotlin.String
correspondingProperty: PROPERTY name:testK visibility:public modality:FINAL [delegated,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-testK> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:testK type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-testK> (): kotlin.String declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:testK type:kotlin.String visibility:public [final,static] ' type=kotlin.String origin=null
PROPERTY name:testOK visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:testOK type:IrErrorType visibility:public [final,static]
EXPRESSION_BODY
ERROR_CALL 'Unresolved reference: <Ambiguity: plus, [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]>#' type=IrErrorType
CALL 'public final fun <get-testK> (): IrErrorType declared in <root>' type=IrErrorType origin=null
ERROR_CALL 'Unresolved reference: <Ambiguity: plus, [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/text/plus]>#' type=IrErrorType
CALL 'public final fun <get-testK> (): kotlin.String declared in <root>' type=kotlin.String origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-testOK> visibility:public modality:FINAL <> () returnType:IrErrorType
correspondingProperty: PROPERTY name:testOK visibility:public modality:FINAL [val]
BLOCK_BODY

View File

@@ -46,10 +46,10 @@ FILE fqName:<root> fileName:/localDifferentReceivers.kt
FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String
BLOCK_BODY
VAR name:testO type:IrErrorType [val]
VAR name:testK type:IrErrorType [val]
VAR name:testK type:kotlin.String [val]
VAR name:testOK type:IrErrorType [val]
ERROR_CALL 'Unresolved reference: <Ambiguity: plus, [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]>#' type=IrErrorType
GET_VAR 'val testK: IrErrorType [val] declared in <root>.box' type=IrErrorType origin=null
ERROR_CALL 'Unresolved reference: <Ambiguity: plus, [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/text/plus]>#' type=IrErrorType
GET_VAR 'val testK: kotlin.String [val] declared in <root>.box' type=kotlin.String origin=null
RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in <root>'
GET_VAR 'val testOK: IrErrorType [val] declared in <root>.box' type=IrErrorType origin=null

View File

@@ -24,6 +24,5 @@ FILE fqName:<root> fileName:/classReference.kt
GET_OBJECT 'CLASS CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
GET_CLASS type=kotlin.reflect.KClass<<root>.A>
CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.A' type=<root>.A origin=null
ERROR_CALL 'No getter found for R|kotlin/jvm/java|' type=java.lang.Class<T of <uninitialized parent>>
ERROR_CALL 'No getter found for R|kotlin/jvm/java|' type=java.lang.Class<T of <uninitialized parent>>
ERROR_CALL 'No getter found for R|kotlin/jvm/java|' type=java.lang.Class<<root>.A>
ERROR_CALL 'No getter found for R|kotlin/jvm/java|' type=java.lang.Class<<root>.A>

View File

@@ -8,7 +8,7 @@ FILE fqName:<root> fileName:/genericPropertyCall.kt
PROPERTY name:test visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:test type:IrErrorType visibility:public [final,static]
EXPRESSION_BODY
CALL 'public final fun <get-id> (): IrErrorType declared in <root>' type=IrErrorType origin=null
ERROR_CALL 'Unresolved reference: R?C|/id|' type=IrErrorType
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test> visibility:public modality:FINAL <> () returnType:IrErrorType
correspondingProperty: PROPERTY name:test visibility:public modality:FINAL [val]
BLOCK_BODY

View File

@@ -65,19 +65,19 @@ FILE fqName:<root> fileName:/genericPropertyRef.kt
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
PROPERTY name:additionalText visibility:public modality:FINAL [delegated,val]
FIELD PROPERTY_BACKING_FIELD name:additionalText type:IrErrorType visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-additionalText> visibility:public modality:FINAL <> () returnType:IrErrorType
FIELD PROPERTY_BACKING_FIELD name:additionalText type:kotlin.Int visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-additionalText> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:additionalText visibility:public modality:FINAL [delegated,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-additionalText> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:additionalText type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-additionalText> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:additionalText type:kotlin.Int visibility:public [final,static] ' type=kotlin.Int origin=null
PROPERTY name:additionalValue visibility:public modality:FINAL [delegated,val]
FIELD PROPERTY_BACKING_FIELD name:additionalValue type:IrErrorType visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-additionalValue> visibility:public modality:FINAL <> () returnType:IrErrorType
FIELD PROPERTY_BACKING_FIELD name:additionalValue type:kotlin.Int visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-additionalValue> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:additionalValue visibility:public modality:FINAL [delegated,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-additionalValue> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:additionalValue type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-additionalValue> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:additionalValue type:kotlin.Int visibility:public [final,static] ' type=kotlin.Int origin=null
CLASS CLASS name:DVal modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.DVal
CONSTRUCTOR visibility:public <> (kmember:kotlin.Any) returnType:<root>.DVal [primary]
@@ -161,12 +161,11 @@ FILE fqName:<root> fileName:/genericPropertyRef.kt
SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value2 type:kotlin.Any? visibility:public [static] ' type=kotlin.Any? origin=null
value: GET_VAR 'value: T of <uninitialized parent> declared in <root>.<set-bar>' type=T of <uninitialized parent> origin=null
PROPERTY name:barRef visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:barRef type:T of <uninitialized parent> visibility:public [final,static]
FIELD PROPERTY_BACKING_FIELD name:barRef type:kotlin.String.Companion visibility:public [final,static]
EXPRESSION_BODY
CALL 'public final fun <get-bar> (): T of <uninitialized parent> declared in <root>' type=T of <uninitialized parent> origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-barRef> visibility:public modality:FINAL <> () returnType:T of <uninitialized parent>
CALL 'public final fun <get-bar> (): T of <uninitialized parent> declared in <root>' type=kotlin.String.Companion origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-barRef> visibility:public modality:FINAL <> () returnType:kotlin.String.Companion
correspondingProperty: PROPERTY name:barRef visibility:public modality:FINAL [val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-barRef> (): T of <uninitialized parent> declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:barRef type:T of <uninitialized parent> visibility:public [final,static] ' type=T of <uninitialized parent> origin=null
RETURN type=kotlin.Nothing from='public final fun <get-barRef> (): kotlin.String.Companion declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:barRef type:kotlin.String.Companion visibility:public [final,static] ' type=kotlin.String.Companion origin=null

View File

@@ -83,7 +83,7 @@ FILE fqName:<root> fileName:/multipleThisReferences.kt
FIELD PROPERTY_BACKING_FIELD name:xx type:kotlin.String visibility:public [final]
EXPRESSION_BODY
CALL 'public final fun plus (other: kotlin.Any?): kotlin.String declared in kotlin' type=kotlin.String origin=null
other: CALL 'public final fun <get-y> (): kotlin.Int declared in <root>.Host' type=kotlin.Int origin=null
other: GET_VAR 'y: kotlin.Int declared in <root>.Host.<init>' type=kotlin.Int origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-xx> visibility:public modality:FINAL <> ($this:<root>.Host.test.<no name provided>) returnType:kotlin.String
correspondingProperty: PROPERTY name:xx visibility:public modality:FINAL [val]
$this: VALUE_PARAMETER name:<this> type:<root>.Host.test.<no name provided>

View File

@@ -22,5 +22,4 @@ FILE fqName:<root> fileName:/objectClassReference.kt
BLOCK_BODY
GET_CLASS type=kotlin.reflect.KClass<<root>.A>
GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
ERROR_CALL 'No getter found for R|kotlin/jvm/java|' type=java.lang.Class<T of <uninitialized parent>>
ERROR_CALL 'No getter found for R|kotlin/jvm/java|' type=java.lang.Class<<root>.A>

View File

@@ -181,43 +181,43 @@ FILE fqName:<root> fileName:/propertyReferences.kt
RETURN type=kotlin.Nothing from='public final fun <get-test_varWithAccessors> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test_varWithAccessors type:kotlin.Int visibility:public [final,static] ' type=kotlin.Int origin=null
PROPERTY name:delegatedVal visibility:public modality:FINAL [delegated,val]
FIELD PROPERTY_BACKING_FIELD name:delegatedVal type:IrErrorType visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-delegatedVal> visibility:public modality:FINAL <> () returnType:IrErrorType
FIELD PROPERTY_BACKING_FIELD name:delegatedVal type:kotlin.Int visibility:public [final,static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-delegatedVal> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:delegatedVal visibility:public modality:FINAL [delegated,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-delegatedVal> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:delegatedVal type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-delegatedVal> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:delegatedVal type:kotlin.Int visibility:public [final,static] ' type=kotlin.Int origin=null
PROPERTY name:test_delegatedVal visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:test_delegatedVal type:IrErrorType visibility:public [final,static]
FIELD PROPERTY_BACKING_FIELD name:test_delegatedVal type:kotlin.Int visibility:public [final,static]
EXPRESSION_BODY
CALL 'public final fun <get-delegatedVal> (): IrErrorType declared in <root>' type=IrErrorType origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test_delegatedVal> visibility:public modality:FINAL <> () returnType:IrErrorType
CALL 'public final fun <get-delegatedVal> (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test_delegatedVal> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:test_delegatedVal visibility:public modality:FINAL [val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test_delegatedVal> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test_delegatedVal type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-test_delegatedVal> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test_delegatedVal type:kotlin.Int visibility:public [final,static] ' type=kotlin.Int origin=null
PROPERTY name:delegatedVar visibility:public modality:FINAL [delegated,var]
FIELD PROPERTY_BACKING_FIELD name:delegatedVar type:IrErrorType visibility:public [static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-delegatedVar> visibility:public modality:FINAL <> () returnType:IrErrorType
FIELD PROPERTY_BACKING_FIELD name:delegatedVar type:kotlin.Int visibility:public [static]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-delegatedVar> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:delegatedVar visibility:public modality:FINAL [delegated,var]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-delegatedVar> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:delegatedVar type:IrErrorType visibility:public [static] ' type=IrErrorType origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<set-delegatedVar> visibility:public modality:FINAL <> (<set-?>:IrErrorType) returnType:kotlin.Unit
RETURN type=kotlin.Nothing from='public final fun <get-delegatedVar> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:delegatedVar type:kotlin.Int visibility:public [static] ' type=kotlin.Int origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<set-delegatedVar> visibility:public modality:FINAL <> (<set-?>:kotlin.Int) returnType:kotlin.Unit
correspondingProperty: PROPERTY name:delegatedVar visibility:public modality:FINAL [delegated,var]
VALUE_PARAMETER name:<set-?> index:0 type:IrErrorType
VALUE_PARAMETER name:<set-?> index:0 type:kotlin.Int
BLOCK_BODY
SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:delegatedVar type:IrErrorType visibility:public [static] ' type=kotlin.Unit origin=null
value: GET_VAR '<set-?>: IrErrorType declared in <root>.<set-delegatedVar>' type=IrErrorType origin=null
SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:delegatedVar type:kotlin.Int visibility:public [static] ' type=kotlin.Unit origin=null
value: GET_VAR '<set-?>: kotlin.Int declared in <root>.<set-delegatedVar>' type=kotlin.Int origin=null
PROPERTY name:test_delegatedVar visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:test_delegatedVar type:IrErrorType visibility:public [final,static]
FIELD PROPERTY_BACKING_FIELD name:test_delegatedVar type:kotlin.Int visibility:public [final,static]
EXPRESSION_BODY
CALL 'public final fun <get-delegatedVar> (): IrErrorType declared in <root>' type=IrErrorType origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test_delegatedVar> visibility:public modality:FINAL <> () returnType:IrErrorType
CALL 'public final fun <get-delegatedVar> (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test_delegatedVar> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:test_delegatedVar visibility:public modality:FINAL [val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test_delegatedVar> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test_delegatedVar type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-test_delegatedVar> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test_delegatedVar type:kotlin.Int visibility:public [final,static] ' type=kotlin.Int origin=null
PROPERTY name:constVal visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:constVal type:kotlin.Int visibility:public [final,static]
EXPRESSION_BODY

View File

@@ -208,7 +208,7 @@ FILE fqName:<root> fileName:/useImportedMember.kt
BRANCH
if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
arg0: CALL 'public final fun <get-g2> (): T of <uninitialized parent> declared in <root>.C' type=T of <uninitialized parent> origin=null
arg0: CALL 'public final fun <get-g2> (): T of <uninitialized parent> declared in <root>.C' type=kotlin.String origin=null
$this: CONST String type=kotlin.String value="8"
arg1: CONST String type=kotlin.String value="8"
then: RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in <root>'
@@ -225,7 +225,7 @@ FILE fqName:<root> fileName:/useImportedMember.kt
BRANCH
if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
arg0: CALL 'public final fun <get-fromClass> (): T of <uninitialized parent> declared in <root>.BaseClass' type=T of <uninitialized parent> origin=null
arg0: CALL 'public final fun <get-fromClass> (): T of <uninitialized parent> declared in <root>.BaseClass' type=kotlin.String origin=null
$this: CONST String type=kotlin.String value="10"
arg1: CONST String type=kotlin.String value="10"
then: RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in <root>'

View File

@@ -14,7 +14,7 @@ FILE fqName:<root> fileName:/variableAsFunctionCallWithGenerics.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testGeneric1 (x: kotlin.String): T of <uninitialized parent> declared in <root>'
CALL 'public abstract fun invoke (): T of <uninitialized parent> declared in kotlin.Function0' type=T of <uninitialized parent> origin=null
$this: CALL 'public final fun <get-gk> (): kotlin.Function0<T of <uninitialized parent>> declared in <root>' type=kotlin.Function0<T of <uninitialized parent>> origin=null
$this: ERROR_CALL 'Unresolved reference: R?C|/gk|' type=kotlin.Function0<T of <uninitialized parent>>
PROPERTY name:kt26531Val visibility:public modality:FINAL [val]
FUN name:<get-kt26531Val> visibility:public modality:FINAL <> () returnType:kotlin.Function0<T of <uninitialized parent>>
correspondingProperty: PROPERTY name:kt26531Val visibility:public modality:FINAL [val]
@@ -30,4 +30,4 @@ FILE fqName:<root> fileName:/variableAsFunctionCallWithGenerics.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun kt26531 (): T of <uninitialized parent> declared in <root>'
CALL 'public abstract fun invoke (): T of <uninitialized parent> declared in kotlin.Function0' type=T of <uninitialized parent> origin=null
$this: CALL 'public final fun <get-kt26531Val> (): kotlin.Function0<T of <uninitialized parent>> declared in <root>' type=kotlin.Function0<T of <uninitialized parent>> origin=null
$this: ERROR_CALL 'Unresolved reference: R?C|/kt26531Val|' type=kotlin.Function0<T of <uninitialized parent>>

View File

@@ -9,8 +9,8 @@ FILE fqName:<root> fileName:/builtinMap.kt
BRANCH
if: CALL 'public abstract fun isEmpty (): kotlin.Boolean declared in kotlin.collections.Map' type=kotlin.Boolean origin=null
$this: ERROR_CALL 'Unresolved reference: this#' type=kotlin.collections.Map<out K1 of <root>.plus, V1 of <root>.plus>
then: ERROR_CALL 'Unresolved reference: <Ambiguity: mapOf, [kotlin/collections/mapOf, kotlin/collections/mapOf]>#' type=IrErrorType
GET_VAR 'pair: kotlin.Pair<K1 of <root>.plus, V1 of <root>.plus> declared in <root>.plus' type=kotlin.Pair<K1 of <root>.plus, V1 of <root>.plus> origin=null
then: CALL 'public final fun mapOf (pair: kotlin.Pair<K of <uninitialized parent>, V of <uninitialized parent>>): kotlin.collections.Map<K of <uninitialized parent>, V of <uninitialized parent>> declared in kotlin.collections' type=kotlin.collections.Map<K1 of <root>.plus, V1 of <root>.plus> origin=null
pair: GET_VAR 'pair: kotlin.Pair<K1 of <root>.plus, V1 of <root>.plus> declared in <root>.plus' type=kotlin.Pair<K1 of <root>.plus, V1 of <root>.plus> origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'public final fun apply (block: kotlin.Function1<T of <uninitialized parent>, kotlin.Unit>): T of <uninitialized parent> [inline] declared in kotlin' type=java.util.LinkedHashMap<K1 of <root>.plus, V1 of <root>.plus> origin=null

View File

@@ -8,14 +8,21 @@ import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.concurrent.tcReg
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirResolveStage
import org.jetbrains.kotlin.fir.resolve.transformers.FirStagesTransformerFactory
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import java.io.PrintStream
import java.util.concurrent.Callable
import java.util.concurrent.Executors
import kotlin.math.max
import kotlin.reflect.KClass
import kotlin.system.measureNanoTime
@@ -28,18 +35,32 @@ fun checkFirProvidersConsistency(firFiles: List<FirFile>) {
}
}
private data class FailureInfo(val transformer: KClass<*>, val throwable: Throwable, val file: String)
private data class FailureInfo(val stageClass: KClass<*>, val throwable: Throwable, val file: String)
private data class ErrorTypeReport(val report: String, var count: Int = 0)
private val threadLocalTransformer = ThreadLocal<FirTransformer<Nothing?>>()
class FirResolveBench(val withProgress: Boolean) {
val timePerTransformer = mutableMapOf<KClass<*>, Long>()
val counterPerTransformer = mutableMapOf<KClass<*>, Long>()
val summaryTimePerStage = mutableMapOf<KClass<*>, Long>()
val realTimePerStage = mutableMapOf<KClass<*>, Long>()
var resolvedTypes = 0
var errorTypes = 0
var unresolvedTypes = 0
var errorFunctionCallTypes = 0
var errorQualifiedAccessTypes = 0
var implicitTypes = 0
var fileCount = 0
var totalLines = 0
var parallelThreads = Runtime.getRuntime().availableProcessors()
var isParallel = true
val singleThreadPool = Executors.newSingleThreadExecutor()
val pool by lazy { Executors.newFixedThreadPool(parallelThreads) }
private val fails = mutableListOf<FailureInfo>()
@@ -48,39 +69,132 @@ class FirResolveBench(val withProgress: Boolean) {
private val errorTypesReports = mutableMapOf<String, ErrorTypeReport>()
fun countBuilder(builder: RawFirBuilder, time: Long) {
timePerTransformer.merge(builder::class, time) { a, b -> a + b }
counterPerTransformer.merge(builder::class, 1) { a, b -> a + b }
summaryTimePerStage.merge(builder::class, time) { a, b -> a + b }
realTimePerStage.merge(builder::class, time) { a, b -> a + b }
}
private fun runBuilder(builder: RawFirBuilder, ktFiles: List<KtFile>): List<FirFile> {
return ktFiles.map { file ->
var firFile: FirFile? = null
val time = measureNanoTime {
firFile = builder.buildFirFile(file)
(builder.session.service<FirProvider>() as FirProviderImpl).recordFile(firFile!!)
}
summaryTimePerStage.merge(builder::class, time) { a, b -> a + b }
firFile!!
}
}
private fun runBuilderConcurrently(builder: RawFirBuilder, ktFiles: List<KtFile>): List<FirFile> {
return ktFiles.map { file ->
pool.submit(Callable {
var firFile: FirFile? = null
val time = measureNanoTime {
firFile = builder.buildFirFile(file)
(builder.session.service<FirProvider>() as FirProviderImpl).recordFile(firFile!!)
}
summaryTimePerStage.merge(builder::class, time) { a, b -> a + b }
firFile!!
})
}.map { it.get() }
}
fun buildFiles(
builder: RawFirBuilder,
ktFiles: List<KtFile>
): List<FirFile> {
val (result, time) = measureNanoTimeWithResult {
if (isParallel)
runBuilderConcurrently(builder, ktFiles)
else
runBuilder(builder, ktFiles)
}
realTimePerStage.merge(builder::class, time) { a, b -> a + b }
ktFiles.forEach {
totalLines += it.text.lines().count()
}
return result
}
private fun runStage(stage: FirResolveStage, firFiles: List<FirFile>) {
val firFileSequence = if (withProgress) firFiles.progress(" ~ ") else firFiles.asSequence()
val transformer = stage.createTransformer()
for (firFile in firFileSequence) {
var fail = false
val time = measureNanoTime {
try {
transformer.transformFile(firFile, null)
} catch (e: Throwable) {
val ktFile = firFile.psi as KtFile
println("Fail in file: ${ktFile.virtualFilePath}")
fail = true
fails += FailureInfo(stage::class, e, ktFile.virtualFilePath)
//println(ktFile.text)
//throw e
}
}
if (!fail) {
summaryTimePerStage.merge(stage::class, time) { a, b -> a + b }
}
}
}
private fun runStageConcurrently(stage: FirResolveStage, firFiles: List<FirFile>) {
require(stage.isParallel)
val transformerLocal = object : ThreadLocal<FirTransformer<Nothing?>>() {
override fun initialValue(): FirTransformer<Nothing?> {
return stage.createTransformer()
}
}
val tasks = (firFiles).shuffled().map { firFile ->
firFile to pool.submit {
var fail = false
val time = measureNanoTime {
try {
transformerLocal.get().transformFile(firFile, null)
} catch (e: Throwable) {
val ktFile = firFile.psi as KtFile
println("Fail in file: ${ktFile.virtualFilePath}")
fail = true
fails += FailureInfo(stage::class, e, ktFile.virtualFilePath)
//println(ktFile.text)
//throw e
}
}
if (!fail) {
summaryTimePerStage.merge(stage::class, time) { a, b -> a + b }
}
}
}
val tasksSequence = if (withProgress) tasks.progress(" ~ ") else tasks.asSequence()
tasksSequence.forEach { (_, future) ->
future.get()
}
}
fun processFiles(
firFiles: List<FirFile>,
transformers: List<FirTransformer<Nothing?>>
factory: FirStagesTransformerFactory
) {
fileCount += firFiles.size
try {
for ((stage, transformer) in transformers.withIndex()) {
println("Starting stage #$stage. $transformer")
val firFileSequence = if (withProgress) firFiles.progress(" ~ ") else firFiles.asSequence()
for (firFile in firFileSequence) {
var fail = false
val time = measureNanoTime {
try {
transformer.transformFile(firFile, null)
} catch (e: Throwable) {
val ktFile = firFile.psi as KtFile
println("Fail in file: ${ktFile.virtualFilePath}")
fail = true
fails += FailureInfo(transformer::class, e, ktFile.virtualFilePath)
//println(ktFile.text)
//throw e
}
}
if (!fail) {
timePerTransformer.merge(transformer::class, time) { a, b -> a + b }
counterPerTransformer.merge(transformer::class, 1) { a, b -> a + b }
}
//totalLength += StringBuilder().apply { FirRenderer(this).visitFile(firFile) }.length
for ((stageNum, stage) in factory.resolveStages.withIndex()) {
val usedThreads = if (stage.isParallel && isParallel) parallelThreads else 1
println("Starting stage #$stageNum, $stage, isParallel = ${stage.isParallel}, using threads: $usedThreads")
val realTime = measureNanoTime {
if (stage.isParallel && isParallel)
runStageConcurrently(stage, firFiles)
else
runStage(stage, firFiles)
}
realTimePerStage[stage::class] = realTime
//totalLength += StringBuilder().apply { FirRenderer(this).visitFile(firFile) }.length
checkFirProvidersConsistency(firFiles)
}
@@ -113,6 +227,30 @@ class FirResolveBench(val withProgress: Boolean) {
element.acceptChildren(this)
}
override fun visitFunctionCall(functionCall: FirFunctionCall) {
val typeRef = functionCall.typeRef
if (typeRef is FirResolvedTypeRef) {
val type = typeRef.type
if (type is ConeKotlinErrorType) {
errorFunctionCallTypes++
}
}
super.visitFunctionCall(functionCall)
}
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) {
val typeRef = qualifiedAccessExpression.typeRef
if (typeRef is FirResolvedTypeRef) {
val type = typeRef.type
if (type is ConeKotlinErrorType) {
errorQualifiedAccessTypes++
}
}
super.visitQualifiedAccessExpression(qualifiedAccessExpression)
}
override fun visitTypeRef(typeRef: FirTypeRef) {
unresolvedTypes++
@@ -177,30 +315,35 @@ class FirResolveBench(val withProgress: Boolean) {
val goodTypes = resolvedTypes - errorTypes - implicitTypes
stream.println("CORRECTLY RESOLVED TYPES: $goodTypes (${goodTypes percentOf resolvedTypes} of resolved)")
stream.println("ERRONEOUSLY RESOLVED TYPES: $errorTypes (${errorTypes percentOf resolvedTypes} of resolved)")
stream.println(" - unresolved calls: $errorFunctionCallTypes")
stream.println(" - unresolved q.accesses: $errorQualifiedAccessTypes")
stream.println("ERRONEOUSLY RESOLVED IMPLICIT TYPES: $implicitTypes (${implicitTypes percentOf resolvedTypes} of resolved)")
stream.println("UNIQUE ERROR TYPES: ${errorTypesReports.size}")
for (c in tcReg) {
stream.println(c.stats())
}
var totalTime = 0L
var totalFiles = 0L
var totalSummaryTime = 0L
timePerTransformer.forEach { (transformer, time) ->
val counter = counterPerTransformer[transformer]!!
stream.println("${transformer.simpleName}, TIME: ${time * 1e-6} ms, TIME PER FILE: ${(time / counter) * 1e-6} ms, FILES: OK/E/T $counter/${fileCount - counter}/$fileCount")
realTimePerStage.forEach { (stageClass, time) ->
val counter = fileCount - fails.count { it.stageClass == stageClass }
val summaryTime = summaryTimePerStage[stageClass]!!
stream.println("${stageClass.simpleName}, TIME: ${time * 1e-6} ms, TIME/FILE: ${(time / counter) * 1e-6} ms, S-TIME/TIME: ${summaryTime / (time * 1.0)}, S-TIME: ${summaryTime * 1e-6} ms, S-TIME/FILE: ${summaryTime / counter * 1e-6} ms, FILES: OK/E/T $counter/${fileCount - counter}/$fileCount")
totalTime += time
totalFiles += counter
totalSummaryTime += summaryTime
}
if (counterPerTransformer.keys.size > 0) {
totalFiles /= counterPerTransformer.keys.size
stream.println("Total, TIME: ${totalTime * 1e-6} ms, TIME PER FILE: ${(totalTime / totalFiles) * 1e-6} ms")
}
stream.println("Total, TIME: ${totalTime * 1e-6} ms, TIME PER FILE: ${(totalTime / fileCount) * 1e-6} ms, S-TIME/TIME: ${totalSummaryTime / (totalTime * 1.0)}, S-TIME: ${totalSummaryTime * 1e-6} ms, S-TIME/FILE: ${totalSummaryTime / fileCount * 1e-6} ms")
stream.println(" ${totalLines / (totalTime * 1e-9)} Line/s")
}
}
fun doFirResolveTestBench(
firFiles: List<FirFile>,
transformers: List<FirTransformer<Nothing?>>,
factory: FirStagesTransformerFactory,
gc: Boolean = true,
withProgress: Boolean = false
) {
@@ -210,7 +353,8 @@ fun doFirResolveTestBench(
}
val bench = FirResolveBench(withProgress)
bench.processFiles(firFiles, transformers)
bench.parallelThreads = 1
bench.processFiles(firFiles, factory)
bench.report(System.out)
bench.throwFailure()
}
@@ -243,4 +387,12 @@ fun <T> Collection<T>.progress(step: Double = 0.1, computeLabel: (T) -> String):
}
progress++
}
}
private inline fun <T> measureNanoTimeWithResult(crossinline block: () -> T): Pair<T, Long> {
var result: Any? = null
val time = measureNanoTime {
result = block()
}
return result as T to time
}

View File

@@ -1,108 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.perf
import com.intellij.ide.impl.ProjectUtil
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ex.ApplicationEx
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl
import com.intellij.openapi.projectRoots.ProjectJdkTable
import com.intellij.psi.PsiManager
import com.intellij.psi.search.FileTypeIndex
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.testFramework.LightPlatformTestCase
import com.intellij.testFramework.ModuleTestCase
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.doFirResolveTestBench
import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.progress
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.caches.project.*
import org.jetbrains.kotlin.idea.fir.IdeFirDependenciesSymbolProvider
import org.jetbrains.kotlin.psi.KtFile
import java.io.File
import kotlin.test.Ignore
@Ignore(value = "[Simon Ogorodnik] turned off as it is suppose to be run manually")
class FirTotalKotlinResolveInIdeTest : ModuleTestCase() {
private val projectRootFile = File(".")
override fun setUpProject() {
(ApplicationManager.getApplication() as ApplicationEx).doNotSave()
myProject = ProjectUtil.openOrImport(projectRootFile.path, null, false)
LightPlatformTestCase.clearUncommittedDocuments(this.project)
this.runStartupActivities()
(FileTypeManager.getInstance() as FileTypeManagerImpl).drainReDetectQueue()
}
private lateinit var sessionProvider: FirProjectSessionProvider
private fun IdeaModuleInfo.createSession(): FirSession {
val moduleInfo = this
return FirJavaModuleBasedSession(
moduleInfo, sessionProvider, moduleInfo.contentScope(),
IdeFirDependenciesSymbolProvider(moduleInfo as ModuleSourceInfo, project, sessionProvider)
)
}
override fun setUp() {
super.setUp()
sessionProvider = FirProjectSessionProvider(project)
}
override fun tearDown() {
val jdkTable = ProjectJdkTable.getInstance()
runWriteAction {
for (sdk in jdkTable.allJdks) {
jdkTable.removeJdk(sdk)
}
}
super.tearDown()
}
fun testTotalKotlin() {
val psiManager = PsiManager.getInstance(project)
val files = FileTypeIndex.getFiles(KotlinFileType.INSTANCE, GlobalSearchScope.projectScope(project))
val firFiles = mutableListOf<FirFile>()
val sessionPerModule = mutableMapOf<ModuleInfo, FirSession>()
println("Got vfiles: ${files.size}")
files.mapNotNull {
val file = psiManager.findFile(it) as? KtFile ?: return@mapNotNull null
val moduleInfo = file.getNullableModuleInfo() as? ModuleSourceInfo ?: return@mapNotNull null
file to moduleInfo
}.progress("Loading FIR").forEach { (file, moduleInfo) ->
val session = sessionPerModule.getOrPut(moduleInfo) {
moduleInfo.createSession()
}
val builder = RawFirBuilder(session, stubMode = true)
try {
val firFile = builder.buildFirFile(file)
(session.service<FirProvider>() as FirProviderImpl).recordFile(firFile)
firFiles += firFile
} catch (e: Exception) {
System.err.println("Error building fir for $file")
e.printStackTrace()
}
}
println("Raw fir up, files: ${firFiles.size}")
doFirResolveTestBench(firFiles, FirTotalResolveTransformer().transformers, withProgress = true)
}
}

View File

@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.impl.FirCompositeSymbolProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.FirStagesTransformerFactory
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
import org.jetbrains.kotlin.fir.service
@@ -121,7 +121,7 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() {
return result!!
}
val transformer = FirTotalResolveTransformer()
val transformer = FirStagesTransformerFactory(sessions)
transformer.processFiles(firFiles)
for (file in firFiles) {
val firFileDump = StringBuilder().also { file.accept(FirRenderer(it), null) }.toString()