FIR2IR: fix handling constructors & their symbols (related also to local classes)
This commit is contained in:
+19
-15
@@ -423,22 +423,26 @@ class Fir2IrDeclarationStorage(
|
|||||||
irParent: IrDeclarationParent? = null,
|
irParent: IrDeclarationParent? = null,
|
||||||
shouldLeaveScope: Boolean = false
|
shouldLeaveScope: Boolean = false
|
||||||
): IrConstructor {
|
): IrConstructor {
|
||||||
return constructorCache.getOrPut(constructor) {
|
val cached = constructorCache[constructor]
|
||||||
val descriptor = WrappedClassConstructorDescriptor()
|
if (cached != null) {
|
||||||
val origin = IrDeclarationOrigin.DEFINED
|
return if (shouldLeaveScope) cached else cached.enterLocalScope(constructor)
|
||||||
val isPrimary = constructor.isPrimary
|
|
||||||
return constructor.convertWithOffsets { startOffset, endOffset ->
|
|
||||||
irSymbolTable.declareConstructor(startOffset, endOffset, origin, descriptor) { symbol ->
|
|
||||||
IrConstructorImpl(
|
|
||||||
startOffset, endOffset, origin, symbol,
|
|
||||||
constructor.name, constructor.visibility,
|
|
||||||
constructor.returnTypeRef.toIrType(session, this),
|
|
||||||
isInline = false, isExternal = false, isPrimary = isPrimary, isExpect = false
|
|
||||||
).bindAndDeclareParameters(constructor, descriptor, irParent, isStatic = true, shouldLeaveScope = shouldLeaveScope)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val descriptor = WrappedClassConstructorDescriptor()
|
||||||
|
val origin = IrDeclarationOrigin.DEFINED
|
||||||
|
val isPrimary = constructor.isPrimary
|
||||||
|
val created = constructor.convertWithOffsets { startOffset, endOffset ->
|
||||||
|
irSymbolTable.declareConstructor(startOffset, endOffset, origin, descriptor) { symbol ->
|
||||||
|
IrConstructorImpl(
|
||||||
|
startOffset, endOffset, origin, symbol,
|
||||||
|
constructor.name, constructor.visibility,
|
||||||
|
constructor.returnTypeRef.toIrType(session, this),
|
||||||
|
isInline = false, isExternal = false, isPrimary = isPrimary, isExpect = false
|
||||||
|
).bindAndDeclareParameters(constructor, descriptor, irParent, isStatic = true, shouldLeaveScope = shouldLeaveScope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
constructorCache[constructor] = created
|
||||||
|
return created
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createIrPropertyAccessor(
|
private fun createIrPropertyAccessor(
|
||||||
|
|||||||
@@ -360,31 +360,17 @@ class Fir2IrVisitor(
|
|||||||
overriddenSymbols += overriddenSymbol
|
overriddenSymbols += overriddenSymbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
body = firFunction?.body?.convertToIrBlockBody()
|
var body = firFunction?.body?.convertToIrBlockBody()
|
||||||
if (this !is IrConstructor) {
|
if (firFunction is FirConstructor && this is IrConstructor && !parentAsClass.isAnnotationClass) {
|
||||||
// Scope for primary constructor should be left after class declaration
|
if (body == null) {
|
||||||
// Scope for secondary constructor should be left after delegating call
|
body = IrBlockBodyImpl(startOffset, endOffset)
|
||||||
declarationStorage.leaveScope(descriptor)
|
}
|
||||||
}
|
val delegatedConstructor = firFunction.delegatedConstructor
|
||||||
}
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitConstructor(constructor: FirConstructor, data: Any?): IrElement {
|
|
||||||
val irConstructor = declarationStorage.getIrConstructor(
|
|
||||||
constructor, irParent = parentStack.last() as? IrClass
|
|
||||||
)
|
|
||||||
return irConstructor.setParentByParentStack().withFunction {
|
|
||||||
setFunctionContent(irConstructor.descriptor, constructor)
|
|
||||||
}.withParent {
|
|
||||||
if (!parentAsClass.isAnnotationClass) {
|
|
||||||
val body = this.body as IrBlockBody? ?: IrBlockBodyImpl(startOffset, endOffset)
|
|
||||||
val delegatedConstructor = constructor.delegatedConstructor
|
|
||||||
if (delegatedConstructor != null) {
|
if (delegatedConstructor != null) {
|
||||||
val irDelegatingConstructorCall = delegatedConstructor.toIrDelegatingConstructorCall()
|
val irDelegatingConstructorCall = delegatedConstructor.toIrDelegatingConstructorCall()
|
||||||
body.statements += irDelegatingConstructorCall ?: delegatedConstructor.convertWithOffsets { startOffset, endOffset ->
|
body.statements += irDelegatingConstructorCall ?: delegatedConstructor.convertWithOffsets { startOffset, endOffset ->
|
||||||
IrErrorCallExpressionImpl(
|
IrErrorCallExpressionImpl(
|
||||||
startOffset, endOffset, irConstructor.returnType, "Cannot find delegated constructor call"
|
startOffset, endOffset, returnType, "Cannot find delegated constructor call"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -397,11 +383,24 @@ class Fir2IrVisitor(
|
|||||||
if (body.statements.isNotEmpty()) {
|
if (body.statements.isNotEmpty()) {
|
||||||
this.body = body
|
this.body = body
|
||||||
}
|
}
|
||||||
|
} else if (this !is IrConstructor) {
|
||||||
|
this.body = body
|
||||||
}
|
}
|
||||||
if (!constructor.isPrimary) {
|
if (this !is IrConstructor || !this.isPrimary) {
|
||||||
declarationStorage.leaveScope(irConstructor.descriptor)
|
// Scope for primary constructor should be left after class declaration
|
||||||
|
declarationStorage.leaveScope(descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitConstructor(constructor: FirConstructor, data: Any?): IrElement {
|
||||||
|
val irConstructor = declarationStorage.getIrConstructor(
|
||||||
|
constructor, irParent = parentStack.last() as? IrClass
|
||||||
|
)
|
||||||
|
return irConstructor.setParentByParentStack().withFunction {
|
||||||
|
setFunctionContent(irConstructor.descriptor, constructor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: Any?): IrElement {
|
override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: Any?): IrElement {
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
FILE fqName:<root> fileName:/localClasses.kt
|
|
||||||
FUN name:outer visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
|
||||||
BLOCK_BODY
|
|
||||||
CLASS CLASS name:LocalClass modality:FINAL visibility:local superTypes:[kotlin.Any]
|
|
||||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.outer.LocalClass
|
|
||||||
CONSTRUCTOR visibility:public <> () returnType:IrErrorType [primary]
|
|
||||||
BLOCK_BODY
|
|
||||||
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
|
|
||||||
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:LocalClass modality:FINAL visibility:local superTypes:[kotlin.Any]'
|
|
||||||
FUN name:foo visibility:public modality:FINAL <> ($this:<root>.outer.LocalClass) returnType:kotlin.Unit
|
|
||||||
$this: VALUE_PARAMETER name:<this> type:<root>.outer.LocalClass
|
|
||||||
BLOCK_BODY
|
|
||||||
ERROR_CALL 'Unresolved reference: <Unresolved name: foo>#' type=IrErrorType
|
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
fun outer() {
|
fun outer() {
|
||||||
class LocalClass {
|
class LocalClass {
|
||||||
fun foo() {}
|
fun foo() {}
|
||||||
|
|||||||
Reference in New Issue
Block a user