FIR2IR: fix handling constructors & their symbols (related also to local classes)

This commit is contained in:
Mikhail Glukhikh
2019-10-28 16:10:42 +03:00
parent 7dee1cd9d2
commit 384134a069
4 changed files with 42 additions and 52 deletions
@@ -423,22 +423,26 @@ class Fir2IrDeclarationStorage(
irParent: IrDeclarationParent? = null,
shouldLeaveScope: Boolean = false
): IrConstructor {
return constructorCache.getOrPut(constructor) {
val descriptor = WrappedClassConstructorDescriptor()
val origin = IrDeclarationOrigin.DEFINED
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 cached = constructorCache[constructor]
if (cached != null) {
return if (shouldLeaveScope) cached else cached.enterLocalScope(constructor)
}
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(
@@ -360,31 +360,17 @@ class Fir2IrVisitor(
overriddenSymbols += overriddenSymbol
}
}
body = firFunction?.body?.convertToIrBlockBody()
if (this !is IrConstructor) {
// Scope for primary constructor should be left after class declaration
// Scope for secondary constructor should be left after delegating call
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)
}.withParent {
if (!parentAsClass.isAnnotationClass) {
val body = this.body as IrBlockBody? ?: IrBlockBodyImpl(startOffset, endOffset)
val delegatedConstructor = constructor.delegatedConstructor
var body = firFunction?.body?.convertToIrBlockBody()
if (firFunction is FirConstructor && this is IrConstructor && !parentAsClass.isAnnotationClass) {
if (body == null) {
body = IrBlockBodyImpl(startOffset, endOffset)
}
val delegatedConstructor = firFunction.delegatedConstructor
if (delegatedConstructor != null) {
val irDelegatingConstructorCall = delegatedConstructor.toIrDelegatingConstructorCall()
body.statements += irDelegatingConstructorCall ?: delegatedConstructor.convertWithOffsets { startOffset, endOffset ->
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()) {
this.body = body
}
} else if (this !is IrConstructor) {
this.body = body
}
if (!constructor.isPrimary) {
declarationStorage.leaveScope(irConstructor.descriptor)
if (this !is IrConstructor || !this.isPrimary) {
// 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 {
@@ -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
View File
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
fun outer() {
class LocalClass {
fun foo() {}