K2 Scripting: fix capturing in scripts created from Fir
This commit is contained in:
committed by
Space Team
parent
00211a5fc9
commit
07df03dbec
@@ -607,6 +607,17 @@ class Fir2IrVisitor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (boundSymbol is FirScriptSymbol && calleeReference.contextReceiverNumber >= 0) {
|
||||||
|
val firScript = boundSymbol.fir
|
||||||
|
val irScript = declarationStorage.getCachedIrScript(firScript) ?: error("IrScript for ${firScript.name} not found")
|
||||||
|
val receiverParameter = irScript.implicitReceiversParameters.find { it.index == calleeReference.contextReceiverNumber }
|
||||||
|
if (receiverParameter != null) {
|
||||||
|
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
|
||||||
|
IrGetValueImpl(startOffset, endOffset, receiverParameter.type, receiverParameter.symbol)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error("Expecting implicit receiver") // TODO: check if any valid situations possible here
|
||||||
|
}
|
||||||
} else if (boundSymbol is FirCallableSymbol) {
|
} else if (boundSymbol is FirCallableSymbol) {
|
||||||
val irFunction = when (boundSymbol) {
|
val irFunction = when (boundSymbol) {
|
||||||
is FirFunctionSymbol -> declarationStorage.getIrFunctionSymbol(boundSymbol).owner
|
is FirFunctionSymbol -> declarationStorage.getIrFunctionSymbol(boundSymbol).owner
|
||||||
|
|||||||
+10
@@ -283,6 +283,7 @@ class ClosureAnnotator(irElement: IrElement, declaration: IrDeclaration) {
|
|||||||
|
|
||||||
override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: ClosureBuilder?) {
|
override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: ClosureBuilder?) {
|
||||||
super.visitFunctionAccess(expression, data)
|
super.visitFunctionAccess(expression, data)
|
||||||
|
processScriptCapturing(expression.dispatchReceiver, expression.symbol.owner, data)
|
||||||
processMemberAccess(expression.symbol.owner, data)
|
processMemberAccess(expression.symbol.owner, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,6 +311,15 @@ class ClosureAnnotator(irElement: IrElement, declaration: IrDeclaration) {
|
|||||||
typeParameterContainerScopeBuilder?.seeType(expression.type)
|
typeParameterContainerScopeBuilder?.seeType(expression.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun processScriptCapturing(receiverExpression: IrExpression?, declaration: IrDeclaration, data: ClosureBuilder?) {
|
||||||
|
if (receiverExpression == null) {
|
||||||
|
val parent = declaration.parent
|
||||||
|
if (parent is IrScript && parent.thisReceiver != null) {
|
||||||
|
data?.seeVariable(parent.thisReceiver!!.symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun processMemberAccess(declaration: IrDeclaration, parentClosure: ClosureBuilder?) {
|
private fun processMemberAccess(declaration: IrDeclaration, parentClosure: ClosureBuilder?) {
|
||||||
if (declaration.isLocal) {
|
if (declaration.isLocal) {
|
||||||
if (declaration is IrSimpleFunction && declaration.visibility != DescriptorVisibilities.LOCAL) {
|
if (declaration is IrSimpleFunction && declaration.visibility != DescriptorVisibilities.LOCAL) {
|
||||||
|
|||||||
+14
-10
@@ -109,6 +109,16 @@ private class ScriptsToClassesLowering(val context: JvmBackendContext, val inner
|
|||||||
private fun collectCapturingClasses(irScript: IrScript, typeRemapper: SimpleTypeRemapper): Set<IrClassImpl> {
|
private fun collectCapturingClasses(irScript: IrScript, typeRemapper: SimpleTypeRemapper): Set<IrClassImpl> {
|
||||||
val annotator = ClosureAnnotator(irScript, irScript)
|
val annotator = ClosureAnnotator(irScript, irScript)
|
||||||
val capturingClasses = mutableSetOf<IrClassImpl>()
|
val capturingClasses = mutableSetOf<IrClassImpl>()
|
||||||
|
|
||||||
|
val scriptsReceivers = mutableSetOf<IrType>().also {
|
||||||
|
it.addIfNotNull(irScript.thisReceiver?.type)
|
||||||
|
}
|
||||||
|
irScript.earlierScripts?.forEach { scriptsReceivers.addIfNotNull(it.owner.thisReceiver?.type) }
|
||||||
|
irScript.implicitReceiversParameters.forEach {
|
||||||
|
scriptsReceivers.add(it.type)
|
||||||
|
scriptsReceivers.add(typeRemapper.remapType(it.type))
|
||||||
|
}
|
||||||
|
|
||||||
val collector = object : IrElementVisitorVoid {
|
val collector = object : IrElementVisitorVoid {
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitElement(element: IrElement) {
|
||||||
element.acceptChildrenVoid(this)
|
element.acceptChildrenVoid(this)
|
||||||
@@ -117,15 +127,6 @@ private class ScriptsToClassesLowering(val context: JvmBackendContext, val inner
|
|||||||
override fun visitClass(declaration: IrClass) {
|
override fun visitClass(declaration: IrClass) {
|
||||||
if (declaration is IrClassImpl && !declaration.isInner) {
|
if (declaration is IrClassImpl && !declaration.isInner) {
|
||||||
val closure = annotator.getClassClosure(declaration)
|
val closure = annotator.getClassClosure(declaration)
|
||||||
val scriptsReceivers = mutableSetOf<IrType>().also {
|
|
||||||
it.addIfNotNull(irScript.thisReceiver?.type)
|
|
||||||
}
|
|
||||||
irScript.earlierScripts?.forEach { scriptsReceivers.addIfNotNull(it.owner.thisReceiver?.type) }
|
|
||||||
irScript.implicitReceiversParameters.forEach {
|
|
||||||
scriptsReceivers.add(it.type)
|
|
||||||
scriptsReceivers.add(typeRemapper.remapType(it.type))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closure.capturedValues.any { it.owner.type in scriptsReceivers }) {
|
if (closure.capturedValues.any { it.owner.type in scriptsReceivers }) {
|
||||||
fun reportError(factory: KtDiagnosticFactory1<String>, name: Name? = null) {
|
fun reportError(factory: KtDiagnosticFactory1<String>, name: Name? = null) {
|
||||||
context.ktDiagnosticReporter.at(declaration).report(factory, (name ?: declaration.name).asString())
|
context.ktDiagnosticReporter.at(declaration).report(factory, (name ?: declaration.name).asString())
|
||||||
@@ -854,7 +855,7 @@ private class ScriptToClassTransformer(
|
|||||||
}
|
}
|
||||||
} else if (irScript.needsReceiverProcessing) {
|
} else if (irScript.needsReceiverProcessing) {
|
||||||
val getValueParameter = expression.symbol.owner as? IrValueParameter
|
val getValueParameter = expression.symbol.owner as? IrValueParameter
|
||||||
if (getValueParameter != null && getValueParameter.name == SpecialNames.THIS) {
|
if (getValueParameter != null && isValidNameForReceiver(getValueParameter.name)) {
|
||||||
val newExpression = getDispatchReceiverExpression(
|
val newExpression = getDispatchReceiverExpression(
|
||||||
data, expression, getValueParameter.type, expression.origin, getValueParameter
|
data, expression, getValueParameter.type, expression.origin, getValueParameter
|
||||||
)
|
)
|
||||||
@@ -866,6 +867,9 @@ private class ScriptToClassTransformer(
|
|||||||
return super.visitGetValue(expression, data)
|
return super.visitGetValue(expression, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isValidNameForReceiver(name: Name) =
|
||||||
|
name == SpecialNames.THIS || irScript.implicitReceiversParameters.any { it.name == name }
|
||||||
|
|
||||||
private fun IrDeclaration.isCurrentScriptTopLevelDeclaration(data: ScriptToClassTransformerContext): Boolean {
|
private fun IrDeclaration.isCurrentScriptTopLevelDeclaration(data: ScriptToClassTransformerContext): Boolean {
|
||||||
if (data.topLevelDeclaration == null || (parent != irScript && parent != irScriptClass)) return false
|
if (data.topLevelDeclaration == null || (parent != irScript && parent != irScriptClass)) return false
|
||||||
val declarationToCompare = if (this is IrFunction) this.propertyIfAccessor else this
|
val declarationToCompare = if (this is IrFunction) this.propertyIfAccessor else this
|
||||||
|
|||||||
Vendored
-1
@@ -1,6 +1,5 @@
|
|||||||
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
|
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_K2: JVM_IR
|
|
||||||
|
|
||||||
// expected: rv: kotlin.Unit
|
// expected: rv: kotlin.Unit
|
||||||
|
|
||||||
|
|||||||
Vendored
-1
@@ -1,6 +1,5 @@
|
|||||||
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
|
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
|
||||||
// IGNORE_BACKEND: JVM
|
// IGNORE_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_K2: JVM_IR
|
|
||||||
|
|
||||||
// expected: rv: kotlin.Unit
|
// expected: rv: kotlin.Unit
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user