FIR2IR: convert qualifiers inside getClass properly

This commit is contained in:
Mikhail Glukhikh
2020-03-10 16:52:50 +03:00
parent 1812b490a1
commit 8231377f6b
15 changed files with 43 additions and 48 deletions
@@ -597,6 +597,7 @@ class Fir2IrVisitor(
private fun FirQualifiedAccess.findIrReceiver(isDispatch: Boolean): IrExpression? {
val firReceiver = if (isDispatch) dispatchReceiver else extensionReceiver
if (firReceiver is FirResolvedQualifier) return firReceiver.toGetObject()
return firReceiver.takeIf { it !is FirNoReceiverExpression }?.toIrExpression()
?: explicitReceiver?.toIrExpression() // NB: this applies to the situation when call is unresolved
?: run {
@@ -1213,20 +1214,29 @@ class Fir2IrVisitor(
}
override fun visitGetClassCall(getClassCall: FirGetClassCall, data: Any?): IrElement {
val argument = getClassCall.argument
val irType = getClassCall.typeRef.toIrType()
val irClassType = argument.typeRef.toIrType()
val irClassReferenceSymbol = when (argument) {
is FirResolvedReifiedParameterReference -> {
declarationStorage.getIrTypeParameterSymbol(argument.symbol, ConversionTypeContext.DEFAULT)
}
is FirResolvedQualifier -> {
val symbol = argument.symbol as? FirClassSymbol
?: return getClassCall.convertWithOffsets { startOffset, endOffset ->
IrErrorCallExpressionImpl(
startOffset, endOffset, irType, "Resolved qualifier ${argument.render()} does not have correct symbol"
)
}
declarationStorage.getIrClassSymbol(symbol)
}
else -> null
}
return getClassCall.convertWithOffsets { startOffset, endOffset ->
val argument = getClassCall.argument
val irType = getClassCall.typeRef.toIrType()
if (argument is FirResolvedReifiedParameterReference) {
IrClassReferenceImpl(
startOffset, endOffset, irType,
declarationStorage.getIrTypeParameterSymbol(argument.symbol, ConversionTypeContext.DEFAULT),
argument.typeRef.toIrType()
)
if (irClassReferenceSymbol != null) {
IrClassReferenceImpl(startOffset, endOffset, irType, irClassReferenceSymbol, irClassType)
} else {
IrGetClassImpl(
startOffset, endOffset, irType,
argument.toIrExpression()
)
IrGetClassImpl(startOffset, endOffset, irType, argument.toIrExpression())
}
}
}
@@ -1240,25 +1250,26 @@ class Fir2IrVisitor(
}
}
override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: Any?): IrElement {
val classSymbol = resolvedQualifier.symbol
if (classSymbol != null) {
val resultingSymbol = when (val klass = classSymbol.fir) {
is FirRegularClass -> {
if (klass.classKind in listOf(ClassKind.OBJECT, ClassKind.ENUM_ENTRY)) classSymbol
else klass.companionObject?.symbol ?: classSymbol
}
else -> classSymbol
}
return resolvedQualifier.convertWithOffsets { startOffset, endOffset ->
private fun FirResolvedQualifier.toGetObject(): IrExpression {
val irType = typeRef.toIrType()
val typeRef = typeRef as? FirResolvedTypeRef
val classSymbol = (typeRef?.type as? ConeClassLikeType)?.lookupTag?.toSymbol(session)
return convertWithOffsets { startOffset, endOffset ->
if (classSymbol != null) {
IrGetObjectValueImpl(
startOffset, endOffset,
resolvedQualifier.typeRef.toIrType(),
resultingSymbol.toIrSymbol(session, declarationStorage) as IrClassSymbol
startOffset, endOffset, irType,
classSymbol.toIrSymbol(session, declarationStorage) as IrClassSymbol
)
} else {
IrErrorCallExpressionImpl(
startOffset, endOffset, irType, "Resolved qualifier ${render()} does not have correctly resolved type"
)
}
}
return visitElement(resolvedQualifier, data)
}
override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: Any?): IrElement {
return resolvedQualifier.toGetObject()
}
override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: Any?): IrElement {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FULL_JDK
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: enable
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: enable
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: enable
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
package test
import test.C.E1
@@ -1,5 +1,4 @@
// !LANGUAGE: +BareArrayClassLiteral
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
object OHolder {
val O = "O"
}
@@ -20,14 +20,12 @@ FILE fqName:<root> fileName:/classReference.kt
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
GET_CLASS type=kotlin.reflect.KClass<<root>.A>
GET_OBJECT 'CLASS CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
CLASS_REFERENCE 'CLASS CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<<root>.A>
GET_CLASS type=kotlin.reflect.KClass<<root>.A>
CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.A' type=<root>.A origin=null
CALL 'public final fun <get-java> <T> (): java.lang.Class<T of kotlin.jvm.<get-java>> declared in kotlin.jvm' type=java.lang.Class<<root>.A> origin=GET_PROPERTY
<T>: <root>.A
$receiver: GET_CLASS type=kotlin.reflect.KClass<<root>.A>
GET_OBJECT 'CLASS CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
$receiver: CLASS_REFERENCE 'CLASS CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<<root>.A>
CALL 'public final fun <get-java> <T> (): java.lang.Class<T of kotlin.jvm.<get-java>> declared in kotlin.jvm' type=java.lang.Class<<root>.A> origin=GET_PROPERTY
<T>: <root>.A
$receiver: GET_CLASS type=kotlin.reflect.KClass<<root>.A>
@@ -20,9 +20,7 @@ FILE fqName:<root> fileName:/objectClassReference.kt
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit
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
CLASS_REFERENCE 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<<root>.A>
CALL 'public final fun <get-java> <T> (): java.lang.Class<T of kotlin.jvm.<get-java>> declared in kotlin.jvm' type=java.lang.Class<<root>.A> origin=GET_PROPERTY
<T>: <root>.A
$receiver: GET_CLASS type=kotlin.reflect.KClass<<root>.A>
GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
$receiver: CLASS_REFERENCE 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<<root>.A>
@@ -35,8 +35,7 @@ FILE fqName:<root> fileName:/reflectionLiterals.kt
PROPERTY name:test1 visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.reflect.KClass<<root>.A> visibility:private [final,static]
EXPRESSION_BODY
GET_CLASS type=kotlin.reflect.KClass<<root>.A>
GET_OBJECT 'CLASS CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
CLASS_REFERENCE 'CLASS CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<<root>.A>
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:kotlin.reflect.KClass<<root>.A>
correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [val]
BLOCK_BODY