Fix for KT-26500 (#1972)

This commit is contained in:
Sergey Bogolepov
2018-08-30 17:23:46 +03:00
committed by GitHub
parent fb1be9b969
commit 8468c00bda
@@ -5,13 +5,14 @@
package org.jetbrains.kotlin.backend.konan.lower package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext
import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.descriptors.impl.*
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
@@ -765,7 +766,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>) { fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>) {
descriptorSubstituteMap.forEach { t, u -> descriptorSubstituteMap.forEach { t, u ->
globalSubstituteMap.put(t, SubstitutedDescriptor(targetDescriptor, u)) globalSubstituteMap[t] = SubstitutedDescriptor(targetDescriptor, u)
} }
} }
@@ -799,21 +800,16 @@ private fun <K, V> Map<K, V>.deepSearch(key: K, typeMapper: (V) -> K?): V? {
return result return result
} }
internal class DescriptorSubstitutorForExternalScope( /**
val globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>, * Maps old variables to new ones that have fixed type.
val context: Context */
) private fun createVariableSubstitutionMap(element: IrElement,
: IrElementTransformerVoidWithContext() { globalSubstituteMap: Map<DeclarationDescriptor, SubstitutedDescriptor>)
: Map<VariableDescriptor, VariableDescriptor> {
private val variableSubstituteMap = mutableMapOf<VariableDescriptor, VariableDescriptor>() val variableSubstituteMap = mutableMapOf<VariableDescriptor, VariableDescriptor>()
fun run(element: IrElement) { element.acceptChildrenVoid(object: IrElementVisitorVoidWithContextFixed() {
collectVariables(element)
element.transformChildrenVoid(this)
}
private fun collectVariables(element: IrElement) {
element.acceptChildrenVoid(object: IrElementVisitorVoid {
override fun visitElement(element: IrElement) { override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this) element.acceptChildrenVoid(this)
} }
@@ -844,9 +840,7 @@ internal class DescriptorSubstitutorForExternalScope(
// So we have to search recursively inside the map to find correct descriptor. // So we have to search recursively inside the map to find correct descriptor.
val typeMapper: (SubstitutedDescriptor) -> ClassDescriptor? = { it.descriptor as? ClassDescriptor } val typeMapper: (SubstitutedDescriptor) -> ClassDescriptor? = { it.descriptor as? ClassDescriptor }
val substitutedDescriptor = oldClassDescriptor?.let { globalSubstituteMap.deepSearch(it, typeMapper) } val substitutedDescriptor = oldClassDescriptor?.let { globalSubstituteMap.deepSearch(it, typeMapper) }
// should be true for empty allScopes if (substitutedDescriptor != null && allScopes.all { it.scope.scopeOwner != substitutedDescriptor.inlinedFunction }) {
if (substitutedDescriptor == null || allScopes.all { it.scope.scopeOwner != substitutedDescriptor.inlinedFunction })
return
val newDescriptor = IrTemporaryVariableDescriptorImpl( val newDescriptor = IrTemporaryVariableDescriptorImpl(
containingDeclaration = oldDescriptor.containingDeclaration, containingDeclaration = oldDescriptor.containingDeclaration,
name = oldDescriptor.name, name = oldDescriptor.name,
@@ -854,7 +848,23 @@ internal class DescriptorSubstitutorForExternalScope(
isMutable = oldDescriptor.isVar) isMutable = oldDescriptor.isVar)
variableSubstituteMap[oldDescriptor] = newDescriptor variableSubstituteMap[oldDescriptor] = newDescriptor
} }
}
}) })
return variableSubstituteMap
}
internal class DescriptorSubstitutorForExternalScope(
val globalSubstituteMap: Map<DeclarationDescriptor, SubstitutedDescriptor>,
val context: Context
)
: IrElementTransformerVoidWithContext() {
private val variableSubstituteMap = mutableMapOf<VariableDescriptor, VariableDescriptor>()
fun run(element: IrElement) {
variableSubstituteMap += createVariableSubstitutionMap(element, globalSubstituteMap)
element.transformChildrenVoid(this)
} }
override fun visitCall(expression: IrCall): IrExpression { override fun visitCall(expression: IrCall): IrExpression {
@@ -951,3 +961,71 @@ internal class DescriptorSubstitutorForExternalScope(
} }
} }
// TODO: Move to big kotlin
abstract class IrElementVisitorVoidWithContextFixed : IrElementVisitorVoid {
private val scopeStack = mutableListOf<ScopeWithIr>()
override final fun visitFile(declaration: IrFile) {
scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
visitFileNew(declaration)
scopeStack.pop()
}
override final fun visitClass(declaration: IrClass) {
scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
visitClassNew(declaration)
scopeStack.pop()
}
override final fun visitProperty(declaration: IrProperty) {
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
visitPropertyNew(declaration)
scopeStack.pop()
}
override final fun visitField(declaration: IrField) {
val isDelegated = declaration.descriptor.isDelegated
if (isDelegated) scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
visitFieldNew(declaration)
if (isDelegated) scopeStack.pop()
}
override final fun visitFunction(declaration: IrFunction) {
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
visitFunctionNew(declaration)
scopeStack.pop()
}
protected val currentFile get() = scopeStack.lastOrNull { it.scope.scopeOwner is PackageFragmentDescriptor }
protected val currentClass get() = scopeStack.lastOrNull { it.scope.scopeOwner is ClassDescriptor }
protected val currentFunction get() = scopeStack.lastOrNull { it.scope.scopeOwner is FunctionDescriptor }
protected val currentProperty get() = scopeStack.lastOrNull { it.scope.scopeOwner is PropertyDescriptor }
protected val currentScope get() = scopeStack.peek()
protected val parentScope get() = if (scopeStack.size < 2) null else scopeStack[scopeStack.size - 2]
protected val allScopes get() = scopeStack
fun printScopeStack() {
scopeStack.forEach { println(it.scope.scopeOwner) }
}
open fun visitFileNew(declaration: IrFile) {
super.visitFile(declaration)
}
open fun visitClassNew(declaration: IrClass) {
super.visitClass(declaration)
}
open fun visitFunctionNew(declaration: IrFunction) {
super.visitFunction(declaration)
}
open fun visitPropertyNew(declaration: IrProperty) {
super.visitProperty(declaration)
}
open fun visitFieldNew(declaration: IrField) {
super.visitField(declaration)
}
}