[FIR] Support IntegerLiteralTypes

This commit is contained in:
Dmitriy Novozhilov
2019-12-09 15:02:55 +03:00
parent 5577f0f8cb
commit b76c984b26
145 changed files with 1815 additions and 585 deletions
@@ -37,6 +37,9 @@ object StandardClassIds {
val KProperty = "KProperty".reflectId() val KProperty = "KProperty".reflectId()
val Comparable = "Comparable".baseId()
val Number = "Number".baseId()
fun byName(name: String) = name.baseId() fun byName(name: String) = name.baseId()
fun reflectByName(name: String) = name.reflectId() fun reflectByName(name: String) = name.reflectId()
@@ -5,10 +5,14 @@
package org.jetbrains.kotlin.fir.types package org.jetbrains.kotlin.fir.types
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.types.model.*
sealed class ConeKotlinTypeProjection : TypeArgumentMarker { sealed class ConeKotlinTypeProjection : TypeArgumentMarker {
@@ -230,3 +234,33 @@ open class ConeTypeVariable(name: String) : TypeVariableMarker {
class ConeTypeVariableTypeConstructor(val debugName: String) : ConeClassifierLookupTag(), TypeVariableTypeConstructorMarker { class ConeTypeVariableTypeConstructor(val debugName: String) : ConeClassifierLookupTag(), TypeVariableTypeConstructorMarker {
override val name: Name get() = Name.identifier(debugName) override val name: Name get() = Name.identifier(debugName)
} }
abstract class ConeIntegerLiteralType(val value: Long) : ConeKotlinType(), SimpleTypeMarker, TypeConstructorMarker {
abstract val possibleTypes: Collection<ConeClassLikeType>
abstract val supertypes: List<ConeClassLikeType>
override val typeArguments: Array<out ConeKotlinTypeProjection> = emptyArray()
override val nullability: ConeNullability = ConeNullability.NOT_NULL
abstract fun getApproximatedType(expectedType: ConeKotlinType? = null): ConeClassLikeType
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as ConeIntegerLiteralType
if (possibleTypes != other.possibleTypes) return false
if (nullability != other.nullability) return false
return true
}
override fun hashCode(): Int {
return 31 * possibleTypes.hashCode() + nullability.hashCode()
}
}
fun ConeIntegerLiteralType.canBeInt(): Boolean {
return value in Int.MIN_VALUE..Int.MAX_VALUE
}
@@ -46,6 +46,7 @@ fun ConeKotlinType.render(): String {
) )
} }
is ConeStubType -> "stub type: $variable" is ConeStubType -> "stub type: $variable"
is ConeIntegerLiteralType -> "ILT: $value"
} + nullabilitySuffix } + nullabilitySuffix
} }
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirTypePlaceholderProjection import org.jetbrains.kotlin.fir.types.impl.FirTypePlaceholderProjection
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -728,38 +727,38 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
private fun FlowContent.generate(expression: FirConstExpression<*>) { private fun FlowContent.generate(expression: FirConstExpression<*>) {
val value = expression.value val value = expression.value
if (value == null && expression.kind != IrConstKind.Null) { if (value == null && expression.kind != FirConstKind.Null) {
return error { return error {
+"null value" +"null value"
} }
} }
when (expression.kind) { when (expression.kind) {
IrConstKind.Null -> keyword("null") FirConstKind.Null -> keyword("null")
IrConstKind.Boolean -> keyword(value.toString()) FirConstKind.Boolean -> keyword(value.toString())
IrConstKind.String, IrConstKind.Char -> FirConstKind.String, FirConstKind.Char ->
stringLiteral(value) stringLiteral(value)
IrConstKind.Byte -> { FirConstKind.Byte -> {
+value.toString() +value.toString()
keyword("B") keyword("B")
} }
IrConstKind.Short -> { FirConstKind.Short -> {
+value.toString() +value.toString()
keyword("S") keyword("S")
} }
IrConstKind.Int -> { FirConstKind.Int -> {
+value.toString() +value.toString()
keyword("I") keyword("I")
} }
IrConstKind.Long -> { FirConstKind.Long -> {
+value.toString() +value.toString()
keyword("L") keyword("L")
} }
IrConstKind.Float -> { FirConstKind.Float -> {
+value.toString() +value.toString()
keyword("F") keyword("F")
} }
IrConstKind.Double -> { FirConstKind.Double -> {
+value.toString() +value.toString()
keyword("D") keyword("D")
} }
@@ -784,6 +783,7 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
+"!!" +"!!"
} }
is ConeIntersectionType -> resolved { generate(type) } is ConeIntersectionType -> resolved { generate(type) }
is ConeIntegerLiteralType -> inlineUnsupported(type)
} }
if (type.typeArguments.isNotEmpty()) { if (type.typeArguments.isNotEmpty()) {
+"<" +"<"
@@ -73,6 +73,7 @@ fun ConeKotlinType.toIrType(session: FirSession, declarationStorage: Fir2IrDecla
intersectedTypes.first().toIrType(session, declarationStorage, definitelyNotNull) intersectedTypes.first().toIrType(session, declarationStorage, definitelyNotNull)
} }
is ConeStubType -> createErrorType() is ConeStubType -> createErrorType()
is ConeIntegerLiteralType -> getApproximatedType().toIrType(session, declarationStorage, definitelyNotNull)
} }
} }
@@ -23,12 +23,16 @@ import org.jetbrains.kotlin.fir.resolve.buildUseSiteMemberScope
import org.jetbrains.kotlin.fir.resolve.calls.SyntheticPropertySymbol import org.jetbrains.kotlin.fir.resolve.calls.SyntheticPropertySymbol
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.IntegerLiteralTypeApproximationTransformer
import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperator
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
import org.jetbrains.kotlin.fir.symbols.AccessorSymbol import org.jetbrains.kotlin.fir.symbols.AccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
@@ -71,6 +75,8 @@ class Fir2IrVisitor(
private val UNARY_OPERATIONS: Set<FirOperation> = EnumSet.of(FirOperation.EXCL) private val UNARY_OPERATIONS: Set<FirOperation> = EnumSet.of(FirOperation.EXCL)
} }
private val integerApproximator = IntegerLiteralTypeApproximationTransformer(session.firSymbolProvider, session.typeContext)
private val typeContext = session.typeContext private val typeContext = session.typeContext
private val declarationStorage = Fir2IrDeclarationStorage(session, symbolTable, moduleDescriptor) private val declarationStorage = Fir2IrDeclarationStorage(session, symbolTable, moduleDescriptor)
@@ -822,6 +828,11 @@ class Fir2IrVisitor(
} }
override fun visitFunctionCall(functionCall: FirFunctionCall, data: Any?): IrElement { override fun visitFunctionCall(functionCall: FirFunctionCall, data: Any?): IrElement {
val functionCall = if (functionCall.toResolvedCallableSymbol()?.fir is FirIntegerOperator) {
functionCall.copy().transformSingle(integerApproximator, null)
} else {
functionCall
}
return functionCall.toIrExpression(functionCall.typeRef).applyCallArguments(functionCall).applyTypeArguments(functionCall) return functionCall.toIrExpression(functionCall.typeRef).applyCallArguments(functionCall).applyTypeArguments(functionCall)
.applyReceivers(functionCall) .applyReceivers(functionCall)
} }
@@ -916,10 +927,23 @@ class Fir2IrVisitor(
override fun <T> visitConstExpression(constExpression: FirConstExpression<T>, data: Any?): IrElement { override fun <T> visitConstExpression(constExpression: FirConstExpression<T>, data: Any?): IrElement {
return constExpression.convertWithOffsets { startOffset, endOffset -> return constExpression.convertWithOffsets { startOffset, endOffset ->
@Suppress("UNCHECKED_CAST")
val kind = constExpression.getIrConstKind() as IrConstKind<T>
@Suppress("UNCHECKED_CAST")
val value = (constExpression.value as? Long)?.let {
when (kind) {
IrConstKind.Byte -> it.toByte()
IrConstKind.Short -> it.toShort()
IrConstKind.Int -> it.toInt()
IrConstKind.Float -> it.toFloat()
IrConstKind.Double -> it.toDouble()
else -> it
}
} as T ?: constExpression.value
IrConstImpl( IrConstImpl(
startOffset, endOffset, startOffset, endOffset,
constExpression.typeRef.toIrType(session, declarationStorage), constExpression.typeRef.toIrType(session, declarationStorage),
constExpression.kind, constExpression.value kind, value
) )
} }
} }
@@ -222,7 +222,7 @@ private fun ConeKotlinType.mapToCanonicalString(session: FirSession): String {
return when (this) { return when (this) {
is ConeClassLikeType -> mapToCanonicalString(session) is ConeClassLikeType -> mapToCanonicalString(session)
is ConeTypeVariableType, is ConeFlexibleType, is ConeCapturedType, is ConeTypeVariableType, is ConeFlexibleType, is ConeCapturedType,
is ConeDefinitelyNotNullType, is ConeIntersectionType, is ConeStubType -> is ConeDefinitelyNotNullType, is ConeIntersectionType, is ConeStubType, is ConeIntegerLiteralType ->
error("Unexpected type: $this [${this::class}]") error("Unexpected type: $this [${this::class}]")
is ConeLookupTagBasedType -> lookupTag.name.asString() is ConeLookupTagBasedType -> lookupTag.name.asString()
} }
@@ -222,7 +222,7 @@ private fun ConeKotlinType.mapToCanonicalString(session: FirSession): String {
return when (this) { return when (this) {
is ConeClassLikeType -> mapToCanonicalString(session) is ConeClassLikeType -> mapToCanonicalString(session)
is ConeTypeVariableType, is ConeFlexibleType, is ConeCapturedType, is ConeTypeVariableType, is ConeFlexibleType, is ConeCapturedType,
is ConeDefinitelyNotNullType, is ConeIntersectionType, is ConeStubType -> is ConeDefinitelyNotNullType, is ConeIntersectionType, is ConeStubType, is ConeIntegerLiteralType ->
error("Unexpected type: $this [${this::class}]") error("Unexpected type: $this [${this::class}]")
is ConeLookupTagBasedType -> lookupTag.name.asString() is ConeLookupTagBasedType -> lookupTag.name.asString()
} }
@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.fir.expressions.FirConstKind
import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.structure.impl.JavaElementImpl import org.jetbrains.kotlin.load.java.structure.impl.JavaElementImpl
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -275,7 +275,7 @@ private fun JavaAnnotationArgument.toFirExpression(
} }
// TODO: use kind here // TODO: use kind here
private fun <T> List<T>.createArrayOfCall(session: FirSession, @Suppress("UNUSED_PARAMETER") kind: IrConstKind<T>): FirArrayOfCall { private fun <T> List<T>.createArrayOfCall(session: FirSession, @Suppress("UNUSED_PARAMETER") kind: FirConstKind<T>): FirArrayOfCall {
return FirArrayOfCallImpl(null).apply { return FirArrayOfCallImpl(null).apply {
for (element in this@createArrayOfCall) { for (element in this@createArrayOfCall) {
arguments += element.createConstant(session) arguments += element.createConstant(session)
@@ -285,24 +285,24 @@ private fun <T> List<T>.createArrayOfCall(session: FirSession, @Suppress("UNUSED
internal fun Any?.createConstant(session: FirSession): FirExpression { internal fun Any?.createConstant(session: FirSession): FirExpression {
return when (this) { return when (this) {
is Byte -> FirConstExpressionImpl(null, IrConstKind.Byte, this) is Byte -> FirConstExpressionImpl(null, FirConstKind.Byte, this)
is Short -> FirConstExpressionImpl(null, IrConstKind.Short, this) is Short -> FirConstExpressionImpl(null, FirConstKind.Short, this)
is Int -> FirConstExpressionImpl(null, IrConstKind.Int, this) is Int -> FirConstExpressionImpl(null, FirConstKind.Int, this)
is Long -> FirConstExpressionImpl(null, IrConstKind.Long, this) is Long -> FirConstExpressionImpl(null, FirConstKind.Long, this)
is Char -> FirConstExpressionImpl(null, IrConstKind.Char, this) is Char -> FirConstExpressionImpl(null, FirConstKind.Char, this)
is Float -> FirConstExpressionImpl(null, IrConstKind.Float, this) is Float -> FirConstExpressionImpl(null, FirConstKind.Float, this)
is Double -> FirConstExpressionImpl(null, IrConstKind.Double, this) is Double -> FirConstExpressionImpl(null, FirConstKind.Double, this)
is Boolean -> FirConstExpressionImpl(null, IrConstKind.Boolean, this) is Boolean -> FirConstExpressionImpl(null, FirConstKind.Boolean, this)
is String -> FirConstExpressionImpl(null, IrConstKind.String, this) is String -> FirConstExpressionImpl(null, FirConstKind.String, this)
is ByteArray -> toList().createArrayOfCall(session, IrConstKind.Byte) is ByteArray -> toList().createArrayOfCall(session, FirConstKind.Byte)
is ShortArray -> toList().createArrayOfCall(session, IrConstKind.Short) is ShortArray -> toList().createArrayOfCall(session, FirConstKind.Short)
is IntArray -> toList().createArrayOfCall(session, IrConstKind.Int) is IntArray -> toList().createArrayOfCall(session, FirConstKind.Int)
is LongArray -> toList().createArrayOfCall(session, IrConstKind.Long) is LongArray -> toList().createArrayOfCall(session, FirConstKind.Long)
is CharArray -> toList().createArrayOfCall(session, IrConstKind.Char) is CharArray -> toList().createArrayOfCall(session, FirConstKind.Char)
is FloatArray -> toList().createArrayOfCall(session, IrConstKind.Float) is FloatArray -> toList().createArrayOfCall(session, FirConstKind.Float)
is DoubleArray -> toList().createArrayOfCall(session, IrConstKind.Double) is DoubleArray -> toList().createArrayOfCall(session, FirConstKind.Double)
is BooleanArray -> toList().createArrayOfCall(session, IrConstKind.Boolean) is BooleanArray -> toList().createArrayOfCall(session, FirConstKind.Boolean)
null -> FirConstExpressionImpl(null, IrConstKind.Null, null) null -> FirConstExpressionImpl(null, FirConstKind.Null, null)
else -> FirErrorExpressionImpl(null, FirSimpleDiagnostic("Unknown value in JavaLiteralAnnotationArgument: $this", DiagnosticKind.Java)) else -> FirErrorExpressionImpl(null, FirSimpleDiagnostic("Unknown value in JavaLiteralAnnotationArgument: $this", DiagnosticKind.Java))
} }
@@ -111,4 +111,8 @@ class FirJavaField(
get() = null get() = null
override var containerSource: DeserializedContainerSource? = null override var containerSource: DeserializedContainerSource? = null
override fun <D> transformInitializer(transformer: FirTransformer<D>, data: D): FirField {
return this
}
} }
@@ -10,10 +10,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.classId
import org.jetbrains.kotlin.fir.expressions.impl.FirConstExpressionImpl import org.jetbrains.kotlin.fir.expressions.impl.FirConstExpressionImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
@@ -35,7 +32,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_NULL_FQ_NAME import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_NULL_FQ_NAME
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_VALUE_FQ_NAME import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_VALUE_FQ_NAME
import org.jetbrains.kotlin.load.java.descriptors.AnnotationDefaultValue import org.jetbrains.kotlin.load.java.descriptors.AnnotationDefaultValue
@@ -391,15 +387,15 @@ internal fun ConeKotlinType.lexicalCastFrom(session: FirSession, value: String):
val (number, radix) = extractRadix(value) val (number, radix) = extractRadix(value)
return when (classId.relativeClassName.asString()) { return when (classId.relativeClassName.asString()) {
"Boolean" -> FirConstExpressionImpl(null, IrConstKind.Boolean, value.toBoolean()) "Boolean" -> FirConstExpressionImpl(null, FirConstKind.Boolean, value.toBoolean())
"Char" -> FirConstExpressionImpl(null, IrConstKind.Char, value.singleOrNull() ?: return null) "Char" -> FirConstExpressionImpl(null, FirConstKind.Char, value.singleOrNull() ?: return null)
"Byte" -> FirConstExpressionImpl(null, IrConstKind.Byte, number.toByteOrNull(radix) ?: return null) "Byte" -> FirConstExpressionImpl(null, FirConstKind.Byte, number.toByteOrNull(radix) ?: return null)
"Short" -> FirConstExpressionImpl(null, IrConstKind.Short, number.toShortOrNull(radix) ?: return null) "Short" -> FirConstExpressionImpl(null, FirConstKind.Short, number.toShortOrNull(radix) ?: return null)
"Int" -> FirConstExpressionImpl(null, IrConstKind.Int, number.toIntOrNull(radix) ?: return null) "Int" -> FirConstExpressionImpl(null, FirConstKind.Int, number.toIntOrNull(radix) ?: return null)
"Long" -> FirConstExpressionImpl(null, IrConstKind.Long, number.toLongOrNull(radix) ?: return null) "Long" -> FirConstExpressionImpl(null, FirConstKind.Long, number.toLongOrNull(radix) ?: return null)
"Float" -> FirConstExpressionImpl(null, IrConstKind.Float, value.toFloatOrNull() ?: return null) "Float" -> FirConstExpressionImpl(null, FirConstKind.Float, value.toFloatOrNull() ?: return null)
"Double" -> FirConstExpressionImpl(null, IrConstKind.Double, value.toDoubleOrNull() ?: return null) "Double" -> FirConstExpressionImpl(null, FirConstKind.Double, value.toDoubleOrNull() ?: return null)
"String" -> FirConstExpressionImpl(null, IrConstKind.String, value) "String" -> FirConstExpressionImpl(null, FirConstKind.String, value)
else -> null else -> null
} }
} }
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.* import org.jetbrains.kotlin.fir.declarations.impl.*
import org.jetbrains.kotlin.fir.expressions.FirConstKind
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirConstExpressionImpl import org.jetbrains.kotlin.fir.expressions.impl.FirConstExpressionImpl
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
@@ -24,7 +25,6 @@ import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.load.java.AnnotationTypeQualifierResolver import org.jetbrains.kotlin.load.java.AnnotationTypeQualifierResolver
import org.jetbrains.kotlin.load.java.descriptors.NullDefaultValue import org.jetbrains.kotlin.load.java.descriptors.NullDefaultValue
import org.jetbrains.kotlin.load.java.descriptors.StringDefaultValue import org.jetbrains.kotlin.load.java.descriptors.StringDefaultValue
@@ -276,7 +276,7 @@ class JavaClassEnhancementScope(
).enhance(session, jsr305State, predefinedEnhancementInfo?.parametersInfo?.getOrNull(index)) ).enhance(session, jsr305State, predefinedEnhancementInfo?.parametersInfo?.getOrNull(index))
val firResolvedTypeRef = signatureParts.type val firResolvedTypeRef = signatureParts.type
val defaultValueExpression = when (val defaultValue = ownerParameter.getDefaultValueFromAnnotation()) { val defaultValueExpression = when (val defaultValue = ownerParameter.getDefaultValueFromAnnotation()) {
NullDefaultValue -> FirConstExpressionImpl(null, IrConstKind.Null, null) NullDefaultValue -> FirConstExpressionImpl(null, FirConstKind.Null, null)
is StringDefaultValue -> firResolvedTypeRef.type.lexicalCastFrom(session, defaultValue.value) is StringDefaultValue -> firResolvedTypeRef.type.lexicalCastFrom(session, defaultValue.value)
null -> null null -> null
} }
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.lexer.KtTokens.CLOSING_QUOTE import org.jetbrains.kotlin.lexer.KtTokens.CLOSING_QUOTE
import org.jetbrains.kotlin.lexer.KtTokens.OPEN_QUOTE import org.jetbrains.kotlin.lexer.KtTokens.OPEN_QUOTE
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -224,40 +223,50 @@ abstract class BaseFirBuilder<T>(val session: FirSession, val context: Context =
else -> null else -> null
} }
return when (type) { return when (type) {
INTEGER_CONSTANT -> INTEGER_CONSTANT -> {
if (convertedText is Long && val kind = when {
(hasLongSuffix(text) || hasUnsignedLongSuffix(text) || hasUnsignedSuffix(text) || convertedText !is Long -> return FirErrorExpressionImpl(
convertedText > Int.MAX_VALUE || convertedText < Int.MIN_VALUE) expression.getSourceOrNull(),
) { FirSimpleDiagnostic(
FirConstExpressionImpl( "Incorrect constant expression: $text",
expression.getSourceOrNull(), IrConstKind.Long, convertedText, FirSimpleDiagnostic("Incorrect long: $text", DiagnosticKind.Syntax) DiagnosticKind.IllegalConstExpression
)
) )
} else if (convertedText is Number) {
// TODO: support byte / short hasLongSuffix(text) || hasUnsignedSuffix(text) || hasUnsignedLongSuffix(text) -> {
FirConstExpressionImpl( FirConstKind.Long
expression.getSourceOrNull(), IrConstKind.Int, convertedText.toInt(), FirSimpleDiagnostic("Incorrect int: $text", DiagnosticKind.Syntax) }
)
} else { else -> {
FirErrorExpressionImpl(expression.getSourceOrNull(), FirSimpleDiagnostic("Incorrect constant expression: $text", DiagnosticKind.IllegalConstExpression)) FirConstKind.IntegerLiteral
}
} }
FirConstExpressionImpl(
expression.getSourceOrNull(),
kind,
convertedText,
FirSimpleDiagnostic("Incorrect integer literal: $text", DiagnosticKind.Syntax)
)
}
FLOAT_CONSTANT -> FLOAT_CONSTANT ->
if (convertedText is Float) { if (convertedText is Float) {
FirConstExpressionImpl( FirConstExpressionImpl(
expression.getSourceOrNull(), IrConstKind.Float, convertedText, FirSimpleDiagnostic("Incorrect float: $text", DiagnosticKind.Syntax) expression.getSourceOrNull(), FirConstKind.Float, convertedText, FirSimpleDiagnostic("Incorrect float: $text", DiagnosticKind.Syntax)
) )
} else { } else {
FirConstExpressionImpl( FirConstExpressionImpl(
expression.getSourceOrNull(), IrConstKind.Double, convertedText as Double, FirSimpleDiagnostic("Incorrect double: $text", DiagnosticKind.Syntax) expression.getSourceOrNull(), FirConstKind.Double, convertedText as Double, FirSimpleDiagnostic("Incorrect double: $text", DiagnosticKind.Syntax)
) )
} }
CHARACTER_CONSTANT -> CHARACTER_CONSTANT ->
FirConstExpressionImpl( FirConstExpressionImpl(
expression.getSourceOrNull(), IrConstKind.Char, text.parseCharacter(), FirSimpleDiagnostic("Incorrect character: $text", DiagnosticKind.Syntax) expression.getSourceOrNull(), FirConstKind.Char, text.parseCharacter(), FirSimpleDiagnostic("Incorrect character: $text", DiagnosticKind.Syntax)
) )
BOOLEAN_CONSTANT -> BOOLEAN_CONSTANT ->
FirConstExpressionImpl(expression.getSourceOrNull(), IrConstKind.Boolean, convertedText as Boolean) FirConstExpressionImpl(expression.getSourceOrNull(), FirConstKind.Boolean, convertedText as Boolean)
NULL -> NULL ->
FirConstExpressionImpl(expression.getSourceOrNull(), IrConstKind.Null, null) FirConstExpressionImpl(expression.getSourceOrNull(), FirConstKind.Null, null)
else -> else ->
throw AssertionError("Unknown literal type: $type, $text") throw AssertionError("Unknown literal type: $type, $text")
} }
@@ -277,11 +286,11 @@ abstract class BaseFirBuilder<T>(val session: FirSession, val context: Context =
OPEN_QUOTE, CLOSING_QUOTE -> continue@L OPEN_QUOTE, CLOSING_QUOTE -> continue@L
LITERAL_STRING_TEMPLATE_ENTRY -> { LITERAL_STRING_TEMPLATE_ENTRY -> {
sb.append(entry.asText) sb.append(entry.asText)
FirConstExpressionImpl(entry.getSourceOrNull(), IrConstKind.String, entry.asText) FirConstExpressionImpl(entry.getSourceOrNull(), FirConstKind.String, entry.asText)
} }
ESCAPE_STRING_TEMPLATE_ENTRY -> { ESCAPE_STRING_TEMPLATE_ENTRY -> {
sb.append(entry.unescapedValue) sb.append(entry.unescapedValue)
FirConstExpressionImpl(entry.getSourceOrNull(), IrConstKind.String, entry.unescapedValue) FirConstExpressionImpl(entry.getSourceOrNull(), FirConstKind.String, entry.unescapedValue)
} }
SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> { SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> {
hasExpressions = true hasExpressions = true
@@ -313,7 +322,7 @@ abstract class BaseFirBuilder<T>(val session: FirSession, val context: Context =
} }
} }
} }
return if (hasExpressions) result!! else FirConstExpressionImpl(base?.toFirSourceElement(), IrConstKind.String, sb.toString()) return if (hasExpressions) result!! else FirConstExpressionImpl(base?.toFirSourceElement(), FirConstKind.String, sb.toString())
} }
/** /**
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.fir.types.ConeStarProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitKPropertyTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitKPropertyTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -149,7 +148,7 @@ fun FirExpression.generateNotNullOrOther(
baseSource, baseSource,
FirOperatorCallImpl(baseSource, FirOperation.EQ).apply { FirOperatorCallImpl(baseSource, FirOperation.EQ).apply {
arguments += subjectExpression arguments += subjectExpression
arguments += FirConstExpressionImpl(baseSource, IrConstKind.Null, null) arguments += FirConstExpressionImpl(baseSource, FirConstKind.Null, null)
}, },
FirSingleExpressionBlock(other) FirSingleExpressionBlock(other)
) )
@@ -326,7 +325,7 @@ fun FirModifiableVariable<*>.generateAccessorsByDelegate(session: FirSession, me
if (member) FirQualifiedAccessExpressionImpl(null).apply { if (member) FirQualifiedAccessExpressionImpl(null).apply {
calleeReference = FirExplicitThisReference(null, null) calleeReference = FirExplicitThisReference(null, null)
} }
else FirConstExpressionImpl(null, IrConstKind.Null, null) else FirConstExpressionImpl(null, FirConstKind.Null, null)
fun propertyRef() = FirCallableReferenceAccessImpl(null).apply { fun propertyRef() = FirCallableReferenceAccessImpl(null).apply {
calleeReference = FirResolvedNamedReferenceImpl(null, variable.name, variable.symbol) calleeReference = FirResolvedNamedReferenceImpl(null, variable.name, variable.symbol)
@@ -17,5 +17,5 @@ FILE: expectActual.kt
public? final? actual fun foo(): <implicit> { public? final? actual fun foo(): <implicit> {
^foo String(Hello) ^foo String(Hello)
} }
public? final? actual val x: <implicit> = Int(42) public? final? actual val x: <implicit> = IntegerLiteral(42)
public? get(): <implicit> public? get(): <implicit>
@@ -11,7 +11,7 @@ FILE: simpleClass.kt
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
private final? val baz: <implicit> = Int(42) private final? val baz: <implicit> = IntegerLiteral(42)
private get(): <implicit> private get(): <implicit>
public? open? override fun foo(x: Int, y: String): String { public? open? override fun foo(x: Int, y: String): String {
@@ -19,7 +19,7 @@ FILE: typeParameters.kt
} }
public? open? override fun get(index: Int): Int { public? open? override fun get(index: Int): Int {
^get Int(42) ^get IntegerLiteral(42)
} }
public? open? override fun concat(other: List<Int>): List<Int> { public? open? override fun concat(other: List<Int>): List<Int> {
@@ -7,18 +7,18 @@ FILE: annotated.kt
} }
public? final? fun foo(arg: Int): Int { public? final? fun foo(arg: Int): Int {
when () { when () {
==(@Ann() arg#, Int(0)) -> { ==(@Ann() arg#, IntegerLiteral(0)) -> {
@Ann() ^foo Int(1) @Ann() ^foo IntegerLiteral(1)
} }
} }
@Ann() when () { @Ann() when () {
==(arg#, Int(1)) -> { ==(arg#, IntegerLiteral(1)) -> {
^foo @Ann() Int(1) ^foo @Ann() IntegerLiteral(1)
} }
} }
^foo Int(42) ^foo IntegerLiteral(42)
} }
public? final? data class Two : R|kotlin/Any| { public? final? data class Two : R|kotlin/Any| {
public? constructor(x: Int, y: Int): R|Two| { public? constructor(x: Int, y: Int): R|Two| {
@@ -1,8 +1,8 @@
FILE: arrayAccess.kt FILE: arrayAccess.kt
public? final? val p: <implicit> = Int(0) public? final? val p: <implicit> = IntegerLiteral(0)
public? get(): <implicit> public? get(): <implicit>
public? final? fun foo(): <implicit> { public? final? fun foo(): <implicit> {
^foo Int(1) ^foo IntegerLiteral(1)
} }
public? final? class Wrapper : R|kotlin/Any| { public? final? class Wrapper : R|kotlin/Any| {
public? constructor(v: IntArray): R|Wrapper| { public? constructor(v: IntArray): R|Wrapper| {
@@ -14,5 +14,5 @@ FILE: arrayAccess.kt
} }
public? final? fun test(a: IntArray, w: Wrapper): <implicit> { public? final? fun test(a: IntArray, w: Wrapper): <implicit> {
^test a#.get#(Int(0)).plus#(a#.get#(p#)).plus#(a#.get#(foo#())).plus#(w#.v#.get#(Int(0))) ^test a#.get#(IntegerLiteral(0)).plus#(a#.get#(p#)).plus#(a#.get#(foo#())).plus#(w#.v#.get#(IntegerLiteral(0)))
} }
@@ -1,11 +1,11 @@
FILE: arrayAssignment.kt FILE: arrayAssignment.kt
public? final? fun test(): R|kotlin/Unit| { public? final? fun test(): R|kotlin/Unit| {
lval x: <implicit> = intArrayOf#(Int(1), Int(2), Int(3)) lval x: <implicit> = intArrayOf#(IntegerLiteral(1), IntegerLiteral(2), IntegerLiteral(3))
x#.set#(Int(1), Int(0)) x#.set#(IntegerLiteral(1), IntegerLiteral(0))
} }
public? final? fun foo(): <implicit> { public? final? fun foo(): <implicit> {
^foo Int(1) ^foo IntegerLiteral(1)
} }
public? final? fun test2(): R|kotlin/Unit| { public? final? fun test2(): R|kotlin/Unit| {
intArrayOf#(Int(1), Int(2), Int(3)).set#(foo#(), Int(1)) intArrayOf#(IntegerLiteral(1), IntegerLiteral(2), IntegerLiteral(3)).set#(foo#(), IntegerLiteral(1))
} }
@@ -37,19 +37,19 @@ FILE: branches.kt
} }
public? final? fun grade(g: Int): String { public? final? fun grade(g: Int): String {
^grade when (g#) { ^grade when (g#) {
==($subj$, Int(6)) || ==($subj$, Int(7)) -> { ==($subj$, IntegerLiteral(6)) || ==($subj$, IntegerLiteral(7)) -> {
String(Outstanding) String(Outstanding)
} }
==($subj$, Int(5)) -> { ==($subj$, IntegerLiteral(5)) -> {
String(Excellent) String(Excellent)
} }
==($subj$, Int(4)) -> { ==($subj$, IntegerLiteral(4)) -> {
String(Good) String(Good)
} }
==($subj$, Int(3)) -> { ==($subj$, IntegerLiteral(3)) -> {
String(Mediocre) String(Mediocre)
} }
Int(1).rangeTo#(Int(2)).contains#($subj$) -> { IntegerLiteral(1).rangeTo#(IntegerLiteral(2)).contains#($subj$) -> {
String(Fail) String(Fail)
} }
($subj$ is Number) -> { ($subj$ is Number) -> {
@@ -7,7 +7,7 @@ FILE: callableReferences.kt
public? final? fun foo(): R|kotlin/Unit| { public? final? fun foo(): R|kotlin/Unit| {
} }
public? final? val bar: <implicit> = Int(0) public? final? val bar: <implicit> = IntegerLiteral(0)
public? get(): <implicit> public? get(): <implicit>
} }
@@ -3,10 +3,10 @@ FILE: calls.kt
^distance x#.plus#(y#) ^distance x#.plus#(y#)
} }
public? final? fun test(): Int { public? final? fun test(): Int {
^test Int(3).distance#(Int(4)) ^test IntegerLiteral(3).distance#(IntegerLiteral(4))
} }
public? final? fun testRegular(): Int { public? final? fun testRegular(): Int {
^testRegular distance#(Int(3), Int(4)) ^testRegular distance#(IntegerLiteral(3), IntegerLiteral(4))
} }
public? final? class My : R|kotlin/Any| { public? final? class My : R|kotlin/Any| {
public? constructor(x: Int): R|My| { public? constructor(x: Int): R|My| {
@@ -30,7 +30,7 @@ FILE: calls.kt
} }
public? final? fun testInvoke(): Int { public? final? fun testInvoke(): Int {
^testInvoke My#(Int(13)).invoke#() ^testInvoke My#(IntegerLiteral(13)).invoke#()
} }
public? final? fun testQualified(first: My, second: My?): R|kotlin/Unit| { public? final? fun testQualified(first: My, second: My?): R|kotlin/Unit| {
println#(first#.x#) println#(first#.x#)
@@ -38,5 +38,5 @@ FILE: calls.kt
first#.foo#() first#.foo#()
second#?.foo#() second#?.foo#()
first#.copy#().foo#() first#.copy#().foo#()
first#.x# = Int(42) first#.x# = IntegerLiteral(42)
} }
@@ -32,7 +32,7 @@ FILE: collectionLiterals.kt
} }
} }
@Ann1(<implicitArrayOf>(Int(1), Int(2))) public? final? class First : R|kotlin/Any| { @Ann1(<implicitArrayOf>(IntegerLiteral(1), IntegerLiteral(2))) public? final? class First : R|kotlin/Any| {
public? constructor(): R|First| { public? constructor(): R|First| {
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
@@ -1,6 +1,6 @@
FILE: for.kt FILE: for.kt
public? final? fun foo(): R|kotlin/Unit| { public? final? fun foo(): R|kotlin/Unit| {
lval <range>: <implicit> = Int(1).rangeTo#(Int(10)) lval <range>: <implicit> = IntegerLiteral(1).rangeTo#(IntegerLiteral(10))
lval <iterator>: <implicit> = R|<local>/<range>|.iterator#() lval <iterator>: <implicit> = R|<local>/<range>|.iterator#()
while(R|<local>/<iterator>|.hasNext#()) { while(R|<local>/<iterator>|.hasNext#()) {
lval i: <implicit> = R|<local>/<iterator>|.next#() lval i: <implicit> = R|<local>/<iterator>|.next#()
@@ -9,14 +9,14 @@ FILE: for.kt
} }
public? final? fun bar(list: List<String>): R|kotlin/Unit| { public? final? fun bar(list: List<String>): R|kotlin/Unit| {
lval <range>: <implicit> = list#.subList#(Int(0), Int(10)) lval <range>: <implicit> = list#.subList#(IntegerLiteral(0), IntegerLiteral(10))
lval <iterator>: <implicit> = R|<local>/<range>|.iterator#() lval <iterator>: <implicit> = R|<local>/<range>|.iterator#()
while(R|<local>/<iterator>|.hasNext#()) { while(R|<local>/<iterator>|.hasNext#()) {
lval element: <implicit> = R|<local>/<iterator>|.next#() lval element: <implicit> = R|<local>/<iterator>|.next#()
println#(element#) println#(element#)
} }
lval <range>: <implicit> = list#.subList#(Int(10), Int(20)) lval <range>: <implicit> = list#.subList#(IntegerLiteral(10), IntegerLiteral(20))
lval <iterator>: <implicit> = R|<local>/<range>|.iterator#() lval <iterator>: <implicit> = R|<local>/<range>|.iterator#()
while(R|<local>/<iterator>|.hasNext#()) { while(R|<local>/<iterator>|.hasNext#()) {
lval element: <implicit> = R|<local>/<iterator>|.next#() lval element: <implicit> = R|<local>/<iterator>|.next#()
@@ -23,7 +23,7 @@ FILE: lambda.kt
} }
public? final? inline fun use(f: ( (Tuple) -> Int )): <implicit> { public? final? inline fun use(f: ( (Tuple) -> Int )): <implicit> {
^use f#(Tuple#(Int(1), Int(2))) ^use f#(Tuple#(IntegerLiteral(1), IntegerLiteral(2)))
} }
public? final? fun foo(): Int { public? final? fun foo(): Int {
lval l1: <implicit> = fun <implicit>.<anonymous>(t: Tuple): <implicit> { lval l1: <implicit> = fun <implicit>.<anonymous>(t: Tuple): <implicit> {
@@ -40,8 +40,8 @@ FILE: lambda.kt
) )
^foo use#(<L> = use@fun <implicit>.<anonymous>(): <implicit> { ^foo use#(<L> = use@fun <implicit>.<anonymous>(): <implicit> {
when () { when () {
==(it#.x#, Int(0)) -> { ==(it#.x#, IntegerLiteral(0)) -> {
^foo Int(0) ^foo IntegerLiteral(0)
} }
} }
@@ -52,8 +52,8 @@ FILE: lambda.kt
public? final? fun bar(): Int { public? final? fun bar(): Int {
^bar use#(<L> = lambda@fun <implicit>.<anonymous>(): <implicit> { ^bar use#(<L> = lambda@fun <implicit>.<anonymous>(): <implicit> {
when () { when () {
==(it#.x#, Int(0)) -> { ==(it#.x#, IntegerLiteral(0)) -> {
^bar Int(0) ^bar IntegerLiteral(0)
} }
} }
@@ -77,7 +77,7 @@ FILE: lambda.kt
public? get(): <implicit> public? get(): <implicit>
public? final? val another: <implicit> = fun <implicit>.<anonymous>(): <implicit> { public? final? val another: <implicit> = fun <implicit>.<anonymous>(): <implicit> {
Int(42) IntegerLiteral(42)
} }
public? get(): <implicit> public? get(): <implicit>
@@ -14,7 +14,7 @@ FILE: lambdaAndAnonymousFunction.kt
} }
public? final? fun test_2(): R|kotlin/Unit| { public? final? fun test_2(): R|kotlin/Unit| {
run#(fun <anonymous>(): Int { run#(fun <anonymous>(): Int {
^ Int(1) ^ IntegerLiteral(1)
} }
) )
} }
@@ -14,7 +14,7 @@ FILE: locals.kt
} }
lval x: <implicit> = Local#(Int(42)).diff#() lval x: <implicit> = Local#(IntegerLiteral(42)).diff#()
local final? fun sum(y: Int, z: Int, f: ( (Int, Int) -> Int )): Int { local final? fun sum(y: Int, z: Int, f: ( (Int, Int) -> Int )): Int {
^sum x#.plus#(f#(y#.plus#(z#))) ^sum x#.plus#(f#(y#.plus#(z#)))
} }
@@ -30,7 +30,7 @@ FILE: locals.kt
} }
.foo#() .foo#()
^withLocals sum#(code#, Local#(Int(1)).diff#(), fun <anonymous>(x: Int, y: Int): <implicit> { ^withLocals sum#(code#, Local#(IntegerLiteral(1)).diff#(), fun <anonymous>(x: Int, y: Int): <implicit> {
^ x#.plus#(y#) ^ x#.plus#(y#)
} }
) )
@@ -1,15 +1,15 @@
FILE: modifications.kt FILE: modifications.kt
public? final? fun simple(): R|kotlin/Unit| { public? final? fun simple(): R|kotlin/Unit| {
lvar x: <implicit> = Int(10) lvar x: <implicit> = IntegerLiteral(10)
+=(x#, Int(20)) +=(x#, IntegerLiteral(20))
-=(x#, Int(5)) -=(x#, IntegerLiteral(5))
/=(x#, Int(5)) /=(x#, IntegerLiteral(5))
*=(x#, Int(10)) *=(x#, IntegerLiteral(10))
} }
public? final? fun List<String>.modify(): R|kotlin/Unit| { public? final? fun List<String>.modify(): R|kotlin/Unit| {
+=(this#, String(Alpha)) +=(this#, String(Alpha))
+=(this#, String(Omega)) +=(this#, String(Omega))
} }
public? final? fun Any.modify(): R|kotlin/Unit| { public? final? fun Any.modify(): R|kotlin/Unit| {
+=((this# as List<Int>), Int(42)) +=((this# as List<Int>), IntegerLiteral(42))
} }
@@ -2,7 +2,7 @@ FILE: nullability.kt
public? final? fun orFourtyTwo(arg: Int?): <implicit> { public? final? fun orFourtyTwo(arg: Int?): <implicit> {
^orFourtyTwo when (lval <elvis>: <implicit> = arg#) { ^orFourtyTwo when (lval <elvis>: <implicit> = arg#) {
==($subj$, Null(null)) -> { ==($subj$, Null(null)) -> {
Int(42) IntegerLiteral(42)
} }
else -> { else -> {
R|<local>/<elvis>| R|<local>/<elvis>|
@@ -5,7 +5,7 @@ FILE: these.kt
} }
public? final? fun foo(): Int { public? final? fun foo(): Int {
^foo Int(1) ^foo IntegerLiteral(1)
} }
public? final? fun bar(): Int { public? final? fun bar(): Int {
@@ -1,6 +1,6 @@
FILE: unary.kt FILE: unary.kt
public? final? fun test(): R|kotlin/Unit| { public? final? fun test(): R|kotlin/Unit| {
lvar x: <implicit> = Int(0) lvar x: <implicit> = IntegerLiteral(0)
lval x1: <implicit> = { lval x1: <implicit> = {
lval <unary>: <implicit> = x# lval <unary>: <implicit> = x#
x# = R|<local>/<unary>|.inc#() x# = R|<local>/<unary>|.inc#()
@@ -26,7 +26,7 @@ FILE: unary.kt
} }
when () { when () {
==(x#, Int(0)).not#() -> { ==(x#, IntegerLiteral(0)).not#() -> {
println#(String(000)) println#(String(000))
} }
} }
@@ -58,15 +58,15 @@ FILE: unary.kt
} }
public? final? fun test3(arr: Array<Int>): R|kotlin/Unit| { public? final? fun test3(arr: Array<Int>): R|kotlin/Unit| {
lval x1: <implicit> = { lval x1: <implicit> = {
lval <unary>: <implicit> = arr#.get#(Int(0)) lval <unary>: <implicit> = arr#.get#(IntegerLiteral(0))
arr#.set#(Int(0), R|<local>/<unary>|.inc#()) arr#.set#(IntegerLiteral(0), R|<local>/<unary>|.inc#())
R|<local>/<unary>| R|<local>/<unary>|
} }
lval x2: <implicit> = { lval x2: <implicit> = {
lval <unary>: <implicit> = arr#.get#(Int(1)) lval <unary>: <implicit> = arr#.get#(IntegerLiteral(1))
lval <unary-result>: <implicit> = R|<local>/<unary>|.inc#() lval <unary-result>: <implicit> = R|<local>/<unary>|.inc#()
arr#.set#(Int(1), R|<local>/<unary-result>|) arr#.set#(IntegerLiteral(1), R|<local>/<unary-result>|)
R|<local>/<unary-result>| R|<local>/<unary-result>|
} }
@@ -82,15 +82,15 @@ FILE: unary.kt
} }
public? final? fun test4(y: Y): R|kotlin/Unit| { public? final? fun test4(y: Y): R|kotlin/Unit| {
lval x1: <implicit> = { lval x1: <implicit> = {
lval <unary>: <implicit> = y#.arr#.get#(Int(0)) lval <unary>: <implicit> = y#.arr#.get#(IntegerLiteral(0))
y#.arr#.set#(Int(0), R|<local>/<unary>|.inc#()) y#.arr#.set#(IntegerLiteral(0), R|<local>/<unary>|.inc#())
R|<local>/<unary>| R|<local>/<unary>|
} }
lval x2: <implicit> = { lval x2: <implicit> = {
lval <unary>: <implicit> = y#.arr#.get#(Int(1)) lval <unary>: <implicit> = y#.arr#.get#(IntegerLiteral(1))
lval <unary-result>: <implicit> = R|<local>/<unary>|.inc#() lval <unary-result>: <implicit> = R|<local>/<unary>|.inc#()
y#.arr#.set#(Int(1), R|<local>/<unary-result>|) y#.arr#.set#(IntegerLiteral(1), R|<local>/<unary-result>|)
R|<local>/<unary-result>| R|<local>/<unary-result>|
} }
@@ -1,8 +1,8 @@
FILE: variables.kt FILE: variables.kt
public? final? fun foo(): R|kotlin/Unit| { public? final? fun foo(): R|kotlin/Unit| {
lval x: <implicit> = Int(1) lval x: <implicit> = IntegerLiteral(1)
lvar y: <implicit> = x#.plus#(Int(1)) lvar y: <implicit> = x#.plus#(IntegerLiteral(1))
lval z: <implicit> = y#.times#(Int(2)) lval z: <implicit> = y#.times#(IntegerLiteral(2))
y# = y#.plus#(z#) y# = y#.plus#(z#)
lval w: <implicit> = y#.minus#(x#) lval w: <implicit> = y#.minus#(x#)
^foo w# ^foo w#
@@ -1,12 +1,12 @@
FILE: while.kt FILE: while.kt
public? final? fun foo(limit: Int): R|kotlin/Unit| { public? final? fun foo(limit: Int): R|kotlin/Unit| {
lvar k: <implicit> = Int(0) lvar k: <implicit> = IntegerLiteral(0)
some@while(<(k#, limit#)) { some@while(<(k#, limit#)) {
lval <unary>: <implicit> = k# lval <unary>: <implicit> = k#
k# = R|<local>/<unary>|.inc#() k# = R|<local>/<unary>|.inc#()
R|<local>/<unary>| R|<local>/<unary>|
println#(k#) println#(k#)
while(==(k#, Int(13))) { while(==(k#, IntegerLiteral(13))) {
lval <unary>: <implicit> = k# lval <unary>: <implicit> = k#
k# = R|<local>/<unary>|.inc#() k# = R|<local>/<unary>|.inc#()
R|<local>/<unary>| R|<local>/<unary>|
@@ -18,7 +18,7 @@ FILE: while.kt
when () { when () {
>(k#, limit#) -> { >(k#, limit#) -> {
continue@@@[==(k#, Int(13))] continue@@@[==(k#, IntegerLiteral(13))]
} }
} }
@@ -35,5 +35,5 @@ FILE: while.kt
R|<local>/<unary>| R|<local>/<unary>|
println#(k#) println#(k#)
} }
while(>=(k#, Int(0))) while(>=(k#, IntegerLiteral(0)))
} }
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirWhenExpressionImpl
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.FirTypeProjection
@@ -36,7 +37,11 @@ fun FirFunctionCall.copy(
typeArguments: List<FirTypeProjection> = this.typeArguments, typeArguments: List<FirTypeProjection> = this.typeArguments,
resultType: FirTypeRef = this.typeRef resultType: FirTypeRef = this.typeRef
): FirFunctionCall { ): FirFunctionCall {
return FirFunctionCallImpl(source).apply { return if (this is FirIntegerOperatorCall) {
FirIntegerOperatorCall(source)
} else {
FirFunctionCallImpl(source)
}.apply {
this.safe = safe this.safe = safe
this.annotations.addAll(annotations) this.annotations.addAll(annotations)
this.arguments.addAll(arguments) this.arguments.addAll(arguments)
@@ -35,9 +35,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.symbols.invoke import org.jetbrains.kotlin.fir.symbols.invoke
import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.fir.visitors.compose import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -74,15 +72,56 @@ class FirCallResolver(
fun resolveCallAndSelectCandidate(functionCall: FirFunctionCall, file: FirFile): FirFunctionCall { fun resolveCallAndSelectCandidate(functionCall: FirFunctionCall, file: FirFile): FirFunctionCall {
qualifiedResolver.reset() qualifiedResolver.reset()
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
val functionCall = functionCall.transformExplicitReceiver(transformer, ResolutionMode.ContextIndependent) var functionCall = functionCall.transformExplicitReceiver(transformer, ResolutionMode.ContextIndependent)
.also { dataFlowAnalyzer.enterQualifiedAccessExpression(functionCall) } .also { dataFlowAnalyzer.enterQualifiedAccessExpression(functionCall) }
.transformArguments(transformer, ResolutionMode.ContextDependent) .transformArguments(transformer, ResolutionMode.ContextDependent)
val name = functionCall.calleeReference.name var result = collectCandidates(functionCall)
if (
(result.candidates.isEmpty() || result.applicability < CandidateApplicability.SYNTHETIC_RESOLVED) &&
functionCall.explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null
) {
functionCall = functionCall.transformExplicitReceiver(integerLiteralTypeApproximator, null)
result = collectCandidates(functionCall)
}
val nameReference = createResolvedNamedReference(
functionCall.calleeReference,
functionCall.calleeReference.name,
result.candidates,
result.applicability
)
val resultExpression = functionCall.transformCalleeReference(StoreNameReference, nameReference)
val candidate = resultExpression.candidate()
// We need desugaring
val resultFunctionCall = if (candidate != null && candidate.callInfo != result.info) {
functionCall.copy(
explicitReceiver = candidate.callInfo.explicitReceiver,
dispatchReceiver = candidate.dispatchReceiverExpression(),
extensionReceiver = candidate.extensionReceiverExpression(),
arguments = candidate.callInfo.arguments,
safe = candidate.callInfo.isSafeCall
)
} else {
resultExpression
}
val typeRef = typeFromCallee(resultFunctionCall)
if (typeRef.type is ConeKotlinErrorType) {
resultFunctionCall.resultType = typeRef
}
return resultFunctionCall
}
private data class ResolutionResult(val info: CallInfo, val applicability: CandidateApplicability, val candidates: Collection<Candidate>)
private fun collectCandidates(functionCall: FirFunctionCall): ResolutionResult {
val explicitReceiver = functionCall.explicitReceiver val explicitReceiver = functionCall.explicitReceiver
val arguments = functionCall.arguments val arguments = functionCall.arguments
val typeArguments = functionCall.typeArguments val typeArguments = functionCall.typeArguments
val name = functionCall.calleeReference.name
val info = CallInfo( val info = CallInfo(
CallKind.Function, CallKind.Function,
@@ -108,34 +147,7 @@ class FirCallResolver(
} else { } else {
conflictResolver.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = true) conflictResolver.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = true)
} }
return ResolutionResult(info, result.currentApplicability, reducedCandidates)
val nameReference = createResolvedNamedReference(
functionCall.calleeReference,
name,
reducedCandidates,
result.currentApplicability
)
val resultExpression = functionCall.transformCalleeReference(StoreNameReference, nameReference)
val candidate = resultExpression.candidate()
// We need desugaring
val resultFunctionCall = if (candidate != null && candidate.callInfo != info) {
functionCall.copy(
explicitReceiver = candidate.callInfo.explicitReceiver,
dispatchReceiver = candidate.dispatchReceiverExpression(),
extensionReceiver = candidate.extensionReceiverExpression(),
arguments = candidate.callInfo.arguments,
safe = candidate.callInfo.isSafeCall
)
} else {
resultExpression
}
val typeRef = typeFromCallee(resultFunctionCall)
if (typeRef.type is ConeKotlinErrorType) {
resultFunctionCall.resultType = typeRef
}
return resultFunctionCall
} }
fun <T : FirQualifiedAccess> resolveVariableAccessAndSelectCandidate(qualifiedAccess: T, file: FirFile): FirStatement { fun <T : FirQualifiedAccess> resolveVariableAccessAndSelectCandidate(qualifiedAccess: T, file: FirFile): FirStatement {
@@ -5,11 +5,12 @@
package org.jetbrains.kotlin.fir package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.fir.resolve.calls.ConeInferenceContext
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
import org.jetbrains.kotlin.fir.types.ConeTypeContext import org.jetbrains.kotlin.fir.types.ConeTypeContext
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
private class SessionBasedTypeContext(override val session: FirSession) : ConeTypeContext { private class SessionBasedTypeContext(override val session: FirSession) : ConeInferenceContext {
override fun newBaseTypeCheckerContext( override fun newBaseTypeCheckerContext(
errorTypesEqualToAnything: Boolean, errorTypesEqualToAnything: Boolean,
stubTypesEqualToAnything: Boolean stubTypesEqualToAnything: Boolean
@@ -18,4 +19,4 @@ private class SessionBasedTypeContext(override val session: FirSession) : ConeTy
} }
} }
val FirSession.typeContext: ConeTypeContext get() = SessionBasedTypeContext(this) val FirSession.typeContext: ConeInferenceContext get() = SessionBasedTypeContext(this)
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.fir.expressions.FirConstKind
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation.Argument.Value.Type.* import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation.Argument.Value.Type.*
import org.jetbrains.kotlin.metadata.deserialization.Flags import org.jetbrains.kotlin.metadata.deserialization.Flags
@@ -111,15 +111,15 @@ abstract class AbstractAnnotationDeserializer(
// TODO: val isUnsigned = Flags.IS_UNSIGNED.get(value.flags) // TODO: val isUnsigned = Flags.IS_UNSIGNED.get(value.flags)
val result: FirExpression = when (value.type) { val result: FirExpression = when (value.type) {
BYTE -> const(IrConstKind.Byte, value.intValue.toByte()) BYTE -> const(FirConstKind.Byte, value.intValue.toByte())
CHAR -> const(IrConstKind.Char, value.intValue.toChar()) CHAR -> const(FirConstKind.Char, value.intValue.toChar())
SHORT -> const(IrConstKind.Short, value.intValue.toShort()) SHORT -> const(FirConstKind.Short, value.intValue.toShort())
INT -> const(IrConstKind.Int, value.intValue.toInt()) INT -> const(FirConstKind.Int, value.intValue.toInt())
LONG -> const(IrConstKind.Long, value.intValue) LONG -> const(FirConstKind.Long, value.intValue)
FLOAT -> const(IrConstKind.Float, value.floatValue) FLOAT -> const(FirConstKind.Float, value.floatValue)
DOUBLE -> const(IrConstKind.Double, value.doubleValue) DOUBLE -> const(FirConstKind.Double, value.doubleValue)
BOOLEAN -> const(IrConstKind.Boolean, (value.intValue != 0L)) BOOLEAN -> const(FirConstKind.Boolean, (value.intValue != 0L))
STRING -> const(IrConstKind.String, nameResolver.getString(value.stringValue)) STRING -> const(FirConstKind.String, nameResolver.getString(value.stringValue))
ANNOTATION -> deserializeAnnotation(value.annotation, nameResolver) ANNOTATION -> deserializeAnnotation(value.annotation, nameResolver)
CLASS -> FirGetClassCallImpl(null).apply { CLASS -> FirGetClassCallImpl(null).apply {
val classId = nameResolver.getClassId(value.classId) val classId = nameResolver.getClassId(value.classId)
@@ -152,5 +152,5 @@ abstract class AbstractAnnotationDeserializer(
return result return result
} }
private fun <T> const(kind: IrConstKind<T>, value: T) = FirConstExpressionImpl(null, kind, value) private fun <T> const(kind: FirConstKind<T>, value: T) = FirConstExpressionImpl(null, kind, value)
} }
@@ -224,6 +224,7 @@ fun <T : ConeKotlinType> T.withNullability(nullability: ConeNullability): T {
ConeNullability.NULLABLE -> original.withNullability(nullability) ConeNullability.NULLABLE -> original.withNullability(nullability)
ConeNullability.UNKNOWN -> original.withNullability(nullability) ConeNullability.UNKNOWN -> original.withNullability(nullability)
} as T } as T
is ConeIntegerLiteralType -> this
else -> error("sealed: ${this::class}") else -> error("sealed: ${this::class}")
} }
} }
@@ -57,7 +57,8 @@ class FirSamResolverImpl(
is ConeClassErrorType, is ConeStubType -> null is ConeClassErrorType, is ConeStubType -> null
// TODO: support those types as well // TODO: support those types as well
is ConeTypeParameterType, is ConeTypeVariableType, is ConeTypeParameterType, is ConeTypeVariableType,
is ConeCapturedType, is ConeDefinitelyNotNullType, is ConeIntersectionType -> null is ConeCapturedType, is ConeDefinitelyNotNullType, is ConeIntersectionType,
is ConeIntegerLiteralType -> null
// TODO: Thing of getting rid of this branch since ConeLookupTagBasedType should be a sealed class // TODO: Thing of getting rid of this branch since ConeLookupTagBasedType should be a sealed class
is ConeLookupTagBasedType -> null is ConeLookupTagBasedType -> null
} }
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
@@ -45,6 +45,14 @@ fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession)
} }
) )
is ConeDefinitelyNotNullType -> original.scope(useSiteSession, scopeSession) is ConeDefinitelyNotNullType -> original.scope(useSiteSession, scopeSession)
is ConeIntegerLiteralType -> {
scopeSession.getOrBuild(
FirIntegerLiteralTypeScope.ILT_SYMBOL,
FirIntegerLiteralTypeScope.SCOPE_SESSION_KEY
) {
FirIntegerLiteralTypeScope(useSiteSession)
}
}
else -> error("Failed type $this") else -> error("Failed type $this")
} }
} }
@@ -14,9 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.calls.InferenceComponents import org.jetbrains.kotlin.fir.resolve.calls.InferenceComponents
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionStageRunner import org.jetbrains.kotlin.fir.resolve.calls.ResolutionStageRunner
import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer
import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator import org.jetbrains.kotlin.fir.resolve.transformers.*
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.phasedFir
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -39,6 +37,8 @@ interface BodyResolveComponents : SessionHolder {
val doubleColonExpressionResolver: FirDoubleColonExpressionResolver val doubleColonExpressionResolver: FirDoubleColonExpressionResolver
val syntheticCallGenerator: FirSyntheticCallGenerator val syntheticCallGenerator: FirSyntheticCallGenerator
val dataFlowAnalyzer: FirDataFlowAnalyzer val dataFlowAnalyzer: FirDataFlowAnalyzer
val integerLiteralTypeApproximator: IntegerLiteralTypeApproximationTransformer
val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater
val <D> AbstractFirBasedSymbol<D>.phasedFir: D where D : FirDeclaration, D : FirSymbolOwner<D> val <D> AbstractFirBasedSymbol<D>.phasedFir: D where D : FirDeclaration, D : FirSymbolOwner<D>
get() = phasedFir(session, FirResolvePhase.DECLARATIONS) get() = phasedFir(session, FirResolvePhase.DECLARATIONS)
@@ -6,14 +6,13 @@
package org.jetbrains.kotlin.fir.resolve.calls package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralTypeImpl
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.arrayElementType import org.jetbrains.kotlin.fir.types.arrayElementType
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.resolve.OverloadabilitySpecificityCallbacks import org.jetbrains.kotlin.resolve.calls.results.*
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature import org.jetbrains.kotlin.types.checker.requireOrDescribe
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.resolve.calls.results.isSignatureNotLessSpecific
abstract class AbstractConeCallConflictResolver( abstract class AbstractConeCallConflictResolver(
private val specificityComparator: TypeSpecificityComparator, private val specificityComparator: TypeSpecificityComparator,
@@ -50,11 +49,39 @@ abstract class AbstractConeCallConflictResolver(
return createEmptyConstraintSystem().isSignatureNotLessSpecific( return createEmptyConstraintSystem().isSignatureNotLessSpecific(
call1, call1,
call2, call2,
OverloadabilitySpecificityCallbacks, SpecificityComparisonWithNumerics,
specificityComparator specificityComparator
) )
} }
private val SpecificityComparisonWithNumerics = object : SpecificityComparisonCallbacks {
override fun isNonSubtypeNotLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker): Boolean {
requireOrDescribe(specific is ConeKotlinType, specific)
requireOrDescribe(general is ConeKotlinType, general)
// TODO: support unsigned types
// see OverloadingConflictResolver.kt:294
val int = ConeIntegerLiteralTypeImpl.INT_TYPE
val long = ConeIntegerLiteralTypeImpl.LONG_TYPE
val byte = ConeIntegerLiteralTypeImpl.BYTE_TYPE
val short = ConeIntegerLiteralTypeImpl.SHORT_TYPE
when {
//TypeUtils.equalTypes(specific, _double) && TypeUtils.equalTypes(general, _float) -> return true
specific == int -> {
when {
general == long -> return true
general == byte -> return true
general == short -> return true
}
}
specific == short && general == byte -> return true
}
return false
}
}
protected fun createFlatSignature(call: Candidate): FlatSignature<Candidate> { protected fun createFlatSignature(call: Candidate): FlatSignature<Candidate> {
return when (val declaration = call.symbol.fir) { return when (val declaration = call.symbol.fir) {
is FirSimpleFunction -> createFlatSignature(call, declaration) is FirSimpleFunction -> createFlatSignature(call, declaration)
@@ -12,8 +12,12 @@ import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.withNullability import org.jetbrains.kotlin.fir.resolve.withNullability
import org.jetbrains.kotlin.fir.returnExpressions import org.jetbrains.kotlin.fir.returnExpressions
import org.jetbrains.kotlin.fir.scopes.impl.FirILTTypeRefPlaceHolder
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperator
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
@@ -165,7 +169,15 @@ fun Candidate.resolveSubCallArgument(
isSafeCall, isSafeCall,
typeProvider typeProvider
) )
val type = sink.components.returnTypeCalculator.tryCalculateReturnType(candidate.symbol.firUnsafe()).coneTypeUnsafe<ConeKotlinType>() /*
* It's important to extract type from argument neither from symbol, because of symbol contains
* placeholder type with value 0, but argument contains type with proper literal value
*/
val type: ConeKotlinType = if (candidate.symbol.fir is FirIntegerOperator) {
(argument as FirFunctionCall).resultType.coneTypeUnsafe()
} else {
sink.components.returnTypeCalculator.tryCalculateReturnType(candidate.symbol.firUnsafe()).coneTypeUnsafe()
}
val argumentType = candidate.substitutor.substituteOrSelf(type) val argumentType = candidate.substitutor.substituteOrSelf(type)
resolvePlainArgumentType(csBuilder, argumentType, expectedType, sink, isReceiver, isDispatch, isSafeCall) resolvePlainArgumentType(csBuilder, argumentType, expectedType, sink, isReceiver, isDispatch, isSafeCall)
} }
@@ -183,6 +195,14 @@ fun Candidate.resolvePlainExpressionArgument(
if (expectedType == null) return if (expectedType == null) return
val argumentType = typeProvider(argument)?.coneTypeSafe<ConeKotlinType>() ?: return val argumentType = typeProvider(argument)?.coneTypeSafe<ConeKotlinType>() ?: return
resolvePlainArgumentType(csBuilder, argumentType, expectedType, sink, isReceiver, isDispatch, isSafeCall) resolvePlainArgumentType(csBuilder, argumentType, expectedType, sink, isReceiver, isDispatch, isSafeCall)
checkApplicabilityForIntegerOperatorCall(sink, argument)
}
private fun Candidate.checkApplicabilityForIntegerOperatorCall(sink: CheckerSink, argument: FirExpression) {
if (symbol.fir !is FirIntegerOperator) return
if (argument !is FirConstExpression<*> && argument !is FirIntegerOperatorCall) {
sink.reportApplicability(CandidateApplicability.INAPPLICABLE)
}
} }
fun Candidate.resolvePlainArgumentType( fun Candidate.resolvePlainArgumentType(
@@ -273,6 +293,7 @@ internal fun Candidate.resolveArgument(
} }
private fun Candidate.prepareExpectedType(session: FirSession, argument: FirExpression, parameter: FirValueParameter): ConeKotlinType { private fun Candidate.prepareExpectedType(session: FirSession, argument: FirExpression, parameter: FirValueParameter): ConeKotlinType {
if (parameter.returnTypeRef is FirILTTypeRefPlaceHolder) return argument.resultType.coneTypeUnsafe()
val basicExpectedType = argument.getExpectedType(session, parameter/*, LanguageVersionSettings*/) val basicExpectedType = argument.getExpectedType(session, parameter/*, LanguageVersionSettings*/)
val expectedType = getExpectedTypeWithSAMConversion(session, argument, basicExpectedType) ?: basicExpectedType val expectedType = getExpectedTypeWithSAMConversion(session, argument, basicExpectedType) ?: basicExpectedType
return this.substitutor.substituteOrSelf(expectedType) return this.substitutor.substituteOrSelf(expectedType)
@@ -260,7 +260,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext,
TypeSubstitutorMarker { TypeSubstitutorMarker {
override fun substituteType(type: ConeKotlinType): ConeKotlinType? { override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
val new = map[type.typeConstructor()] ?: return null val new = map[type.typeConstructor()] ?: return null
return makeNullableIfNeed(type.isMarkedNullable, new as ConeKotlinType) return makeNullableIfNeed(type.isMarkedNullable, (new as ConeKotlinType).approximateIntegerLiteralType())
} }
} }
} }
@@ -299,10 +299,6 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext,
return this is ConeCapturedTypeConstructor return this is ConeCapturedTypeConstructor
} }
override fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker {
TODO()
}
override fun KotlinTypeMarker.removeExactAnnotation(): KotlinTypeMarker { override fun KotlinTypeMarker.removeExactAnnotation(): KotlinTypeMarker {
// TODO // TODO
return this return this
@@ -314,7 +310,11 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext,
} }
override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker? { override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker? {
// TODO: implement return ConeIntegerLiteralTypeImpl.findCommonSuperType(explicitSupertypes)
return null }
override fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker {
require(this is ConeIntegerLiteralType)
return this.getApproximatedType()
} }
} }
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.resolve.calls package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType
import org.jetbrains.kotlin.fir.returnExpressions import org.jetbrains.kotlin.fir.returnExpressions
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeVariable import org.jetbrains.kotlin.fir.types.ConeTypeVariable
@@ -33,7 +34,8 @@ fun Candidate.computeCompletionMode(
if (expectedType != null) return KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL if (expectedType != null) return KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL
// This is questionable as null return type can be only for error call // This is questionable as null return type can be only for error call
if (currentReturnType == null) return KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL if (currentReturnType == null || currentReturnType is ConeIntegerLiteralType)
return KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL
return when { return when {
// Consider call foo(bar(x)), if return type of bar is a proper one, then we can complete resolve for bar => full completion mode // Consider call foo(bar(x)), if return type of bar is a proper one, then we can complete resolve for bar => full completion mode
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
@@ -51,6 +50,8 @@ class FirDataFlowAnalyzer(private val components: FirAbstractBodyResolveTransfor
private val variablesForWhenConditions = mutableMapOf<WhenBranchConditionExitNode, DataFlowVariable>() private val variablesForWhenConditions = mutableMapOf<WhenBranchConditionExitNode, DataFlowVariable>()
private var contractDescriptionVisitingMode = false
/* /*
* If there is no types from smartcasts function returns null * If there is no types from smartcasts function returns null
* *
@@ -211,8 +212,8 @@ class FirDataFlowAnalyzer(private val components: FirAbstractBodyResolveTransfor
val rightConst = rightOperand as? FirConstExpression<*> val rightConst = rightOperand as? FirConstExpression<*>
when { when {
leftConst?.kind == IrConstKind.Null -> processEqNull(node, rightOperand, operation) leftConst?.kind == FirConstKind.Null -> processEqNull(node, rightOperand, operation)
rightConst?.kind == IrConstKind.Null -> processEqNull(node, leftOperand, operation) rightConst?.kind == FirConstKind.Null -> processEqNull(node, leftOperand, operation)
leftConst != null -> processEqWithConst(node, rightOperand, leftConst, operation) leftConst != null -> processEqWithConst(node, rightOperand, leftConst, operation)
rightConst != null -> processEqWithConst(node, leftOperand, rightConst, operation) rightConst != null -> processEqWithConst(node, leftOperand, rightConst, operation)
operation != FirOperation.EQ && operation != FirOperation.IDENTITY -> return operation != FirOperation.EQ && operation != FirOperation.IDENTITY -> return
@@ -248,7 +249,7 @@ class FirDataFlowAnalyzer(private val components: FirAbstractBodyResolveTransfor
// propagating facts for (... == true) and (... == false) // propagating facts for (... == true) and (... == false)
variableStorage[operand]?.let { operandVariable -> variableStorage[operand]?.let { operandVariable ->
if (const.kind != IrConstKind.Boolean) return@let if (const.kind != FirConstKind.Boolean) return@let
val constValue = (const.value as Boolean) val constValue = (const.value as Boolean)
val shouldInvert = isEq xor constValue val shouldInvert = isEq xor constValue
@@ -556,6 +557,7 @@ class FirDataFlowAnalyzer(private val components: FirAbstractBodyResolveTransfor
val conditionalEffects = contractDescription.effects.filterIsInstance<ConeConditionalEffectDeclaration>() val conditionalEffects = contractDescription.effects.filterIsInstance<ConeConditionalEffectDeclaration>()
if (conditionalEffects.isEmpty()) return if (conditionalEffects.isEmpty()) return
val argumentsMapping = createArgumentsMapping(functionCall) ?: return val argumentsMapping = createArgumentsMapping(functionCall) ?: return
contractDescriptionVisitingMode = true
graphBuilder.enterContract(functionCall).mergeIncomingFlow() graphBuilder.enterContract(functionCall).mergeIncomingFlow()
val functionCallVariable = getOrCreateVariable(functionCall) val functionCallVariable = getOrCreateVariable(functionCall)
for (conditionalEffect in conditionalEffects) { for (conditionalEffect in conditionalEffects) {
@@ -594,6 +596,7 @@ class FirDataFlowAnalyzer(private val components: FirAbstractBodyResolveTransfor
} }
} }
graphBuilder.exitContract(functionCall).mergeIncomingFlow() graphBuilder.exitContract(functionCall).mergeIncomingFlow()
contractDescriptionVisitingMode = true
} }
@@ -622,6 +625,7 @@ class FirDataFlowAnalyzer(private val components: FirAbstractBodyResolveTransfor
} }
fun exitConstExpresion(constExpression: FirConstExpression<*>) { fun exitConstExpresion(constExpression: FirConstExpression<*>) {
if (constExpression.resultType is FirResolvedTypeRef && !contractDescriptionVisitingMode) return
graphBuilder.exitConstExpresion(constExpression).mergeIncomingFlow() graphBuilder.exitConstExpresion(constExpression).mergeIncomingFlow()
} }
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.* import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.fir.expressions.FirConstKind
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
private object ConeConditionalEffectToFirVisitor : ConeContractDescriptionVisitor<FirExpression?, Map<Int, FirExpression>>() { private object ConeConditionalEffectToFirVisitor : ConeContractDescriptionVisitor<FirExpression?, Map<Int, FirExpression>>() {
@@ -21,8 +21,8 @@ private object ConeConditionalEffectToFirVisitor : ConeContractDescriptionVisito
override fun visitConstantDescriptor(constantReference: ConeConstantReference, data: Map<Int, FirExpression>): FirExpression? { override fun visitConstantDescriptor(constantReference: ConeConstantReference, data: Map<Int, FirExpression>): FirExpression? {
return when (constantReference) { return when (constantReference) {
ConeBooleanConstantReference.TRUE -> FirConstExpressionImpl(null, IrConstKind.Boolean, true) ConeBooleanConstantReference.TRUE -> FirConstExpressionImpl(null, FirConstKind.Boolean, true)
ConeBooleanConstantReference.FALSE -> FirConstExpressionImpl(null, IrConstKind.Boolean, false) ConeBooleanConstantReference.FALSE -> FirConstExpressionImpl(null, FirConstKind.Boolean, false)
ConeConstantReference.NULL -> createConstNull() ConeConstantReference.NULL -> createConstNull()
else -> null else -> null
} }
@@ -71,7 +71,7 @@ private object ConeConditionalEffectToFirVisitor : ConeContractDescriptionVisito
return data[valueParameterReference.parameterIndex] return data[valueParameterReference.parameterIndex]
} }
private fun createConstNull(): FirConstExpression<*> = FirConstExpressionImpl(null, IrConstKind.Null, null) private fun createConstNull(): FirConstExpression<*> = FirConstExpressionImpl(null, FirConstKind.Null, null)
} }
fun ConeConditionalEffectDeclaration.buildContractFir(argumentMapping: Map<Int, FirExpression>): FirExpression? { fun ConeConditionalEffectDeclaration.buildContractFir(argumentMapping: Map<Int, FirExpression>): FirExpression? {
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.CandidateApplicability
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
@@ -47,6 +48,11 @@ class FirVariableExpectedError : FirDiagnostic() {
override val reason: String get() = "Variable expected" override val reason: String get() = "Variable expected"
} }
class FirTypeMismatchError(val expectedType: ConeKotlinType, val actualType: ConeKotlinType) : FirDiagnostic() {
override val reason: String
get() = "Type mismatch. Expected: $expectedType, Actual: $actualType"
}
private fun describeSymbol(symbol: AbstractFirBasedSymbol<*>): String { private fun describeSymbol(symbol: AbstractFirBasedSymbol<*>): String {
return when (symbol) { return when (symbol) {
is FirClassLikeSymbol<*> -> symbol.classId.asString() is FirClassLikeSymbol<*> -> symbol.classId.asString()
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.diagnostics
import org.jetbrains.kotlin.diagnostics.Severity.* import org.jetbrains.kotlin.diagnostics.Severity.*
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import kotlin.reflect.full.memberProperties import kotlin.reflect.full.memberProperties
@@ -27,6 +28,7 @@ object FirErrors {
val RECURSION_IN_IMPLICIT_TYPES = DiagnosticFactory0.create<KtElement>(ERROR) val RECURSION_IN_IMPLICIT_TYPES = DiagnosticFactory0.create<KtElement>(ERROR)
val ERROR_FROM_JAVA_RESOLUTION = DiagnosticFactory0.create<KtElement>(ERROR) val ERROR_FROM_JAVA_RESOLUTION = DiagnosticFactory0.create<KtElement>(ERROR)
val OTHER_ERROR = DiagnosticFactory0.create<KtElement>(ERROR) val OTHER_ERROR = DiagnosticFactory0.create<KtElement>(ERROR)
val TYPE_MISMATCH = DiagnosticFactory2.create<KtElement, ConeKotlinType, ConeKotlinType>(ERROR)
init { init {
val klass = FirErrors::class val klass = FirErrors::class
@@ -57,6 +57,7 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
is FirAmbiguityError -> FirErrors.AMBIGUITY.onSource(source, diagnostic.candidates) is FirAmbiguityError -> FirErrors.AMBIGUITY.onSource(source, diagnostic.candidates)
is FirOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.onSource(source, diagnostic.candidates) is FirOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.onSource(source, diagnostic.candidates)
is FirVariableExpectedError -> Errors.VARIABLE_EXPECTED.onSource(source) is FirVariableExpectedError -> Errors.VARIABLE_EXPECTED.onSource(source)
is FirTypeMismatchError -> FirErrors.TYPE_MISMATCH.onSource(source, diagnostic.expectedType, diagnostic.actualType)
is FirSimpleDiagnostic -> diagnostic.getFactory().onSource(source) is FirSimpleDiagnostic -> diagnostic.getFactory().onSource(source)
is FirStubDiagnostic -> null is FirStubDiagnostic -> null
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${diagnostic.javaClass}") else -> throw IllegalArgumentException("Unsupported diagnostic type: ${diagnostic.javaClass}")
@@ -16,10 +16,8 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer import org.jetbrains.kotlin.fir.resolve.transformers.*
import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.MapArguments import org.jetbrains.kotlin.fir.resolve.transformers.MapArguments
import org.jetbrains.kotlin.fir.resolve.transformers.StoreType
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
@@ -98,12 +96,14 @@ class FirCallCompleter(
return call.transformSingle( return call.transformSingle(
FirCallCompletionResultsWriterTransformer( FirCallCompletionResultsWriterTransformer(
session, finalSubstitutor, returnTypeCalculator, session, finalSubstitutor, returnTypeCalculator,
inferenceComponents.approximator inferenceComponents.approximator,
integerOperatorsTypeUpdater,
integerLiteralTypeApproximator
), ),
null null
) )
} }
return call return call.transformSingle(integerOperatorsTypeUpdater, null)
} }
private inner class LambdaAnalyzerImpl( private inner class LambdaAnalyzerImpl(
@@ -70,6 +70,7 @@ abstract class AbstractConeSubstitutor : ConeSubstitutor() {
is ConeDefinitelyNotNullType -> this.substituteOriginal() is ConeDefinitelyNotNullType -> this.substituteOriginal()
is ConeIntersectionType -> this.substituteIntersectedTypes() is ConeIntersectionType -> this.substituteIntersectedTypes()
is ConeStubType -> return null is ConeStubType -> return null
is ConeIntegerLiteralType -> return null
} }
} }
@@ -16,11 +16,14 @@ import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.Candidate
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.calls.candidate import org.jetbrains.kotlin.fir.resolve.calls.candidate
import org.jetbrains.kotlin.fir.resolve.calls.isBuiltinFunctionalType
import org.jetbrains.kotlin.fir.resolve.constructFunctionalTypeRef import org.jetbrains.kotlin.fir.resolve.constructFunctionalTypeRef
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substituteOrNull import org.jetbrains.kotlin.fir.resolve.substitution.substituteOrNull
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.withNullability import org.jetbrains.kotlin.fir.resolve.withNullability
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
@@ -29,6 +32,7 @@ import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.fir.types.impl.FirTypeProjectionWithVarianceImpl import org.jetbrains.kotlin.fir.types.impl.FirTypeProjectionWithVarianceImpl
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.compose import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.types.AbstractTypeApproximator import org.jetbrains.kotlin.types.AbstractTypeApproximator
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
@@ -37,12 +41,14 @@ class FirCallCompletionResultsWriterTransformer(
override val session: FirSession, override val session: FirSession,
private val finalSubstitutor: ConeSubstitutor, private val finalSubstitutor: ConeSubstitutor,
private val typeCalculator: ReturnTypeCalculator, private val typeCalculator: ReturnTypeCalculator,
private val typeApproximator: AbstractTypeApproximator private val typeApproximator: AbstractTypeApproximator,
) : FirAbstractTreeTransformer<Nothing?>(phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { private val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater,
private val integerApproximator: IntegerLiteralTypeApproximationTransformer
) : FirAbstractTreeTransformer<ExpectedArgumentType?>(phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) {
override fun transformQualifiedAccessExpression( override fun transformQualifiedAccessExpression(
qualifiedAccessExpression: FirQualifiedAccessExpression, qualifiedAccessExpression: FirQualifiedAccessExpression,
data: Nothing? data: ExpectedArgumentType?
): CompositeTransformResult<FirStatement> { ): CompositeTransformResult<FirStatement> {
val calleeReference = val calleeReference =
qualifiedAccessExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return qualifiedAccessExpression.compose() qualifiedAccessExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return qualifiedAccessExpression.compose()
@@ -92,9 +98,8 @@ class FirCallCompletionResultsWriterTransformer(
override fun transformCallableReferenceAccess( override fun transformCallableReferenceAccess(
callableReferenceAccess: FirCallableReferenceAccess, callableReferenceAccess: FirCallableReferenceAccess,
data: Nothing? data: ExpectedArgumentType?
): CompositeTransformResult<FirStatement> { ): CompositeTransformResult<FirStatement> {
val calleeReference = val calleeReference =
callableReferenceAccess.calleeReference as? FirNamedReferenceWithCandidate ?: return callableReferenceAccess.compose() callableReferenceAccess.calleeReference as? FirNamedReferenceWithCandidate ?: return callableReferenceAccess.compose()
@@ -120,7 +125,7 @@ class FirCallCompletionResultsWriterTransformer(
override fun transformVariableAssignment( override fun transformVariableAssignment(
variableAssignment: FirVariableAssignment, variableAssignment: FirVariableAssignment,
data: Nothing? data: ExpectedArgumentType?
): CompositeTransformResult<FirStatement> { ): CompositeTransformResult<FirStatement> {
val calleeReference = variableAssignment.calleeReference as? FirNamedReferenceWithCandidate val calleeReference = variableAssignment.calleeReference as? FirNamedReferenceWithCandidate
?: return variableAssignment.compose() ?: return variableAssignment.compose()
@@ -134,9 +139,8 @@ class FirCallCompletionResultsWriterTransformer(
).compose() ).compose()
} }
override fun transformFunctionCall(functionCall: FirFunctionCall, data: Nothing?): CompositeTransformResult<FirStatement> { override fun transformFunctionCall(functionCall: FirFunctionCall, data: ExpectedArgumentType?): CompositeTransformResult<FirStatement> {
val calleeReference = functionCall.calleeReference as? FirNamedReferenceWithCandidate ?: return functionCall.compose() val calleeReference = functionCall.calleeReference as? FirNamedReferenceWithCandidate ?: return functionCall.compose()
val functionCall = functionCall.transformArguments(this, data) as FirFunctionCall
val subCandidate = calleeReference.candidate val subCandidate = calleeReference.candidate
val declaration = subCandidate.symbol.phasedFir as FirCallableMemberDeclaration<*> val declaration = subCandidate.symbol.phasedFir as FirCallableMemberDeclaration<*>
@@ -170,35 +174,62 @@ class FirCallCompletionResultsWriterTransformer(
} }
} }
val resultType = typeRef.substituteTypeRef(subCandidate) var result = functionCall.transformSingle(integerOperatorsTypeUpdater, null)
.transformCalleeReference(
StoreCalleeReference,
FirResolvedNamedReferenceImpl(
calleeReference.source,
calleeReference.name,
calleeReference.candidateSymbol
)
)
.transformDispatchReceiver(StoreReceiver, subCandidate.dispatchReceiverExpression())
.transformExtensionReceiver(StoreReceiver, subCandidate.extensionReceiverExpression())
val resultType: FirTypeRef
result = when (result) {
is FirIntegerOperatorCall -> {
val expectedType = data?.getExpectedType(functionCall)
resultType = typeRef.resolvedTypeFromPrototype(typeRef.coneTypeUnsafe<ConeIntegerLiteralType>().getApproximatedType(expectedType))
result.transformSingle(integerApproximator, expectedType)
}
else -> {
resultType = typeRef.substituteTypeRef(subCandidate)
result.transformArguments(this, subCandidate.createArgumentsMapping()).transformExplicitReceiver(integerApproximator, null)
}
}
return functionCall.copy( return result.copy(
resultType = resultType, resultType = resultType,
typeArguments = typeArguments, typeArguments = typeArguments
calleeReference = FirResolvedNamedReferenceImpl(
calleeReference.source,
calleeReference.name,
calleeReference.candidateSymbol
),
dispatchReceiver = subCandidate.dispatchReceiverExpression(),
extensionReceiver = subCandidate.extensionReceiverExpression()
).compose() ).compose()
}
private fun Candidate.createArgumentsMapping(): ExpectedArgumentType? {
return argumentMapping?.map { (argument, valueParameter) ->
val expectedType = valueParameter.returnTypeRef.coneTypeUnsafe<ConeKotlinType>()
.let { substitutor.substituteOrSelf(it) }
.let { finalSubstitutor.substituteOrSelf(it) }
argument.expandArgument() to expectedType
}
?.toMap()?.toExpectedType()
} }
override fun transformDelegatedConstructorCall( override fun transformDelegatedConstructorCall(
delegatedConstructorCall: FirDelegatedConstructorCall, delegatedConstructorCall: FirDelegatedConstructorCall,
data: Nothing? data: ExpectedArgumentType?
): CompositeTransformResult<FirStatement> { ): CompositeTransformResult<FirStatement> {
val calleeReference = delegatedConstructorCall.calleeReference as? FirNamedReferenceWithCandidate ?: return delegatedConstructorCall.compose() val calleeReference = delegatedConstructorCall.calleeReference as? FirNamedReferenceWithCandidate ?: return delegatedConstructorCall.compose()
val subCandidate = calleeReference.candidate val result = delegatedConstructorCall.transformArguments(this, calleeReference.candidate.createArgumentsMapping())
val result = delegatedConstructorCall.transformArguments(this, data) return result.transformCalleeReference(
return result.transformCalleeReference(StoreCalleeReference, FirResolvedNamedReferenceImpl( StoreCalleeReference,
calleeReference.source, FirResolvedNamedReferenceImpl(
calleeReference.name, calleeReference.source,
calleeReference.candidateSymbol calleeReference.name,
)).compose() calleeReference.candidateSymbol
)
).compose()
} }
private fun computeTypeArguments( private fun computeTypeArguments(
@@ -213,11 +244,15 @@ class FirCallCompletionResultsWriterTransformer(
override fun transformAnonymousFunction( override fun transformAnonymousFunction(
anonymousFunction: FirAnonymousFunction, anonymousFunction: FirAnonymousFunction,
data: Nothing? data: ExpectedArgumentType?
): CompositeTransformResult<FirStatement> { ): CompositeTransformResult<FirStatement> {
val expectedReturnType = data?.getExpectedType(anonymousFunction)
?.takeIf { it.isBuiltinFunctionalType }
?.let { it.typeArguments.last() as? ConeClassLikeType }
val initialType = anonymousFunction.returnTypeRef.coneTypeSafe<ConeKotlinType>() val initialType = anonymousFunction.returnTypeRef.coneTypeSafe<ConeKotlinType>()
if (initialType != null) { if (initialType != null) {
val finalType = finalSubstitutor.substituteOrNull(initialType) val finalType = expectedReturnType ?: finalSubstitutor.substituteOrNull(initialType)
val resultType = anonymousFunction.returnTypeRef.withReplacedConeType(finalType) val resultType = anonymousFunction.returnTypeRef.withReplacedConeType(finalType)
@@ -225,23 +260,26 @@ class FirCallCompletionResultsWriterTransformer(
anonymousFunction.replaceTypeRef(anonymousFunction.constructFunctionalTypeRef(session)) anonymousFunction.replaceTypeRef(anonymousFunction.constructFunctionalTypeRef(session))
} }
return transformElement(anonymousFunction, data) return transformElement(anonymousFunction, null)
} }
override fun transformBlock(block: FirBlock, data: Nothing?): CompositeTransformResult<FirStatement> { override fun transformBlock(block: FirBlock, data: ExpectedArgumentType?): CompositeTransformResult<FirStatement> {
val initialType = block.resultType.coneTypeSafe<ConeKotlinType>() val initialType = block.resultType.coneTypeSafe<ConeKotlinType>()
if (initialType != null) { if (initialType != null) {
val finalType = finalSubstitutor.substituteOrNull(initialType) val finalType = finalSubstitutor.substituteOrNull(initialType)
val resultType = block.resultType.withReplacedConeType(finalType) var resultType = block.resultType.withReplacedConeType(finalType)
resultType.coneTypeSafe<ConeIntegerLiteralType>()?.let {
resultType = resultType.resolvedTypeFromPrototype(it.getApproximatedType(data?.getExpectedType(block)))
}
block.replaceTypeRef(resultType) block.replaceTypeRef(resultType)
} }
return transformElement(block, data) return transformElement(block, data)
} }
override fun transformWhenExpression(whenExpression: FirWhenExpression, data: Nothing?): CompositeTransformResult<FirStatement> { override fun transformWhenExpression(whenExpression: FirWhenExpression, data: ExpectedArgumentType?): CompositeTransformResult<FirStatement> {
val calleeReference = whenExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return whenExpression.compose() val calleeReference = whenExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return whenExpression.compose()
val whenExpression = whenExpression.transformChildren(this, data) as FirWhenExpression val whenExpression = whenExpression.transformChildren(this, data?.getExpectedType(whenExpression)?.toExpectedType()) as FirWhenExpression
val declaration = whenExpression.candidate()?.symbol?.fir as? FirMemberFunction<*> ?: return whenExpression.compose() val declaration = whenExpression.candidate()?.symbol?.fir as? FirMemberFunction<*> ?: return whenExpression.compose()
@@ -261,7 +299,7 @@ class FirCallCompletionResultsWriterTransformer(
).compose() ).compose()
} }
override fun transformTryExpression(tryExpression: FirTryExpression, data: Nothing?): CompositeTransformResult<FirStatement> { override fun transformTryExpression(tryExpression: FirTryExpression, data: ExpectedArgumentType?): CompositeTransformResult<FirStatement> {
val calleeReference = tryExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return tryExpression.compose() val calleeReference = tryExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return tryExpression.compose()
val tryExpression = tryExpression.transformChildren(this, data) as FirTryExpression val tryExpression = tryExpression.transformChildren(this, data) as FirTryExpression
@@ -281,6 +319,40 @@ class FirCallCompletionResultsWriterTransformer(
calleeReference.candidateSymbol calleeReference.candidateSymbol
) )
).compose() ).compose()
}
override fun <T> transformConstExpression(
constExpression: FirConstExpression<T>,
data: ExpectedArgumentType?
): CompositeTransformResult<FirStatement> {
if (data == ExpectedArgumentType.NoApproximation) return constExpression.compose()
val expectedType = data?.getExpectedType(constExpression)
return constExpression.transform(integerApproximator, expectedType)
} }
} }
sealed class ExpectedArgumentType {
class ArgumentsMap(val map: Map<FirExpression, ConeKotlinType>) : ExpectedArgumentType()
class ExpectedType(val type: ConeKotlinType) : ExpectedArgumentType()
object NoApproximation : ExpectedArgumentType()
}
private fun ExpectedArgumentType.getExpectedType(argument: FirExpression): ConeKotlinType? = when (this) {
is ExpectedArgumentType.ArgumentsMap -> map[argument]
is ExpectedArgumentType.ExpectedType -> type
ExpectedArgumentType.NoApproximation -> null
}
private fun Map<FirExpression, ConeKotlinType>.toExpectedType(): ExpectedArgumentType = ExpectedArgumentType.ArgumentsMap(this)
fun ConeKotlinType.toExpectedType(): ExpectedArgumentType = ExpectedArgumentType.ExpectedType(this)
private fun FirExpression.expandArgument(): FirExpression = when (this) {
is FirWrappedArgumentExpression -> expression
else -> this
}
private fun ConeKotlinType.approximateIfPossible(expectedType: ConeKotlinType?) = if (this is ConeIntegerLiteralType) {
getApproximatedType(expectedType)
} else {
this
}
@@ -0,0 +1,203 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.impl.FirResolvedNamedReferenceImpl
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.calls.ConeInferenceContext
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperator
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.types.AbstractTypeChecker
class IntegerLiteralTypeApproximationTransformer(
private val symbolProvider: FirSymbolProvider,
private val inferenceContext: ConeInferenceContext
) : FirTransformer<ConeKotlinType?>() {
override fun <E : FirElement> transformElement(element: E, data: ConeKotlinType?): CompositeTransformResult<E> {
return element.compose()
}
override fun <T> transformConstExpression(
constExpression: FirConstExpression<T>,
data: ConeKotlinType?
): CompositeTransformResult<FirStatement> {
val type = constExpression.resultType.coneTypeSafe<ConeIntegerLiteralType>() ?: return constExpression.compose()
val approximatedType = type.getApproximatedType(data)
constExpression.resultType = constExpression.resultType.resolvedTypeFromPrototype(approximatedType)
@Suppress("UNCHECKED_CAST")
val kind = approximatedType.toConstKind() as FirConstKind<T>
constExpression.replaceKind(kind)
return constExpression.compose()
}
override fun transformFunctionCall(functionCall: FirFunctionCall, data: ConeKotlinType?): CompositeTransformResult<FirStatement> {
val operator = functionCall.toResolvedCallableSymbol()?.fir as? FirIntegerOperator ?: return functionCall.compose()
functionCall.transformChildren(this, data)
val argumentType = functionCall.arguments.firstOrNull()?.resultType?.coneTypeUnsafe<ConeClassLikeType>()
val receiverClassId = functionCall.dispatchReceiver.typeRef.coneTypeUnsafe<ConeClassLikeType>().lookupTag.classId
val scope = symbolProvider.getClassDeclaredMemberScope(receiverClassId)!!
var resultSymbol: FirFunctionSymbol<*>? = null
scope.processFunctionsByName(operator.name) { symbol ->
if (operator.kind.unary) {
resultSymbol = symbol
return@processFunctionsByName ProcessorAction.STOP
}
val function = symbol.fir
val valueParameterType = function.valueParameters.first().returnTypeRef.coneTypeUnsafe<ConeClassLikeType>()
if (AbstractTypeChecker.isSubtypeOf(inferenceContext, argumentType!!, valueParameterType)) {
resultSymbol = symbol
return@processFunctionsByName ProcessorAction.STOP
}
ProcessorAction.NEXT
}
// TODO: Maybe resultType = data?
// check black box tests
// e.g. Byte doesn't have `and` in member scope. It's an extension
if (resultSymbol == null) return functionCall.compose()
functionCall.resultType = data?.let { functionCall.resultType.resolvedTypeFromPrototype(it) } ?: resultSymbol.fir.returnTypeRef
return functionCall.transformCalleeReference(StoreCalleeReference, FirResolvedNamedReferenceImpl(null, operator.name, resultSymbol!!)).compose()
}
override fun transformOperatorCall(operatorCall: FirOperatorCall, data: ConeKotlinType?): CompositeTransformResult<FirStatement> {
if (operatorCall.operation !in FirOperation.BOOLEANS) return operatorCall.compose()
val leftArgument = operatorCall.arguments[0]
val rightArgument = operatorCall.arguments[1]
val leftIsIlt = leftArgument.typeRef.coneTypeSafe<ConeIntegerLiteralType>() != null
val rightIsIlt = rightArgument.typeRef.coneTypeSafe<ConeIntegerLiteralType>() != null
val expectedType: ConeKotlinType? = when {
!leftIsIlt && !rightIsIlt -> return operatorCall.compose()
leftIsIlt && rightIsIlt -> null
leftIsIlt -> rightArgument.typeRef.coneTypeUnsafe()
rightIsIlt -> leftArgument.typeRef.coneTypeUnsafe()
else -> throw IllegalStateException()
}
return operatorCall.transformArguments(this, expectedType).compose()
}
// TODO: call outside
override fun transformTypeOperatorCall(
typeOperatorCall: FirTypeOperatorCall,
data: ConeKotlinType?
): CompositeTransformResult<FirStatement> {
return typeOperatorCall.transformArguments(this, null).compose()
}
}
fun ConeClassLikeType.toConstKind(): FirConstKind<*> {
return when (this) {
ConeIntegerLiteralTypeImpl.INT_TYPE -> FirConstKind.Int
ConeIntegerLiteralTypeImpl.LONG_TYPE -> FirConstKind.Long
ConeIntegerLiteralTypeImpl.SHORT_TYPE -> FirConstKind.Short
ConeIntegerLiteralTypeImpl.BYTE_TYPE -> FirConstKind.Byte
else -> throw IllegalStateException()
}
}
fun FirFunctionCall.getOriginalFunction(): FirCallableDeclaration<*>? {
val symbol: AbstractFirBasedSymbol<*>? = when (val reference = calleeReference) {
is FirResolvedNamedReference -> reference.resolvedSymbol
is FirNamedReferenceWithCandidate -> reference.candidateSymbol
else -> null
}
return symbol?.fir as? FirCallableDeclaration<*>
}
class IntegerOperatorsTypeUpdater(val approximator: IntegerLiteralTypeApproximationTransformer) : FirTransformer<Nothing?>() {
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
return element.compose()
}
override fun transformFunctionCall(functionCall: FirFunctionCall, data: Nothing?): CompositeTransformResult<FirStatement> {
val function: FirCallableDeclaration<*> = functionCall.getOriginalFunction() ?: return functionCall.compose()
if (function !is FirIntegerOperator) {
val expectedType = function.receiverTypeRef?.coneTypeSafe<ConeKotlinType>()
return functionCall.transformExplicitReceiver(approximator, expectedType).compose()
}
// TODO: maybe unsafe?
val receiverValue = functionCall.explicitReceiver!!.typeRef.coneTypeSafe<ConeIntegerLiteralType>()?.value ?: return functionCall.compose()
val kind = function.kind
val resultValue = when {
kind.unary -> when (kind) {
FirIntegerOperator.Kind.UNARY_PLUS -> receiverValue
FirIntegerOperator.Kind.UNARY_MINUS -> -receiverValue
FirIntegerOperator.Kind.INV -> receiverValue.inv()
else -> throw IllegalStateException()
}
else -> {
val argumentType = functionCall.arguments.first().typeRef.coneTypeUnsafe<ConeKotlinType>()
// TODO: handle overflow
when (argumentType) {
is ConeIntegerLiteralType -> {
val argumentValue = argumentType.value
val divisionByZero = argumentValue == 0L
when (kind) {
FirIntegerOperator.Kind.PLUS -> receiverValue + argumentValue
FirIntegerOperator.Kind.MINUS -> receiverValue - argumentValue
FirIntegerOperator.Kind.TIMES -> receiverValue * argumentValue
// TODO: maybe add some error reporting (e.g. in userdata)
FirIntegerOperator.Kind.DIV -> if (divisionByZero) receiverValue else receiverValue / argumentValue
FirIntegerOperator.Kind.REM -> if (divisionByZero) receiverValue else receiverValue % argumentValue
// TODO: check that argument can be int
FirIntegerOperator.Kind.SHL -> receiverValue shl argumentValue.toInt()
FirIntegerOperator.Kind.SHR -> receiverValue shr argumentValue.toInt()
FirIntegerOperator.Kind.USHR -> receiverValue ushr argumentValue.toInt()
FirIntegerOperator.Kind.XOR -> receiverValue xor argumentValue
FirIntegerOperator.Kind.AND -> receiverValue and argumentValue
FirIntegerOperator.Kind.OR -> receiverValue or argumentValue
else -> throw IllegalStateException()
}
}
else -> {
val expectedType = when (argumentType) {
ConeIntegerLiteralTypeImpl.LONG_TYPE -> argumentType
else -> ConeIntegerLiteralTypeImpl.INT_TYPE
}
functionCall.transformSingle(approximator, expectedType)
functionCall.replaceTypeRef(functionCall.resultType.resolvedTypeFromPrototype(expectedType))
return functionCall.compose()
}
}
}
}
functionCall.replaceTypeRef(functionCall.resultType.resolvedTypeFromPrototype(ConeIntegerLiteralTypeImpl(resultValue)))
return functionCall.toOperatorCall().compose()
}
}
private fun FirFunctionCall.toOperatorCall(): FirIntegerOperatorCall {
if (this is FirIntegerOperatorCall) return this
return FirIntegerOperatorCall(source).also {
it.typeRef = typeRef
it.annotations += annotations
it.safe = safe
it.typeArguments += typeArguments
it.explicitReceiver = explicitReceiver
it.dispatchReceiver = dispatchReceiver
it.extensionReceiver = extensionReceiver
it.arguments += arguments
it.calleeReference = calleeReference
}
}
@@ -79,6 +79,9 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
protected inline val dataFlowAnalyzer: FirDataFlowAnalyzer get() = components.dataFlowAnalyzer protected inline val dataFlowAnalyzer: FirDataFlowAnalyzer get() = components.dataFlowAnalyzer
protected inline val scopeSession: ScopeSession get() = components.scopeSession protected inline val scopeSession: ScopeSession get() = components.scopeSession
protected inline val file: FirFile get() = components.file protected inline val file: FirFile get() = components.file
protected inline val integerLiteralTypeApproximator: IntegerLiteralTypeApproximationTransformer get() = components.integerLiteralTypeApproximator
protected inline val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater get() = components.integerOperatorsTypeUpdater
val ResolutionMode.expectedType: FirTypeRef? val ResolutionMode.expectedType: FirTypeRef?
get() = when (this) { get() = when (this) {
@@ -122,7 +125,9 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
val callCompleter: FirCallCompleter = FirCallCompleter(transformer, this) val callCompleter: FirCallCompleter = FirCallCompleter(transformer, this)
override val dataFlowAnalyzer: FirDataFlowAnalyzer = FirDataFlowAnalyzer(this) override val dataFlowAnalyzer: FirDataFlowAnalyzer = FirDataFlowAnalyzer(this)
override val syntheticCallGenerator: FirSyntheticCallGenerator = FirSyntheticCallGenerator(this, callCompleter) override val syntheticCallGenerator: FirSyntheticCallGenerator = FirSyntheticCallGenerator(this, callCompleter)
override val integerLiteralTypeApproximator: IntegerLiteralTypeApproximationTransformer =
IntegerLiteralTypeApproximationTransformer(symbolProvider, inferenceComponents.ctx)
override val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater = IntegerOperatorsTypeUpdater(integerLiteralTypeApproximator)
internal var containerIfAny: FirDeclaration? = null internal var containerIfAny: FirDeclaration? = null
private set private set
@@ -15,9 +15,12 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator
import org.jetbrains.kotlin.fir.resolve.transformers.FirWhenExhaustivenessTransformer import org.jetbrains.kotlin.fir.resolve.transformers.FirWhenExhaustivenessTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.IntegerLiteralTypeApproximationTransformer
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.compose import org.jetbrains.kotlin.fir.visitors.compose
@@ -168,9 +171,13 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
// ------------------------------- Jumps ------------------------------- // ------------------------------- Jumps -------------------------------
override fun <E : FirTargetElement> transformJump(jump: FirJump<E>, data: ResolutionMode): CompositeTransformResult<FirStatement> { override fun <E : FirTargetElement> transformJump(jump: FirJump<E>, data: ResolutionMode): CompositeTransformResult<FirStatement> {
val result = transformer.transformExpression(jump, data) var result = transformer.transformExpression(jump, data).single
if (result is FirReturnExpression) {
val expectedType = result.target.labeledElement.returnTypeRef.coneTypeSafe<ConeKotlinType>()
result = result.transformResult(integerLiteralTypeApproximator, expectedType)
}
dataFlowAnalyzer.exitJump(jump) dataFlowAnalyzer.exitJump(jump)
return result return result.compose()
} }
override fun transformThrowExpression(throwExpression: FirThrowExpression, data: ResolutionMode): CompositeTransformResult<FirStatement> { override fun transformThrowExpression(throwExpression: FirThrowExpression, data: ResolutionMode): CompositeTransformResult<FirStatement> {
@@ -19,8 +19,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitExtensionReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.ImplicitExtensionReceiverValue
import org.jetbrains.kotlin.fir.resolve.calls.extractLambdaInfoFromFunctionalType import org.jetbrains.kotlin.fir.resolve.calls.extractLambdaInfoFromFunctionalType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.ControlFlowGraphReferenceTransformer import org.jetbrains.kotlin.fir.resolve.transformers.*
import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolveTransformer.Companion.resolveStatus import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolveTransformer.Companion.resolveStatus
import org.jetbrains.kotlin.fir.resolve.transformers.StoreType import org.jetbrains.kotlin.fir.resolve.transformers.StoreType
import org.jetbrains.kotlin.fir.resolve.transformers.transformVarargTypeToArrayType import org.jetbrains.kotlin.fir.resolve.transformers.transformVarargTypeToArrayType
@@ -104,6 +103,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
localScopes.addIfNotNull(primaryConstructorParametersScope) localScopes.addIfNotNull(primaryConstructorParametersScope)
components.withContainer(property) { components.withContainer(property) {
property.transformChildrenWithoutAccessors(returnTypeRef) property.transformChildrenWithoutAccessors(returnTypeRef)
property.transformInitializer(integerLiteralTypeApproximator, null)
if (property.initializer != null) { if (property.initializer != null) {
storeVariableReturnType(property) storeVariableReturnType(property)
} }
@@ -125,7 +125,10 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
private fun transformLocalVariable(variable: FirProperty): CompositeTransformResult<FirDeclaration> { private fun transformLocalVariable(variable: FirProperty): CompositeTransformResult<FirDeclaration> {
assert(variable.isLocal) assert(variable.isLocal)
variable.transformOtherChildren(transformer, withExpectedType(variable.returnTypeRef)) val resolutionMode = withExpectedType(variable.returnTypeRef)
variable.transformOtherChildren(transformer, resolutionMode)
.transformInitializer(transformer, resolutionMode)
.transformInitializer(integerLiteralTypeApproximator, null)
if (variable.initializer != null) { if (variable.initializer != null) {
storeVariableReturnType(variable) storeVariableReturnType(variable)
} }
@@ -138,7 +141,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
private fun FirProperty.transformChildrenWithoutAccessors(returnTypeRef: FirTypeRef): FirProperty { private fun FirProperty.transformChildrenWithoutAccessors(returnTypeRef: FirTypeRef): FirProperty {
val data = withExpectedType(returnTypeRef) val data = withExpectedType(returnTypeRef)
return transformReturnTypeRef(transformer, data).transformOtherChildren(transformer, data) return transformInitializer(transformer, data).transformOtherChildren(transformer, data)
} }
private fun <F : FirVariable<F>> FirVariable<F>.transformAccessors() { private fun <F : FirVariable<F>> FirVariable<F>.transformAccessors() {
@@ -380,6 +383,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
valueParameter.replaceResolvePhase(transformerPhase) valueParameter.replaceResolvePhase(transformerPhase)
return valueParameter.compose() // TODO return valueParameter.compose() // TODO
} }
val valueParameter = valueParameter.transformInitializer(integerLiteralTypeApproximator, valueParameter.returnTypeRef.coneTypeSafe())
return (transformDeclaration(valueParameter, withExpectedType(valueParameter.returnTypeRef)).single as FirStatement).compose() return (transformDeclaration(valueParameter, withExpectedType(valueParameter.returnTypeRef)).single as FirStatement).compose()
} }
@@ -464,9 +468,11 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
session, session,
ConeSubstitutor.Empty, ConeSubstitutor.Empty,
returnTypeCalculator, returnTypeCalculator,
inferenceComponents.approximator inferenceComponents.approximator,
integerOperatorsTypeUpdater,
integerLiteralTypeApproximator
) )
af.transformSingle(writer, null) af.transformSingle(writer, data.expectedTypeRef.coneTypeSafe<ConeKotlinType>()?.toExpectedType())
val returnTypes = dataFlowAnalyzer.returnExpressionsOfAnonymousFunction(af).mapNotNull { (it as? FirExpression)?.resultType?.coneTypeUnsafe() } val returnTypes = dataFlowAnalyzer.returnExpressionsOfAnonymousFunction(af).mapNotNull { (it as? FirExpression)?.resultType?.coneTypeUnsafe() }
af.replaceReturnTypeRef(af.returnTypeRef.resolvedTypeFromPrototype(inferenceComponents.ctx.commonSuperTypeOrNull(returnTypes) ?: session.builtinTypes.unitType.coneTypeUnsafe())) af.replaceReturnTypeRef(af.returnTypeRef.resolvedTypeFromPrototype(inferenceComponents.ctx.commonSuperTypeOrNull(returnTypes) ?: session.builtinTypes.unitType.coneTypeUnsafe()))
af.replaceTypeRef(af.constructFunctionalTypeRef(session)) af.replaceTypeRef(af.constructFunctionalTypeRef(session))
@@ -5,10 +5,11 @@
package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
import org.jetbrains.kotlin.fir.BuiltinTypes import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.FirCallResolver import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirTypeParametersOwner import org.jetbrains.kotlin.fir.declarations.FirTypeParametersOwner
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirErrorExpressionImpl import org.jetbrains.kotlin.fir.expressions.impl.FirErrorExpressionImpl
@@ -21,14 +22,14 @@ import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.references.impl.FirErrorNamedReferenceImpl import org.jetbrains.kotlin.fir.references.impl.FirErrorNamedReferenceImpl
import org.jetbrains.kotlin.fir.references.impl.FirExplicitThisReference import org.jetbrains.kotlin.fir.references.impl.FirExplicitThisReference
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.candidate import org.jetbrains.kotlin.fir.resolve.calls.candidate
import org.jetbrains.kotlin.fir.resolve.diagnostics.FirOperatorAmbiguityError import org.jetbrains.kotlin.fir.resolve.diagnostics.FirOperatorAmbiguityError
import org.jetbrains.kotlin.fir.resolve.diagnostics.FirTypeMismatchError
import org.jetbrains.kotlin.fir.resolve.diagnostics.FirVariableExpectedError import org.jetbrains.kotlin.fir.resolve.diagnostics.FirVariableExpectedError
import org.jetbrains.kotlin.fir.resolve.transformers.IntegerLiteralTypeApproximationTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol
@@ -40,7 +41,6 @@ import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.compose import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
@@ -192,9 +192,10 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
override fun transformOperatorCall(operatorCall: FirOperatorCall, data: ResolutionMode): CompositeTransformResult<FirStatement> { override fun transformOperatorCall(operatorCall: FirOperatorCall, data: ResolutionMode): CompositeTransformResult<FirStatement> {
if (operatorCall.operation in FirOperation.BOOLEANS) { if (operatorCall.operation in FirOperation.BOOLEANS) {
// TODO: add approximation of integer literals
val result = (operatorCall.transformChildren(transformer, ResolutionMode.ContextIndependent) as FirOperatorCall).also { val result = (operatorCall.transformChildren(transformer, ResolutionMode.ContextIndependent) as FirOperatorCall).also {
it.resultType = operatorCall.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type) it.resultType = operatorCall.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type)
} }.transformSingle(integerLiteralTypeApproximator, null)
dataFlowAnalyzer.exitOperatorCall(result) dataFlowAnalyzer.exitOperatorCall(result)
return result.compose() return result.compose()
} }
@@ -259,8 +260,9 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
data: ResolutionMode data: ResolutionMode
): CompositeTransformResult<FirStatement> { ): CompositeTransformResult<FirStatement> {
val symbolProvider = session.firSymbolProvider val symbolProvider = session.firSymbolProvider
val resolved = transformExpression(typeOperatorCall, data).single val resolved = (transformExpression(typeOperatorCall, data).single as FirTypeOperatorCall)
when ((resolved as FirTypeOperatorCall).operation) { .transformArguments(integerLiteralTypeApproximator, null)
when (resolved.operation) {
FirOperation.IS, FirOperation.NOT_IS -> { FirOperation.IS, FirOperation.NOT_IS -> {
resolved.resultType = FirResolvedTypeRefImpl( resolved.resultType = FirResolvedTypeRefImpl(
null, null,
@@ -279,7 +281,7 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
else -> error("Unknown type operator") else -> error("Unknown type operator")
} }
dataFlowAnalyzer.exitTypeOperatorCall(typeOperatorCall) dataFlowAnalyzer.exitTypeOperatorCall(typeOperatorCall)
return resolved.compose() return resolved.transform(integerLiteralTypeApproximator, null)
} }
override fun transformBinaryLogicExpression( override fun transformBinaryLogicExpression(
@@ -313,6 +315,7 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
val completeAssignment = callCompleter.completeCall(resolvedAssignment, noExpectedType) // TODO: check val completeAssignment = callCompleter.completeCall(resolvedAssignment, noExpectedType) // TODO: check
val expectedType = components.typeFromCallee(completeAssignment) val expectedType = components.typeFromCallee(completeAssignment)
completeAssignment.transformRValue(transformer, withExpectedType(expectedType)) completeAssignment.transformRValue(transformer, withExpectedType(expectedType))
.transformRValue(integerLiteralTypeApproximator, expectedType.coneTypeSafe())
} else { } else {
// This can happen in erroneous code only // This can happen in erroneous code only
resolvedAssignment resolvedAssignment
@@ -396,36 +399,57 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
} }
override fun <T> transformConstExpression(constExpression: FirConstExpression<T>, data: ResolutionMode): CompositeTransformResult<FirStatement> { override fun <T> transformConstExpression(constExpression: FirConstExpression<T>, data: ResolutionMode): CompositeTransformResult<FirStatement> {
// TODO: add support of IntegerLiteralType
constExpression.annotations.forEach { it.accept(this, data) } constExpression.annotations.forEach { it.accept(this, data) }
val kind = constExpression.kind val kind = constExpression.kind
val symbol = when (kind) { val symbol = when (kind) {
IrConstKind.Null -> StandardClassIds.Nothing(symbolProvider) FirConstKind.Null -> StandardClassIds.Nothing(symbolProvider)
IrConstKind.Boolean -> StandardClassIds.Boolean(symbolProvider) FirConstKind.Boolean -> StandardClassIds.Boolean(symbolProvider)
IrConstKind.Char -> StandardClassIds.Char(symbolProvider) FirConstKind.Char -> StandardClassIds.Char(symbolProvider)
IrConstKind.Byte -> StandardClassIds.Byte(symbolProvider) FirConstKind.Byte -> StandardClassIds.Byte(symbolProvider)
IrConstKind.Short -> StandardClassIds.Short(symbolProvider) FirConstKind.Short -> StandardClassIds.Short(symbolProvider)
IrConstKind.Int -> StandardClassIds.Int(symbolProvider) FirConstKind.Int -> StandardClassIds.Int(symbolProvider)
IrConstKind.Long -> StandardClassIds.Long(symbolProvider) FirConstKind.Long -> StandardClassIds.Long(symbolProvider)
IrConstKind.String -> StandardClassIds.String(symbolProvider) FirConstKind.String -> StandardClassIds.String(symbolProvider)
IrConstKind.Float -> StandardClassIds.Float(symbolProvider) FirConstKind.Float -> StandardClassIds.Float(symbolProvider)
IrConstKind.Double -> StandardClassIds.Double(symbolProvider) FirConstKind.Double -> StandardClassIds.Double(symbolProvider)
FirConstKind.IntegerLiteral -> null
} }
val type = ConeClassLikeTypeImpl(symbol.toLookupTag(), emptyArray(), isNullable = kind == IrConstKind.Null) val type = if (symbol != null) {
ConeClassLikeTypeImpl(symbol.toLookupTag(), emptyArray(), isNullable = kind == FirConstKind.Null)
constExpression.resultType = FirResolvedTypeRefImpl(null, type) } else {
val integerLiteralType = ConeIntegerLiteralTypeImpl(constExpression.value as Long)
val expectedType = data.expectedType?.coneTypeSafe<ConeKotlinType>()
if (expectedType != null) {
val approximatedType = integerLiteralType.getApproximatedType(expectedType)
val newConstKind = approximatedType.toConstKind()
if (newConstKind == null) {
constExpression.replaceKind(FirConstKind.Int as FirConstKind<T>)
dataFlowAnalyzer.exitConstExpresion(constExpression as FirConstExpression<*>)
constExpression.resultType = FirErrorTypeRefImpl(
constExpression.source,
FirTypeMismatchError(expectedType, integerLiteralType.getApproximatedType())
)
return constExpression.compose()
}
constExpression.replaceKind(newConstKind as FirConstKind<T>)
approximatedType
} else {
integerLiteralType
}
}
dataFlowAnalyzer.exitConstExpresion(constExpression as FirConstExpression<*>) dataFlowAnalyzer.exitConstExpresion(constExpression as FirConstExpression<*>)
constExpression.resultType = constExpression.resultType.resolvedTypeFromPrototype(type)
return constExpression.compose() return constExpression.compose()
} }
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: ResolutionMode): CompositeTransformResult<FirStatement> { override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: ResolutionMode): CompositeTransformResult<FirStatement> {
dataFlowAnalyzer.enterAnnotationCall(annotationCall) dataFlowAnalyzer.enterAnnotationCall(annotationCall)
return (annotationCall.transformChildren(transformer, data) as FirAnnotationCall).also { return (annotationCall.transformChildren(transformer, data) as FirAnnotationCall)
dataFlowAnalyzer.exitAnnotationCall(it) // TODO: it's temporary incorrect solution until we design resolve and completion for annotation calls
}.compose() .transformArguments(integerLiteralTypeApproximator, null).also {
dataFlowAnalyzer.exitAnnotationCall(it)
}.compose()
} }
private fun ConeKotlinTypeProjection.toFirTypeProjection(): FirTypeProjection = when (this) { private fun ConeKotlinTypeProjection.toFirTypeProjection(): FirTypeProjection = when (this) {
@@ -0,0 +1,173 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.FirSymbolOwner
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirSimpleFunctionImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolve.scopeSessionKey
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralTypeImpl
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions
private object FirIntegerLiteralTypeClassifierSymbol : FirClassifierSymbol<FirIntegerLiteralTypeClassifier>() {
override fun toLookupTag(): ConeClassifierLookupTag {
throw IllegalStateException("Should not be called")
}
}
private object FirIntegerLiteralTypeClassifier : FirDeclaration, FirSymbolOwner<FirIntegerLiteralTypeClassifier> {
override val symbol: AbstractFirBasedSymbol<FirIntegerLiteralTypeClassifier>
get() = FirIntegerLiteralTypeClassifierSymbol
override val source: FirSourceElement? get() = throw IllegalStateException("Should not be called")
override val session: FirSession get() = throw IllegalStateException("Should not be called")
override val resolvePhase: FirResolvePhase get() = throw IllegalStateException("Should not be called")
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R {
throw IllegalStateException("Should not be called")
}
override fun replaceResolvePhase(newResolvePhase: FirResolvePhase) {
throw IllegalStateException("Should not be called")
}
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
throw IllegalStateException("Should not be called")
}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
throw IllegalStateException("Should not be called")
}
}
class FirIntegerLiteralTypeScope(private val session: FirSession) : FirScope() {
companion object {
val BINARY_OPERATOR_NAMES = FirIntegerOperator.Kind.values().filterNot { it.unary }.map { it.operatorName }
val UNARY_OPERATOR_NAMES = FirIntegerOperator.Kind.values().filter { it.unary }.map { it.operatorName }
private val ALL_OPERATORS = FirIntegerOperator.Kind.values().map { it.operatorName to it }.toMap()
val ILT_SYMBOL: FirClassifierSymbol<*> = FirIntegerLiteralTypeClassifierSymbol
val SCOPE_SESSION_KEY = scopeSessionKey<FirIntegerLiteralTypeScope>()
}
private val BINARY_OPERATOR_SYMBOLS = BINARY_OPERATOR_NAMES.map { name ->
name to FirNamedFunctionSymbol(CallableId(name)).apply {
createFirFunction(name, this).apply {
val valueParameterName = Name.identifier("arg")
valueParameters += FirValueParameterImpl(
source = null,
session,
FirILTTypeRefPlaceHolder(),
valueParameterName,
FirVariableSymbol(name),
defaultValue = null,
isCrossinline = false,
isNoinline = false,
isVararg = false
)
}
}
}.toMap()
private val UNARY_OPERATOR_SYMBOLS = UNARY_OPERATOR_NAMES.map { name ->
name to FirNamedFunctionSymbol(CallableId(name)).apply { createFirFunction(name, this) }
}.toMap()
private fun createFirFunction(name: Name, symbol: FirNamedFunctionSymbol): FirSimpleFunctionImpl = FirIntegerOperator(
source = null,
session,
FirILTTypeRefPlaceHolder(),
receiverTypeRef = null,
ALL_OPERATORS.getValue(name),
FirResolvedDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL),
symbol
).apply {
resolvePhase = FirResolvePhase.BODY_RESOLVE
}
override fun processClassifiersByName(name: Name, processor: (FirClassifierSymbol<*>) -> ProcessorAction): ProcessorAction {
return ProcessorAction.NONE
}
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
val symbol = BINARY_OPERATOR_SYMBOLS[name]
?: UNARY_OPERATOR_SYMBOLS[name]
?: return ProcessorAction.NONE
return processor(symbol)
}
override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction {
return ProcessorAction.NONE
}
}
class FirIntegerOperator(
source: FirSourceElement?,
session: FirSession,
returnTypeRef: FirTypeRef,
receiverTypeRef: FirTypeRef?,
val kind: Kind,
status: FirDeclarationStatus,
symbol: FirFunctionSymbol<FirSimpleFunction>
) : FirSimpleFunctionImpl(source, session, returnTypeRef, receiverTypeRef, kind.operatorName, status, symbol) {
enum class Kind(val unary: Boolean, val operatorName: Name) {
PLUS(false, OperatorNameConventions.PLUS),
MINUS(false, OperatorNameConventions.MINUS),
TIMES(false, OperatorNameConventions.TIMES),
DIV(false, OperatorNameConventions.DIV),
REM(false, OperatorNameConventions.REM),
SHL(false, Name.identifier("shl")),
SHR(false, Name.identifier("shr")),
USHR(false, Name.identifier("ushr")),
XOR(false, Name.identifier("xor")),
AND(false, Name.identifier("and")),
OR(false, Name.identifier("or")),
UNARY_PLUS(true, OperatorNameConventions.UNARY_PLUS),
UNARY_MINUS(true, OperatorNameConventions.UNARY_MINUS),
INV(true, Name.identifier("inv"))
}
}
class FirILTTypeRefPlaceHolder : FirResolvedTypeRef() {
override val source: FirSourceElement? get() = null
override val annotations: List<FirAnnotationCall> get() = emptyList()
override var type: ConeIntegerLiteralType = ConeIntegerLiteralTypeImpl(0)
override val delegatedTypeRef: FirTypeRef? get() = null
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
return this
}
}
class FirIntegerOperatorCall(source: FirSourceElement?) : FirFunctionCallImpl(source)
@@ -38,21 +38,24 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
val session: FirSession val session: FirSession
override fun TypeConstructorMarker.isIntegerLiteralTypeConstructor(): Boolean { override fun TypeConstructorMarker.isIntegerLiteralTypeConstructor(): Boolean {
// TODO() return this is ConeIntegerLiteralType
return false
} }
override fun SimpleTypeMarker.possibleIntegerTypes(): Collection<KotlinTypeMarker> { override fun SimpleTypeMarker.possibleIntegerTypes(): Collection<KotlinTypeMarker> {
TODO("not implemented") return (this as? ConeIntegerLiteralType)?.possibleTypes ?: emptyList()
} }
override fun SimpleTypeMarker.fastCorrespondingSupertypes(constructor: TypeConstructorMarker): List<SimpleTypeMarker>? { override fun SimpleTypeMarker.fastCorrespondingSupertypes(constructor: TypeConstructorMarker): List<SimpleTypeMarker>? {
require(this is ConeKotlinType) require(this is ConeKotlinType)
return session.correspondingSupertypesCache.getCorrespondingSupertypes(this, constructor) return if (this is ConeIntegerLiteralType) {
supertypes
} else {
session.correspondingSupertypesCache.getCorrespondingSupertypes(this, constructor)
}
} }
override fun SimpleTypeMarker.isIntegerLiteralType(): Boolean { override fun SimpleTypeMarker.isIntegerLiteralType(): Boolean {
return false return this is ConeIntegerLiteralType
} }
override fun KotlinTypeMarker.asSimpleType(): SimpleTypeMarker? { override fun KotlinTypeMarker.asSimpleType(): SimpleTypeMarker? {
@@ -65,6 +68,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is ConeIntersectionType -> this is ConeIntersectionType -> this
is ConeFlexibleType -> null is ConeFlexibleType -> null
is ConeStubType -> this is ConeStubType -> this
is ConeIntegerLiteralType -> this
else -> error("Unknown simpleType: $this") else -> error("Unknown simpleType: $this")
} }
} }
@@ -134,6 +138,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is ConeIntersectionType -> this is ConeIntersectionType -> this
is ConeStubType -> variable.typeConstructor is ConeStubType -> variable.typeConstructor
is ConeDefinitelyNotNullType -> original.typeConstructor() is ConeDefinitelyNotNullType -> original.typeConstructor()
is ConeIntegerLiteralType -> this
else -> error("?: $this") else -> error("?: $this")
} }
} }
@@ -210,6 +215,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is ConeIntersectionType -> 0 is ConeIntersectionType -> 0
is FirRegularClassSymbol -> fir.typeParameters.size is FirRegularClassSymbol -> fir.typeParameters.size
is FirTypeAliasSymbol -> fir.typeParameters.size is FirTypeAliasSymbol -> fir.typeParameters.size
is ConeIntegerLiteralType -> 0
else -> error("?!:10") else -> error("?!:10")
} }
} }
@@ -234,6 +240,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is FirTypeAliasSymbol -> listOfNotNull(fir.expandedConeType) is FirTypeAliasSymbol -> listOfNotNull(fir.expandedConeType)
is ConeCapturedTypeConstructor -> supertypes!! is ConeCapturedTypeConstructor -> supertypes!!
is ConeIntersectionType -> intersectedTypes is ConeIntersectionType -> intersectedTypes
is ConeIntegerLiteralType -> supertypes
else -> error("?!:13") else -> error("?!:13")
} }
} }
@@ -280,7 +287,8 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
return when (this) { return when (this) {
is ConeCapturedTypeConstructor, is ConeCapturedTypeConstructor,
is ConeTypeVariableTypeConstructor, is ConeTypeVariableTypeConstructor,
is ConeIntersectionType -> false is ConeIntersectionType,
is ConeIntegerLiteralType -> false
is AbstractFirBasedSymbol<*> -> true is AbstractFirBasedSymbol<*> -> true
else -> true else -> true
} }
@@ -363,6 +371,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
if (this is ConeCapturedType) return true if (this is ConeCapturedType) return true
if (this is ConeTypeVariableType) return false if (this is ConeTypeVariableType) return false
if (this is ConeIntersectionType) return false if (this is ConeIntersectionType) return false
if (this is ConeIntegerLiteralType) return true
if (this is ConeStubType) return true if (this is ConeStubType) return true
if (this is ConeDefinitelyNotNullType) return true if (this is ConeDefinitelyNotNullType) return true
require(this is ConeLookupTagBasedType) require(this is ConeLookupTagBasedType)
@@ -0,0 +1,48 @@
fun takeInt(x: Int) {}
fun takeLong(x: Long) {}
fun takeByte(x: Byte) {}
fun takeAny(x: Any) {}
fun takeString(x: String) {}
fun test_0() {
1l
1
10000000000
}
fun test_1() {
takeInt(1)
takeByte(1)
takeLong(1)
}
fun test_2() {
<!INAPPLICABLE_CANDIDATE!>takeInt<!>(10000000000)
takeLong(10000000000)
<!INAPPLICABLE_CANDIDATE!>takeByte<!>(1000)
}
fun test_3() {
takeInt(run { 1 })
takeByte(run { 1 })
takeLong(run { 1 })
}
fun test_4() {
takeAny(1)
takeAny(run { 1 })
}
fun test_5() {
<!INAPPLICABLE_CANDIDATE!>takeString<!>(1)
<!INAPPLICABLE_CANDIDATE!>takeString<!>(run { 1 })
}
annotation class Ann(val x: Byte)
@Ann(10)
fun test_6() {
@Ann(300)
val x = ""
}
@@ -0,0 +1,66 @@
FILE: integerLiteralTypes.kt
public final fun takeInt(x: R|kotlin/Int|): R|kotlin/Unit| {
}
public final fun takeLong(x: R|kotlin/Long|): R|kotlin/Unit| {
}
public final fun takeByte(x: R|kotlin/Byte|): R|kotlin/Unit| {
}
public final fun takeAny(x: R|kotlin/Any|): R|kotlin/Unit| {
}
public final fun takeString(x: R|kotlin/String|): R|kotlin/Unit| {
}
public final fun test_0(): R|kotlin/Unit| {
Long(1)
Int(1)
Long(10000000000)
}
public final fun test_1(): R|kotlin/Unit| {
R|/takeInt|(Int(1))
R|/takeByte|(Byte(1))
R|/takeLong|(Long(1))
}
public final fun test_2(): R|kotlin/Unit| {
<Inapplicable(INAPPLICABLE): [/takeInt]>#(Long(10000000000))
R|/takeLong|(Long(10000000000))
<Inapplicable(INAPPLICABLE): [/takeByte]>#(Int(1000))
}
public final fun test_3(): R|kotlin/Unit| {
R|/takeInt|(R|kotlin/run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
Int(1)
}
))
R|/takeByte|(R|kotlin/run|<R|kotlin/Byte|>(<L> = run@fun <anonymous>(): R|kotlin/Byte| <kind=EXACTLY_ONCE> {
Int(1)
}
))
R|/takeLong|(R|kotlin/run|<R|kotlin/Long|>(<L> = run@fun <anonymous>(): R|kotlin/Long| <kind=EXACTLY_ONCE> {
Int(1)
}
))
}
public final fun test_4(): R|kotlin/Unit| {
R|/takeAny|(Int(1))
R|/takeAny|(R|kotlin/run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
Int(1)
}
))
}
public final fun test_5(): R|kotlin/Unit| {
<Inapplicable(INAPPLICABLE): [/takeString]>#(Int(1))
<Inapplicable(INAPPLICABLE): [/takeString]>#(R|kotlin/run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
Int(1)
}
))
}
public final annotation class Ann : R|kotlin/Annotation| {
public constructor(x: R|kotlin/Byte|): R|Ann| {
super<R|kotlin/Any|>()
}
public final val x: R|kotlin/Byte| = R|<local>/x|
public get(): R|kotlin/Byte|
}
@R|Ann|(Int(10)) public final fun test_6(): R|kotlin/Unit| {
@R|Ann|(Int(300)) lval x: R|kotlin/String| = String()
}
@@ -0,0 +1,69 @@
fun foo(x: Int) {}
fun foo(x: Byte) {}
fun test_0() {
foo(1)
}
fun test_1() {
val x1 = 1 + 1
val x2 = 1.plus(1)
1 + 1
127 + 1
val x3 = 2000000000 * 4
}
fun test_2(n: Int) {
val x = 1 + n
val y = n + 1
}
fun Int.bar(): Int {}
fun Int.baz(): Int
fun Byte.baz(): Byte {}
fun test_3() {
val x = 1.bar()
val y = 1.baz()
}
fun takeByte(b: Byte) {}
fun test_4() {
takeByte(1 + 1)
<!INAPPLICABLE_CANDIDATE!>takeByte<!>(1 + 127)
takeByte(1 - 1)
<!INAPPLICABLE_CANDIDATE!>takeByte<!>(-100 - 100)
takeByte(10 * 10)
<!INAPPLICABLE_CANDIDATE!>takeByte<!>(100 * 100)
<!UNRESOLVED_REFERENCE!>taleByte<!>(10 / 10)
takeByte(100 % 10)
takeByte(1000 % 10)
takeByte(1000 and 100)
<!INAPPLICABLE_CANDIDATE!>takeByte<!>(128 and 511)
takeByte(100 or 100)
<!INAPPLICABLE_CANDIDATE!>takeByte<!>(1000 or 0)
takeByte(511 xor 511)
<!INAPPLICABLE_CANDIDATE!>takeByte<!>(512 xor 511)
}
fun test_5() {
takeByte(-1)
takeByte(+1)
takeByte(1.inv())
}
fun test_6() {
<!INAPPLICABLE_CANDIDATE!>takeByte<!>(run { 127 + 1 })
<!INAPPLICABLE_CANDIDATE!>takeByte<!>(1 <!INAPPLICABLE_CANDIDATE!>+<!> run { 1 })
takeByte(run { 1 + 1 })
1 + 1
run { 1 }
1 + run { 1 }
}
fun test_7(d: Double) {
val x1 = 1 + d
val x2 = d + 1
}
@@ -0,0 +1,79 @@
FILE: operatorsOverLiterals.kt
public final fun foo(x: R|kotlin/Int|): R|kotlin/Unit| {
}
public final fun foo(x: R|kotlin/Byte|): R|kotlin/Unit| {
}
public final fun test_0(): R|kotlin/Unit| {
R|/foo|(Int(1))
}
public final fun test_1(): R|kotlin/Unit| {
lval x1: R|kotlin/Int| = Int(1).R|kotlin/Int.plus|(Int(1))
lval x2: R|kotlin/Int| = Int(1).R|kotlin/Int.plus|(Int(1))
Int(1).R|kotlin/Int.plus|(Int(1))
Int(127).R|kotlin/Int.plus|(Int(1))
lval x3: R|kotlin/Int| = Int(2000000000).R|kotlin/Int.times|(Int(4))
}
public final fun test_2(n: R|kotlin/Int|): R|kotlin/Unit| {
lval x: R|kotlin/Int| = Int(1).R|kotlin/Int.plus|(R|<local>/n|)
lval y: R|kotlin/Int| = R|<local>/n|.R|kotlin/Int.plus|(Int(1))
}
public final fun R|kotlin/Int|.bar(): R|kotlin/Int| {
}
public final fun R|kotlin/Int|.baz(): R|kotlin/Int|
public final fun R|kotlin/Byte|.baz(): R|kotlin/Byte| {
}
public final fun test_3(): R|kotlin/Unit| {
lval x: R|kotlin/Int| = Int(1).R|/bar|()
lval y: R|kotlin/Int| = Int(1).R|/baz|()
}
public final fun takeByte(b: R|kotlin/Byte|): R|kotlin/Unit| {
}
public final fun test_4(): R|kotlin/Unit| {
R|/takeByte|(Byte(1).R|kotlin/Byte.plus|(Byte(1)))
<Inapplicable(INAPPLICABLE): [/takeByte]>#(Int(1).R|kotlin/Int.plus|(Int(127)))
R|/takeByte|(Byte(1).R|kotlin/Byte.minus|(Byte(1)))
<Inapplicable(INAPPLICABLE): [/takeByte]>#(Int(100).R|kotlin/Int.unaryMinus|().R|kotlin/Int.minus|(Int(100)))
R|/takeByte|(Byte(10).R|kotlin/Byte.times|(Byte(10)))
<Inapplicable(INAPPLICABLE): [/takeByte]>#(Int(100).R|kotlin/Int.times|(Int(100)))
<Unresolved name: taleByte>#(Int(10).R|kotlin/Int.div|(Int(10)))
R|/takeByte|(Byte(100).R|kotlin/Byte.rem|(Byte(10)))
R|/takeByte|(Int(1000).R|kotlin/Int.rem|(Byte(10)))
R|/takeByte|(Int(1000).R|<local>/and|(Byte(100)))
<Inapplicable(INAPPLICABLE): [/takeByte]>#(Int(128).R|kotlin/Int.and|(Int(511)))
R|/takeByte|(Byte(100).R|<local>/or|(Byte(100)))
<Inapplicable(INAPPLICABLE): [/takeByte]>#(Int(1000).R|kotlin/Int.or|(Int(0)))
R|/takeByte|(Int(511).R|kotlin/Int.xor|(Int(511)))
<Inapplicable(INAPPLICABLE): [/takeByte]>#(Int(512).R|kotlin/Int.xor|(Int(511)))
}
public final fun test_5(): R|kotlin/Unit| {
R|/takeByte|(Byte(1).R|kotlin/Byte.unaryMinus|())
R|/takeByte|(Byte(1).R|kotlin/Byte.unaryPlus|())
R|/takeByte|(Byte(1).R|<local>/inv|())
}
public final fun test_6(): R|kotlin/Unit| {
<Inapplicable(INAPPLICABLE): [/takeByte]>#(R|kotlin/run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
Int(127).R|kotlin/Int.plus|(Int(1))
}
))
<Inapplicable(INAPPLICABLE): [/takeByte]>#(Int(1).<Inapplicable(INAPPLICABLE): [kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus]>#(R|kotlin/run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
Int(1)
}
)))
R|/takeByte|(R|kotlin/run|<R|kotlin/Byte|>(<L> = run@fun <anonymous>(): R|kotlin/Byte| <kind=EXACTLY_ONCE> {
Int(1).R|kotlin/Int.plus|(Int(1))
}
))
Int(1).R|kotlin/Int.plus|(Int(1))
R|kotlin/run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
Int(1)
}
)
Int(1).R|<local>/plus|(R|kotlin/run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
Int(1)
}
))
}
public final fun test_7(d: R|kotlin/Double|): R|kotlin/Unit| {
lval x1: R|kotlin/Double| = Int(1).R|kotlin/Int.plus|(R|<local>/d|)
lval x2: R|kotlin/Double| = R|<local>/d|.R|kotlin/Double.plus|(Int(1))
}
@@ -28,7 +28,7 @@ digraph binaryOperations_kt {
subgraph cluster_4 { subgraph cluster_4 {
color=blue color=blue
12 [label="Enter block"]; 12 [label="Enter block"];
13 [label="Const: Int(1)"]; 13 [label="Const: IntegerLiteral(1)"];
14 [label="Exit block"]; 14 [label="Exit block"];
} }
15 [label="Exit when branch result"]; 15 [label="Exit when branch result"];
@@ -80,7 +80,7 @@ digraph binaryOperations_kt {
subgraph cluster_9 { subgraph cluster_9 {
color=blue color=blue
30 [label="Enter block"]; 30 [label="Enter block"];
31 [label="Const: Int(1)"]; 31 [label="Const: IntegerLiteral(1)"];
32 [label="Exit block"]; 32 [label="Exit block"];
} }
33 [label="Exit when branch result"]; 33 [label="Exit when branch result"];
@@ -140,7 +140,7 @@ digraph binaryOperations_kt {
subgraph cluster_15 { subgraph cluster_15 {
color=blue color=blue
53 [label="Enter block"]; 53 [label="Enter block"];
54 [label="Const: Int(1)"]; 54 [label="Const: IntegerLiteral(1)"];
55 [label="Exit block"]; 55 [label="Exit block"];
} }
56 [label="Exit when branch result"]; 56 [label="Exit when branch result"];
@@ -205,7 +205,7 @@ digraph binaryOperations_kt {
subgraph cluster_21 { subgraph cluster_21 {
color=blue color=blue
76 [label="Enter block"]; 76 [label="Enter block"];
77 [label="Const: Int(1)"]; 77 [label="Const: IntegerLiteral(1)"];
78 [label="Exit block"]; 78 [label="Exit block"];
} }
79 [label="Exit when branch result"]; 79 [label="Exit when branch result"];
@@ -2,7 +2,7 @@ FILE: binaryOperations.kt
public final fun test_1(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_1(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|): R|kotlin/Unit| {
when () { when () {
R|<local>/b1| || R|<local>/b2| -> { R|<local>/b1| || R|<local>/b2| -> {
Int(1) IntegerLiteral(1)
} }
} }
@@ -10,7 +10,7 @@ FILE: binaryOperations.kt
public final fun test_2(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_2(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|): R|kotlin/Unit| {
when () { when () {
R|<local>/b1| && R|<local>/b2| -> { R|<local>/b1| && R|<local>/b2| -> {
Int(1) IntegerLiteral(1)
} }
} }
@@ -18,7 +18,7 @@ FILE: binaryOperations.kt
public final fun test_3(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|, b3: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_3(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|, b3: R|kotlin/Boolean|): R|kotlin/Unit| {
when () { when () {
R|<local>/b1| && R|<local>/b2| || R|<local>/b3| -> { R|<local>/b1| && R|<local>/b2| || R|<local>/b3| -> {
Int(1) IntegerLiteral(1)
} }
} }
@@ -26,7 +26,7 @@ FILE: binaryOperations.kt
public final fun test_4(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|, b3: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_4(b1: R|kotlin/Boolean|, b2: R|kotlin/Boolean|, b3: R|kotlin/Boolean|): R|kotlin/Unit| {
when () { when () {
R|<local>/b1| || R|<local>/b2| && R|<local>/b3| -> { R|<local>/b1| || R|<local>/b2| && R|<local>/b3| -> {
Int(1) IntegerLiteral(1)
} }
} }
@@ -28,7 +28,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_4 { subgraph cluster_4 {
color=blue color=blue
12 [label="Enter block"]; 12 [label="Enter block"];
13 [label="Const: Int(1)"]; 13 [label="Const: IntegerLiteral(1)"];
14 [label="Exit block"]; 14 [label="Exit block"];
} }
15 [label="Exit when branch result"]; 15 [label="Exit when branch result"];
@@ -81,7 +81,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_9 { subgraph cluster_9 {
color=blue color=blue
31 [label="Enter block"]; 31 [label="Enter block"];
32 [label="Const: Int(1)"]; 32 [label="Const: IntegerLiteral(1)"];
33 [label="Exit block"]; 33 [label="Exit block"];
} }
34 [label="Exit when branch result"]; 34 [label="Exit when branch result"];
@@ -135,7 +135,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_14 { subgraph cluster_14 {
color=blue color=blue
49 [label="Enter block"]; 49 [label="Enter block"];
50 [label="Const: Int(1)"]; 50 [label="Const: IntegerLiteral(1)"];
51 [label="Exit block"]; 51 [label="Exit block"];
} }
52 [label="Exit when branch result"]; 52 [label="Exit when branch result"];
@@ -188,7 +188,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_19 { subgraph cluster_19 {
color=blue color=blue
68 [label="Enter block"]; 68 [label="Enter block"];
69 [label="Const: Int(1)"]; 69 [label="Const: IntegerLiteral(1)"];
70 [label="Exit block"]; 70 [label="Exit block"];
} }
71 [label="Exit when branch result"]; 71 [label="Exit when branch result"];
@@ -242,7 +242,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_24 { subgraph cluster_24 {
color=blue color=blue
86 [label="Enter block"]; 86 [label="Enter block"];
87 [label="Const: Int(1)"]; 87 [label="Const: IntegerLiteral(1)"];
88 [label="Exit block"]; 88 [label="Exit block"];
} }
89 [label="Exit when branch result"]; 89 [label="Exit when branch result"];
@@ -295,7 +295,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_29 { subgraph cluster_29 {
color=blue color=blue
105 [label="Enter block"]; 105 [label="Enter block"];
106 [label="Const: Int(1)"]; 106 [label="Const: IntegerLiteral(1)"];
107 [label="Exit block"]; 107 [label="Exit block"];
} }
108 [label="Exit when branch result"]; 108 [label="Exit when branch result"];
@@ -349,7 +349,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_34 { subgraph cluster_34 {
color=blue color=blue
123 [label="Enter block"]; 123 [label="Enter block"];
124 [label="Const: Int(1)"]; 124 [label="Const: IntegerLiteral(1)"];
125 [label="Exit block"]; 125 [label="Exit block"];
} }
126 [label="Exit when branch result"]; 126 [label="Exit when branch result"];
@@ -402,7 +402,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_39 { subgraph cluster_39 {
color=blue color=blue
142 [label="Enter block"]; 142 [label="Enter block"];
143 [label="Const: Int(1)"]; 143 [label="Const: IntegerLiteral(1)"];
144 [label="Exit block"]; 144 [label="Exit block"];
} }
145 [label="Exit when branch result"]; 145 [label="Exit when branch result"];
@@ -2,7 +2,7 @@ FILE: booleanOperatorsWithConsts.kt
public final fun test_1(b: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_1(b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () { when () {
R|<local>/b| || Boolean(false) -> { R|<local>/b| || Boolean(false) -> {
Int(1) IntegerLiteral(1)
} }
} }
@@ -10,7 +10,7 @@ FILE: booleanOperatorsWithConsts.kt
public final fun test_2(b: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_2(b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () { when () {
Boolean(false) || R|<local>/b| -> { Boolean(false) || R|<local>/b| -> {
Int(1) IntegerLiteral(1)
} }
} }
@@ -18,7 +18,7 @@ FILE: booleanOperatorsWithConsts.kt
public final fun test_3(b: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_3(b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () { when () {
R|<local>/b| || Boolean(true) -> { R|<local>/b| || Boolean(true) -> {
Int(1) IntegerLiteral(1)
} }
} }
@@ -26,7 +26,7 @@ FILE: booleanOperatorsWithConsts.kt
public final fun test_4(b: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_4(b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () { when () {
Boolean(true) || R|<local>/b| -> { Boolean(true) || R|<local>/b| -> {
Int(1) IntegerLiteral(1)
} }
} }
@@ -34,7 +34,7 @@ FILE: booleanOperatorsWithConsts.kt
public final fun test_5(b: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_5(b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () { when () {
R|<local>/b| && Boolean(false) -> { R|<local>/b| && Boolean(false) -> {
Int(1) IntegerLiteral(1)
} }
} }
@@ -42,7 +42,7 @@ FILE: booleanOperatorsWithConsts.kt
public final fun test_6(b: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_6(b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () { when () {
Boolean(false) && R|<local>/b| -> { Boolean(false) && R|<local>/b| -> {
Int(1) IntegerLiteral(1)
} }
} }
@@ -50,7 +50,7 @@ FILE: booleanOperatorsWithConsts.kt
public final fun test_7(b: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_7(b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () { when () {
R|<local>/b| && Boolean(true) -> { R|<local>/b| && Boolean(true) -> {
Int(1) IntegerLiteral(1)
} }
} }
@@ -58,7 +58,7 @@ FILE: booleanOperatorsWithConsts.kt
public final fun test_8(b: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_8(b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () { when () {
Boolean(true) && R|<local>/b| -> { Boolean(true) && R|<local>/b| -> {
Int(1) IntegerLiteral(1)
} }
} }
+172 -176
View File
@@ -28,7 +28,7 @@ digraph complex_kt {
14 [label="Access variable R|<local>/url|"]; 14 [label="Access variable R|<local>/url|"];
15 [label="Access variable R|<local>/url|"]; 15 [label="Access variable R|<local>/url|"];
16 [label="Function call: <Unresolved name: HttpRequests>#.<Unresolved name: request>#(R|<local>/url|)"]; 16 [label="Function call: <Unresolved name: HttpRequests>#.<Unresolved name: request>#(R|<local>/url|)"];
17 [label="Function call: <Unresolved name: HttpRequests>#.<Unresolved name: request>#(R|<local>/url|).<Unresolved name: connect>#(<L> = connect@fun <anonymous>(): <ERROR TYPE REF: Unresolved name: fromJson> { 17 [label="Function call: <Unresolved name: HttpRequests>#.<Unresolved name: request>#(R|<local>/url|).<Unresolved name: connect>#(<L> = connect@fun <anonymous>(): R|class error: Unresolved name: fromJson| {
<Unresolved name: GsonBuilder>#().<Unresolved name: create>#().<Unresolved name: fromJson>#(<Unresolved name: it>#.<Unresolved name: inputStream>#.<Ambiguity: reader, [kotlin/io/reader, kotlin/io/reader, kotlin/io/reader]>#(), <getClass>(Q|kotlin/Array|).R|kotlin/jvm/java|) <Unresolved name: GsonBuilder>#().<Unresolved name: create>#().<Unresolved name: fromJson>#(<Unresolved name: it>#.<Unresolved name: inputStream>#.<Ambiguity: reader, [kotlin/io/reader, kotlin/io/reader, kotlin/io/reader]>#(), <getClass>(Q|kotlin/Array|).R|kotlin/jvm/java|)
} }
)"]; )"];
@@ -44,44 +44,42 @@ digraph complex_kt {
21 [label="Enter block"]; 21 [label="Enter block"];
22 [label="Const: String(Can't parse json response)"]; 22 [label="Const: String(Can't parse json response)"];
23 [label="Access variable R|<local>/syntaxException|"]; 23 [label="Access variable R|<local>/syntaxException|"];
24 [label="Const: String(Can't parse json response)"]; 24 [label="Access variable R|<local>/syntaxException|"];
25 [label="Access variable R|<local>/syntaxException|"]; 25 [label="Access variable R|<local>/syntaxException|"];
26 [label="Const: String(Can't parse json response)"]; 26 [label="Function call: <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|)"];
27 [label="Access variable R|<local>/syntaxException|"]; 27 [label="Throw: throw <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|)"];
28 [label="Function call: <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|)"]; 28 [label="Stub" style="filled" fillcolor=gray];
29 [label="Throw: throw <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|)"]; 29 [label="Exit block" style="filled" fillcolor=gray];
30 [label="Stub" style="filled" fillcolor=gray];
31 [label="Exit block" style="filled" fillcolor=gray];
} }
32 [label="Catch exit" style="filled" fillcolor=gray]; 30 [label="Catch exit" style="filled" fillcolor=gray];
} }
subgraph cluster_6 { subgraph cluster_6 {
color=blue color=blue
33 [label="Catch enter"]; 31 [label="Catch enter"];
subgraph cluster_7 { subgraph cluster_7 {
color=blue color=blue
34 [label="Enter block"]; 32 [label="Enter block"];
33 [label="Access variable R|<local>/ioException|"];
34 [label="Access variable R|<local>/ioException|"];
35 [label="Access variable R|<local>/ioException|"]; 35 [label="Access variable R|<local>/ioException|"];
36 [label="Access variable R|<local>/ioException|"]; 36 [label="Function call: <Unresolved name: IOException>#(R|<local>/ioException|)"];
37 [label="Access variable R|<local>/ioException|"]; 37 [label="Throw: throw <Unresolved name: IOException>#(R|<local>/ioException|)"];
38 [label="Function call: <Unresolved name: IOException>#(R|<local>/ioException|)"]; 38 [label="Stub" style="filled" fillcolor=gray];
39 [label="Throw: throw <Unresolved name: IOException>#(R|<local>/ioException|)"]; 39 [label="Exit block" style="filled" fillcolor=gray];
40 [label="Stub" style="filled" fillcolor=gray];
41 [label="Exit block" style="filled" fillcolor=gray];
} }
42 [label="Catch exit" style="filled" fillcolor=gray]; 40 [label="Catch exit" style="filled" fillcolor=gray];
} }
43 [label="Try expression exit"]; 41 [label="Try expression exit"];
} }
44 [label="Variable declaration: lval pluginDTOs: R|kotlin/Array<class error: Symbol not found, for `PluginDTO`>|"]; 42 [label="Variable declaration: lval pluginDTOs: R|kotlin/Array<class error: Symbol not found, for `PluginDTO`>|"];
45 [label="Exit function fetchPluginReleaseDate" style="filled" fillcolor=red]; 43 [label="Exit function fetchPluginReleaseDate" style="filled" fillcolor=red];
} }
subgraph cluster_8 { subgraph cluster_8 {
color=blue color=blue
46 [label="Enter annotation"]; 44 [label="Enter annotation"];
47 [label="Access variable <Unresolved name: IOException>#"]; 45 [label="Access variable <Unresolved name: IOException>#"];
48 [label="Access variable <Unresolved name: ResponseParseException>#"]; 46 [label="Access variable <Unresolved name: ResponseParseException>#"];
49 [label="Exit annotation"]; 47 [label="Exit annotation"];
} }
0 -> {1}; 0 -> {1};
@@ -94,7 +92,7 @@ digraph complex_kt {
7 -> {8}; 7 -> {8};
8 -> {9}; 8 -> {9};
9 -> {10}; 9 -> {10};
10 -> {45 33 20 11}; 10 -> {43 31 20 11};
11 -> {12}; 11 -> {12};
12 -> {13}; 12 -> {13};
13 -> {14}; 13 -> {14};
@@ -103,54 +101,54 @@ digraph complex_kt {
16 -> {17}; 16 -> {17};
17 -> {18}; 17 -> {18};
18 -> {19}; 18 -> {19};
19 -> {43}; 19 -> {41};
20 -> {45 21}; 20 -> {43 21};
21 -> {22}; 21 -> {22};
22 -> {23}; 22 -> {23};
23 -> {24}; 23 -> {24};
24 -> {25}; 24 -> {25};
25 -> {26}; 25 -> {26};
26 -> {27}; 26 -> {27};
27 -> {28}; 27 -> {43};
28 -> {29}; 27 -> {28} [style=dotted];
29 -> {45}; 28 -> {29} [style=dotted];
29 -> {30} [style=dotted]; 29 -> {30} [style=dotted];
30 -> {31} [style=dotted]; 30 -> {41} [style=dotted];
31 -> {32} [style=dotted]; 31 -> {43 32};
32 -> {43} [style=dotted]; 32 -> {33};
33 -> {45 34}; 33 -> {34};
34 -> {35}; 34 -> {35};
35 -> {36}; 35 -> {36};
36 -> {37}; 36 -> {37};
37 -> {38}; 37 -> {43};
38 -> {39}; 37 -> {38} [style=dotted];
39 -> {45}; 38 -> {39} [style=dotted];
39 -> {40} [style=dotted]; 39 -> {40} [style=dotted];
40 -> {41} [style=dotted]; 40 -> {41} [style=dotted];
41 -> {42} [style=dotted]; 41 -> {42};
42 -> {43} [style=dotted]; 42 -> {43};
43 -> {44}; 43 -> {44};
44 -> {45}; 44 -> {45};
45 -> {46}; 45 -> {46};
46 -> {47}; 46 -> {47};
47 -> {48};
48 -> {49};
subgraph cluster_9 { subgraph cluster_9 {
color=red color=red
50 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; 48 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
51 [label="Function call: <Unresolved name: GsonBuilder>#()"]; 49 [label="Function call: <Unresolved name: GsonBuilder>#()"];
52 [label="Function call: <Unresolved name: GsonBuilder>#().<Unresolved name: create>#()"]; 50 [label="Function call: <Unresolved name: GsonBuilder>#().<Unresolved name: create>#()"];
53 [label="Access variable <Unresolved name: it>#"]; 51 [label="Access variable <Unresolved name: it>#"];
54 [label="Access variable <Unresolved name: inputStream>#"]; 52 [label="Access variable <Unresolved name: inputStream>#"];
55 [label="Function call: <Unresolved name: it>#.<Unresolved name: inputStream>#.<Ambiguity: reader, [kotlin/io/reader, kotlin/io/reader, kotlin/io/reader]>#()"]; 53 [label="Function call: <Unresolved name: it>#.<Unresolved name: inputStream>#.<Ambiguity: reader, [kotlin/io/reader, kotlin/io/reader, kotlin/io/reader]>#()"];
54 [label="Access variable R|kotlin/jvm/java|"];
55 [label="Access variable R|kotlin/jvm/java|"];
56 [label="Access variable R|kotlin/jvm/java|"]; 56 [label="Access variable R|kotlin/jvm/java|"];
57 [label="Access variable R|kotlin/jvm/java|"]; 57 [label="Function call: <Unresolved name: GsonBuilder>#().<Unresolved name: create>#().<Unresolved name: fromJson>#(<Unresolved name: it>#.<Unresolved name: inputStream>#.<Ambiguity: reader, [kotlin/io/reader, kotlin/io/reader, kotlin/io/reader]>#(), <getClass>(Q|kotlin/Array|).R|kotlin/jvm/java|)"];
58 [label="Access variable R|kotlin/jvm/java|"]; 58 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
59 [label="Function call: <Unresolved name: GsonBuilder>#().<Unresolved name: create>#().<Unresolved name: fromJson>#(<Unresolved name: it>#.<Unresolved name: inputStream>#.<Ambiguity: reader, [kotlin/io/reader, kotlin/io/reader, kotlin/io/reader]>#(), <getClass>(Q|kotlin/Array|).R|kotlin/jvm/java|)"];
60 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
} }
48 -> {49};
49 -> {50};
50 -> {51}; 50 -> {51};
51 -> {52}; 51 -> {52};
52 -> {53}; 52 -> {53};
@@ -159,98 +157,96 @@ digraph complex_kt {
55 -> {56}; 55 -> {56};
56 -> {57}; 56 -> {57};
57 -> {58}; 57 -> {58};
58 -> {59};
59 -> {60};
subgraph cluster_10 { subgraph cluster_10 {
color=red color=red
61 [label="Enter function close" style="filled" fillcolor=red]; 59 [label="Enter function close" style="filled" fillcolor=red];
62 [label="Exit function close" style="filled" fillcolor=red]; 60 [label="Exit function close" style="filled" fillcolor=red];
} }
61 -> {62}; 59 -> {60};
subgraph cluster_11 { subgraph cluster_11 {
color=red color=red
63 [label="Enter function closeFinally" style="filled" fillcolor=red]; 61 [label="Enter function closeFinally" style="filled" fillcolor=red];
subgraph cluster_12 { subgraph cluster_12 {
color=blue color=blue
64 [label="Enter when"]; 62 [label="Enter when"];
subgraph cluster_13 { subgraph cluster_13 {
color=blue color=blue
65 [label="Enter when branch condition "]; 63 [label="Enter when branch condition "];
66 [label="Access variable this@R|/closeFinally|"]; 64 [label="Access variable this@R|/closeFinally|"];
67 [label="Const: Null(null)"]; 65 [label="Const: Null(null)"];
68 [label="Operator =="]; 66 [label="Operator =="];
69 [label="Exit when branch condition"]; 67 [label="Exit when branch condition"];
} }
subgraph cluster_14 { subgraph cluster_14 {
color=blue color=blue
70 [label="Enter when branch condition "]; 68 [label="Enter when branch condition "];
71 [label="Access variable R|<local>/cause|"]; 69 [label="Access variable R|<local>/cause|"];
72 [label="Const: Null(null)"]; 70 [label="Const: Null(null)"];
73 [label="Operator =="]; 71 [label="Operator =="];
74 [label="Exit when branch condition"]; 72 [label="Exit when branch condition"];
} }
subgraph cluster_15 { subgraph cluster_15 {
color=blue color=blue
75 [label="Enter when branch condition else"]; 73 [label="Enter when branch condition else"];
76 [label="Exit when branch condition"]; 74 [label="Exit when branch condition"];
} }
77 [label="Enter when branch result"]; 75 [label="Enter when branch result"];
subgraph cluster_16 { subgraph cluster_16 {
color=blue color=blue
78 [label="Enter block"]; 76 [label="Enter block"];
subgraph cluster_17 { subgraph cluster_17 {
color=blue color=blue
79 [label="Try expression enter"]; 77 [label="Try expression enter"];
subgraph cluster_18 { subgraph cluster_18 {
color=blue color=blue
80 [label="Try main block enter"]; 78 [label="Try main block enter"];
subgraph cluster_19 { subgraph cluster_19 {
color=blue color=blue
81 [label="Enter block"]; 79 [label="Enter block"];
82 [label="Function call: this@R|/AutoCloseable|.R|/AutoCloseable.close|()"]; 80 [label="Function call: this@R|/AutoCloseable|.R|/AutoCloseable.close|()"];
83 [label="Exit block"]; 81 [label="Exit block"];
} }
84 [label="Try main block exit"]; 82 [label="Try main block exit"];
} }
subgraph cluster_20 { subgraph cluster_20 {
color=blue color=blue
85 [label="Catch enter"]; 83 [label="Catch enter"];
subgraph cluster_21 { subgraph cluster_21 {
color=blue color=blue
86 [label="Enter block"]; 84 [label="Enter block"];
87 [label="Access variable R|<local>/cause|"]; 85 [label="Access variable R|<local>/cause|"];
88 [label="Access variable R|<local>/closeException|"]; 86 [label="Access variable R|<local>/closeException|"];
89 [label="Function call: R|<local>/cause|.R|kotlin/addSuppressed|(R|<local>/closeException|)"]; 87 [label="Function call: R|<local>/cause|.R|kotlin/addSuppressed|(R|<local>/closeException|)"];
90 [label="Exit block"]; 88 [label="Exit block"];
} }
91 [label="Catch exit"]; 89 [label="Catch exit"];
} }
92 [label="Try expression exit"]; 90 [label="Try expression exit"];
} }
93 [label="Exit block"]; 91 [label="Exit block"];
} }
94 [label="Exit when branch result"]; 92 [label="Exit when branch result"];
95 [label="Enter when branch result"]; 93 [label="Enter when branch result"];
subgraph cluster_22 { subgraph cluster_22 {
color=blue color=blue
96 [label="Enter block"]; 94 [label="Enter block"];
97 [label="Function call: this@R|/AutoCloseable|.R|/AutoCloseable.close|()"]; 95 [label="Function call: this@R|/AutoCloseable|.R|/AutoCloseable.close|()"];
98 [label="Exit block"]; 96 [label="Exit block"];
} }
99 [label="Exit when branch result"]; 97 [label="Exit when branch result"];
100 [label="Enter when branch result"]; 98 [label="Enter when branch result"];
subgraph cluster_23 { subgraph cluster_23 {
color=blue color=blue
101 [label="Enter block"]; 99 [label="Enter block"];
102 [label="Exit block"]; 100 [label="Exit block"];
} }
103 [label="Exit when branch result"]; 101 [label="Exit when branch result"];
104 [label="Exit when"]; 102 [label="Exit when"];
} }
105 [label="Jump: ^closeFinally when () { 103 [label="Jump: ^closeFinally when () {
==(this@R|/closeFinally|, Null(null)) -> { ==(this@R|/closeFinally|, Null(null)) -> {
} }
==(R|<local>/cause|, Null(null)) -> { ==(R|<local>/cause|, Null(null)) -> {
@@ -267,118 +263,120 @@ digraph complex_kt {
} }
} }
"]; "];
106 [label="Stub" style="filled" fillcolor=gray]; 104 [label="Stub" style="filled" fillcolor=gray];
107 [label="Exit function closeFinally" style="filled" fillcolor=red]; 105 [label="Exit function closeFinally" style="filled" fillcolor=red];
} }
61 -> {62};
62 -> {63};
63 -> {64}; 63 -> {64};
64 -> {65}; 64 -> {65};
65 -> {66}; 65 -> {66};
66 -> {67}; 66 -> {67};
67 -> {68}; 67 -> {98 68};
68 -> {69}; 68 -> {69};
69 -> {100 70}; 69 -> {70};
70 -> {71}; 70 -> {71};
71 -> {72}; 71 -> {72};
72 -> {73}; 72 -> {93 73};
73 -> {74}; 73 -> {74};
74 -> {95 75}; 74 -> {75};
75 -> {76}; 75 -> {76};
76 -> {77}; 76 -> {77};
77 -> {78}; 77 -> {78};
78 -> {79}; 78 -> {105 83 79};
79 -> {80}; 79 -> {80};
80 -> {107 85 81}; 80 -> {81};
81 -> {82}; 81 -> {82};
82 -> {83}; 82 -> {90};
83 -> {84}; 83 -> {105 84};
84 -> {92}; 84 -> {85};
85 -> {107 86}; 85 -> {86};
86 -> {87}; 86 -> {87};
87 -> {88}; 87 -> {88};
88 -> {89}; 88 -> {89};
89 -> {90}; 89 -> {90};
90 -> {91}; 90 -> {91};
91 -> {92}; 91 -> {92};
92 -> {93}; 92 -> {102};
93 -> {94}; 93 -> {94};
94 -> {104}; 94 -> {95};
95 -> {96}; 95 -> {96};
96 -> {97}; 96 -> {97};
97 -> {98}; 97 -> {102};
98 -> {99}; 98 -> {99};
99 -> {104}; 99 -> {100};
100 -> {101}; 100 -> {101};
101 -> {102}; 101 -> {102};
102 -> {103}; 102 -> {103};
103 -> {104}; 103 -> {105};
104 -> {105}; 103 -> {104} [style=dotted];
105 -> {107}; 104 -> {105} [style=dotted];
105 -> {106} [style=dotted];
106 -> {107} [style=dotted];
subgraph cluster_24 { subgraph cluster_24 {
color=red color=red
108 [label="Enter function firstIsInstanceOrNull" style="filled" fillcolor=red]; 106 [label="Enter function firstIsInstanceOrNull" style="filled" fillcolor=red];
109 [label="Access variable this@R|/firstIsInstanceOrNull|"]; 107 [label="Access variable this@R|/firstIsInstanceOrNull|"];
110 [label="Variable declaration: lval <range>: R|kotlin/sequences/Sequence<*>|"]; 108 [label="Variable declaration: lval <range>: R|kotlin/sequences/Sequence<*>|"];
111 [label="Access variable R|<local>/<range>|"]; 109 [label="Access variable R|<local>/<range>|"];
112 [label="Function call: R|<local>/<range>|.R|FakeOverride<kotlin/sequences/Sequence.iterator: R|kotlin/collections/Iterator<kotlin/Any?>|>|()"]; 110 [label="Function call: R|<local>/<range>|.R|FakeOverride<kotlin/sequences/Sequence.iterator: R|kotlin/collections/Iterator<kotlin/Any?>|>|()"];
113 [label="Variable declaration: lval <iterator>: R|kotlin/collections/Iterator<kotlin/Any?>|"]; 111 [label="Variable declaration: lval <iterator>: R|kotlin/collections/Iterator<kotlin/Any?>|"];
subgraph cluster_25 { subgraph cluster_25 {
color=blue color=blue
114 [label="Enter while loop"]; 112 [label="Enter while loop"];
subgraph cluster_26 { subgraph cluster_26 {
color=blue color=blue
115 [label="Enter loop condition"]; 113 [label="Enter loop condition"];
116 [label="Access variable R|<local>/<iterator>|"]; 114 [label="Access variable R|<local>/<iterator>|"];
117 [label="Function call: R|<local>/<iterator>|.R|kotlin/collections/Iterator.hasNext|()"]; 115 [label="Function call: R|<local>/<iterator>|.R|kotlin/collections/Iterator.hasNext|()"];
118 [label="Exit loop condition"]; 116 [label="Exit loop condition"];
} }
subgraph cluster_27 { subgraph cluster_27 {
color=blue color=blue
119 [label="Enter loop block"]; 117 [label="Enter loop block"];
subgraph cluster_28 { subgraph cluster_28 {
color=blue color=blue
120 [label="Enter block"]; 118 [label="Enter block"];
121 [label="Access variable R|<local>/<iterator>|"]; 119 [label="Access variable R|<local>/<iterator>|"];
122 [label="Function call: R|<local>/<iterator>|.R|FakeOverride<kotlin/collections/Iterator.next: R|kotlin/Any?|>|()"]; 120 [label="Function call: R|<local>/<iterator>|.R|FakeOverride<kotlin/collections/Iterator.next: R|kotlin/Any?|>|()"];
123 [label="Variable declaration: lval element: R|kotlin/Any?|"]; 121 [label="Variable declaration: lval element: R|kotlin/Any?|"];
subgraph cluster_29 { subgraph cluster_29 {
color=blue color=blue
124 [label="Enter when"]; 122 [label="Enter when"];
subgraph cluster_30 { subgraph cluster_30 {
color=blue color=blue
125 [label="Enter when branch condition "]; 123 [label="Enter when branch condition "];
126 [label="Access variable R|<local>/element|"]; 124 [label="Access variable R|<local>/element|"];
127 [label="Type operator: element is T"]; 125 [label="Type operator: element is T"];
128 [label="Exit when branch condition"]; 126 [label="Exit when branch condition"];
} }
129 [label="Synthetic else branch"]; 127 [label="Synthetic else branch"];
130 [label="Enter when branch result"]; 128 [label="Enter when branch result"];
subgraph cluster_31 { subgraph cluster_31 {
color=blue color=blue
131 [label="Enter block"]; 129 [label="Enter block"];
132 [label="Access variable R|<local>/element|"]; 130 [label="Access variable R|<local>/element|"];
133 [label="Jump: ^firstIsInstanceOrNull R|<local>/element|"]; 131 [label="Jump: ^firstIsInstanceOrNull R|<local>/element|"];
134 [label="Stub" style="filled" fillcolor=gray]; 132 [label="Stub" style="filled" fillcolor=gray];
135 [label="Exit block" style="filled" fillcolor=gray]; 133 [label="Exit block" style="filled" fillcolor=gray];
} }
136 [label="Exit when branch result" style="filled" fillcolor=gray]; 134 [label="Exit when branch result" style="filled" fillcolor=gray];
137 [label="Exit when"]; 135 [label="Exit when"];
} }
138 [label="Exit block"]; 136 [label="Exit block"];
} }
139 [label="Exit loop block"]; 137 [label="Exit loop block"];
} }
140 [label="Exit whileloop"]; 138 [label="Exit whileloop"];
} }
141 [label="Const: Null(null)"]; 139 [label="Const: Null(null)"];
142 [label="Jump: ^firstIsInstanceOrNull Null(null)"]; 140 [label="Jump: ^firstIsInstanceOrNull Null(null)"];
143 [label="Stub" style="filled" fillcolor=gray]; 141 [label="Stub" style="filled" fillcolor=gray];
144 [label="Exit function firstIsInstanceOrNull" style="filled" fillcolor=red]; 142 [label="Exit function firstIsInstanceOrNull" style="filled" fillcolor=red];
} }
106 -> {107};
107 -> {108};
108 -> {109}; 108 -> {109};
109 -> {110}; 109 -> {110};
110 -> {111}; 110 -> {111};
@@ -387,9 +385,9 @@ digraph complex_kt {
113 -> {114}; 113 -> {114};
114 -> {115}; 114 -> {115};
115 -> {116}; 115 -> {116};
116 -> {117}; 116 -> {138 117};
117 -> {118}; 117 -> {118};
118 -> {140 119}; 118 -> {119};
119 -> {120}; 119 -> {120};
120 -> {121}; 120 -> {121};
121 -> {122}; 121 -> {122};
@@ -397,25 +395,23 @@ digraph complex_kt {
123 -> {124}; 123 -> {124};
124 -> {125}; 124 -> {125};
125 -> {126}; 125 -> {126};
126 -> {127}; 126 -> {128 127};
127 -> {128}; 127 -> {135};
128 -> {130 129}; 128 -> {129};
129 -> {137}; 129 -> {130};
130 -> {131}; 130 -> {131};
131 -> {132}; 131 -> {142};
132 -> {133}; 131 -> {132} [style=dotted];
133 -> {144}; 132 -> {133} [style=dotted];
133 -> {134} [style=dotted]; 133 -> {134} [style=dotted];
134 -> {135} [style=dotted]; 134 -> {135} [style=dotted];
135 -> {136} [style=dotted]; 135 -> {136};
136 -> {137} [style=dotted]; 136 -> {137};
137 -> {138}; 137 -> {113};
138 -> {139}; 138 -> {139};
139 -> {115}; 139 -> {140};
140 -> {141}; 140 -> {142};
141 -> {142}; 140 -> {141} [style=dotted];
142 -> {144}; 141 -> {142} [style=dotted];
142 -> {143} [style=dotted];
143 -> {144} [style=dotted];
} }
@@ -190,7 +190,7 @@ digraph propertiesAndInitBlocks_kt {
subgraph cluster_18 { subgraph cluster_18 {
color=blue color=blue
53 [label="Enter block"]; 53 [label="Enter block"];
54 [label="Const: Int(0)"]; 54 [label="Const: IntegerLiteral(0)"];
55 [label="Exit block"]; 55 [label="Exit block"];
} }
56 [label="Exit finally"]; 56 [label="Exit finally"];
@@ -52,7 +52,7 @@ FILE: propertiesAndInitBlocks.kt
Int(2) Int(2)
} }
finally { finally {
Int(0) IntegerLiteral(0)
} }
public get(): R|kotlin/Int| public get(): R|kotlin/Int|
@@ -50,7 +50,7 @@ digraph returnValuesFromLambda_kt {
19 [label="Function call: R|/C.C|()"]; 19 [label="Function call: R|/C.C|()"];
20 [label="Exit function anonymousFunction"]; 20 [label="Exit function anonymousFunction"];
} }
21 [label="Function call: R|kotlin/run|<R|A|>(<L> = run@fun <anonymous>(): R|C| <kind=EXACTLY_ONCE> { 21 [label="Function call: R|kotlin/run|<R|A|>(<L> = run@fun <anonymous>(): R|A| <kind=EXACTLY_ONCE> {
when () { when () {
R|<local>/b| -> { R|<local>/b| -> {
^@run R|/B.B|() ^@run R|/B.B|()
@@ -124,7 +124,7 @@ digraph returnValuesFromLambda_kt {
36 [label="Stub" style="filled" fillcolor=gray]; 36 [label="Stub" style="filled" fillcolor=gray];
37 [label="Exit function anonymousFunction" style="filled" fillcolor=gray]; 37 [label="Exit function anonymousFunction" style="filled" fillcolor=gray];
} }
38 [label="Function call: R|kotlin/run|<R|kotlin/Nothing|>(<L> = run@fun <anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> { 38 [label="Function call: R|kotlin/run|<R|kotlin/Nothing|>(<L> = run@fun <anonymous>(): R|kotlin/Nothing| <kind=EXACTLY_ONCE> {
^test_3 Unit ^test_3 Unit
} }
)" style="filled" fillcolor=gray]; )" style="filled" fillcolor=gray];
@@ -14,7 +14,7 @@ FILE: returnValuesFromLambda.kt
} }
public final fun test_1(b: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_1(b: R|kotlin/Boolean|): R|kotlin/Unit| {
lval x: R|A| = R|kotlin/run|<R|A|>(<L> = run@fun <anonymous>(): R|C| <kind=EXACTLY_ONCE> { lval x: R|A| = R|kotlin/run|<R|A|>(<L> = run@fun <anonymous>(): R|A| <kind=EXACTLY_ONCE> {
when () { when () {
R|<local>/b| -> { R|<local>/b| -> {
^@run R|/B.B|() ^@run R|/B.B|()
@@ -32,7 +32,7 @@ FILE: returnValuesFromLambda.kt
) )
} }
public final fun test_3(): R|kotlin/Unit| { public final fun test_3(): R|kotlin/Unit| {
lval x: R|kotlin/Nothing| = R|kotlin/run|<R|kotlin/Nothing|>(<L> = run@fun <anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> { lval x: R|kotlin/Nothing| = R|kotlin/run|<R|kotlin/Nothing|>(<L> = run@fun <anonymous>(): R|kotlin/Nothing| <kind=EXACTLY_ONCE> {
^test_3 Unit ^test_3 Unit
} }
) )
@@ -14,3 +14,14 @@ class B3_1 : <!AMBIGUITY!>A3<!>("")
class B3_2 : A3("", "asas") class B3_2 : A3("", "asas")
class B3_3 : A3("", true) class B3_3 : A3("", true)
class B3_4 : <!INAPPLICABLE_CANDIDATE!>A3<!>("", Unit) class B3_4 : <!INAPPLICABLE_CANDIDATE!>A3<!>("", Unit)
open class A4(val x: Byte)
class B4 : A4( 1 + 1)
open class A5 {
constructor(x: Byte)
constructor(x: Short)
}
class B5_1 : A5(1 + 1)
class B5_2 : A5(100 * 2)
@@ -74,3 +74,40 @@ FILE: delegatingConstructorCall.kt
} }
} }
public open class A4 : R|kotlin/Any| {
public constructor(x: R|kotlin/Byte|): R|A4| {
super<R|kotlin/Any|>()
}
public final val x: R|kotlin/Byte| = R|<local>/x|
public get(): R|kotlin/Byte|
}
public final class B4 : R|A4| {
public constructor(): R|B4| {
super<R|A4|>(Byte(1).R|kotlin/Byte.plus|(Byte(1)))
}
}
public open class A5 : R|kotlin/Any| {
public constructor(x: R|kotlin/Byte|): R|A5| {
super<R|kotlin/Any|>()
}
public constructor(x: R|kotlin/Short|): R|A5| {
super<R|kotlin/Any|>()
}
}
public final class B5_1 : R|A5| {
public constructor(): R|B5_1| {
super<R|A5|>(Short(1).R|kotlin/Short.plus|(Short(1)))
}
}
public final class B5_2 : R|A5| {
public constructor(): R|B5_2| {
super<R|A5|>(Short(100).R|kotlin/Short.times|(Short(2)))
}
}
@@ -2,7 +2,7 @@ FILE: exhaustiveness_boolean.kt
public final fun test_1(b: R|kotlin/Boolean|): R|kotlin/Unit| { public final fun test_1(b: R|kotlin/Boolean|): R|kotlin/Unit| {
lval x: R|kotlin/Unit| = when (R|<local>/b|) { lval x: R|kotlin/Unit| = when (R|<local>/b|) {
==($subj$, Boolean(true)) -> { ==($subj$, Boolean(true)) -> {
Int(1) IntegerLiteral(1)
} }
} }
+1 -1
View File
@@ -33,7 +33,7 @@ class TestProperty {
return intConst + 1 return intConst + 1
} }
} }
1 return 1
} }
val z = run { val z = run {
+1 -1
View File
@@ -61,7 +61,7 @@ FILE: localObject.kt
} }
Int(1) ^ Int(1)
} }
public final val z: R|kotlin/Int| = R|/run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| { public final val z: R|kotlin/Int| = R|/run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| {
@@ -69,9 +69,9 @@ FILE: main.kt
public get(): R|kotlin/String| public get(): R|kotlin/String|
} }
@R|annotations/WithString|(String(xyz)) public final class Second : @R|annotations/WithInt|(Int(0)) R|test/First| { @R|annotations/WithString|(String(xyz)) public final class Second : @R|annotations/WithInt|(IntegerLiteral(0)) R|test/First| {
public constructor(y: R|kotlin/Char|): R|test/Second| { public constructor(y: R|kotlin/Char|): R|test/Second| {
super<@R|annotations/WithInt|(Int(0)) R|test/First|>() super<@R|annotations/WithInt|(IntegerLiteral(0)) R|test/First|>()
} }
public final val y: R|kotlin/Char| = R|<local>/y| public final val y: R|kotlin/Char| = R|<local>/y|
@@ -199,7 +199,7 @@ digraph safeCalls_kt {
73 [label="Stub" style="filled" fillcolor=gray]; 73 [label="Stub" style="filled" fillcolor=gray];
74 [label="Exit function anonymousFunction" style="filled" fillcolor=gray]; 74 [label="Exit function anonymousFunction" style="filled" fillcolor=gray];
} }
75 [label="Function call: R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Nothing|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Unit| <kind=EXACTLY_ONCE> { 75 [label="Function call: R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Nothing|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Nothing| <kind=EXACTLY_ONCE> {
^test_5 Unit ^test_5 Unit
} }
)" style="filled" fillcolor=gray]; )" style="filled" fillcolor=gray];
@@ -207,7 +207,7 @@ digraph safeCalls_kt {
77 [label="Enter safe call" style="filled" fillcolor=gray]; 77 [label="Enter safe call" style="filled" fillcolor=gray];
78 [label="Access variable R|<local>/x|" style="filled" fillcolor=gray]; 78 [label="Access variable R|<local>/x|" style="filled" fillcolor=gray];
79 [label="Function call: R|<local>/x|.R|/A.bool|()" style="filled" fillcolor=gray]; 79 [label="Function call: R|<local>/x|.R|/A.bool|()" style="filled" fillcolor=gray];
80 [label="Function call: R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Nothing|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Unit| <kind=EXACTLY_ONCE> { 80 [label="Function call: R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Nothing|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Nothing| <kind=EXACTLY_ONCE> {
^test_5 Unit ^test_5 Unit
} }
)?.R|/boo|(R|<local>/x|.R|/A.bool|())" style="filled" fillcolor=gray]; )?.R|/boo|(R|<local>/x|.R|/A.bool|())" style="filled" fillcolor=gray];
@@ -32,7 +32,7 @@ FILE: safeCalls.kt
} }
public final fun R|kotlin/Any?|.boo(b: R|kotlin/Boolean|): R|kotlin/Unit| public final fun R|kotlin/Any?|.boo(b: R|kotlin/Boolean|): R|kotlin/Unit|
public final fun test_5(x: R|A?|): R|kotlin/Unit| { public final fun test_5(x: R|A?|): R|kotlin/Unit| {
R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Nothing|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Unit| <kind=EXACTLY_ONCE> { R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Nothing|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Nothing| <kind=EXACTLY_ONCE> {
^test_5 Unit ^test_5 Unit
} }
)?.R|/boo|(R|<local>/x|.R|/A.bool|()) )?.R|/boo|(R|<local>/x|.R|/A.bool|())
@@ -28,16 +28,16 @@ FILE: implicitReceiverOrder.kt
} }
public final fun test(a: R|A|, b: R|B|): R|kotlin/Unit| { public final fun test(a: R|A|, b: R|B|): R|kotlin/Unit| {
R|kotlin/with|<R|B|, R|kotlin/Int|>(R|<local>/b|, <L> = with@fun R|B|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> { R|kotlin/with|<R|B|, R|kotlin/Int|>(R|<local>/b|, <L> = with@fun R|B|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
R|kotlin/with|<R|A|, R|kotlin/Int|>(R|<local>/a|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> { R|kotlin/with|<R|A|, R|kotlin/Int|>(R|<local>/a|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
this@R|/A|.R|/A.foo|() this@R|/A|.R|/A.foo|()
(this@R|/B|, this@R|special/anonymous|).R|/B.bar|() (this@R|/B|, this@R|special/anonymous|).R|/B.bar|()
} }
) )
} }
) )
R|kotlin/with|<R|A|, R|kotlin/Int|>(R|<local>/a|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> { R|kotlin/with|<R|A|, R|kotlin/Int|>(R|<local>/a|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
R|kotlin/with|<R|B|, R|kotlin/Int|>(R|<local>/b|, <L> = with@fun R|B|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> { R|kotlin/with|<R|B|, R|kotlin/Int|>(R|<local>/b|, <L> = with@fun R|B|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
this@R|/B|.R|/B.foo|() this@R|/B|.R|/B.foo|()
(this@R|/A|, this@R|special/anonymous|).R|/A.bar|() (this@R|/A|, this@R|special/anonymous|).R|/A.bar|()
} }
@@ -7,7 +7,7 @@ fun main(k: KSub, vString: SuperClass<String>.NestedInSuperClass, vInt: SuperCla
// TODO: Support parametrisized inner classes // TODO: Support parametrisized inner classes
k.getImpl().nestedI(vInt) k.getImpl().nestedI(vInt)
k.getNestedSubClass().<!INAPPLICABLE_CANDIDATE!>nested<!>("") k.getNestedSubClass().<!INAPPLICABLE_CANDIDATE!>nested<!>("")
k.getNestedSubClass().<!INAPPLICABLE_CANDIDATE!>nested<!>(1) k.getNestedSubClass().nested(1)
} }
// FILE: J1.java // FILE: J1.java
@@ -9,7 +9,7 @@ FILE: K1.kt
R|<local>/k|.R|/J1.getImpl|().R|FakeOverride</SuperI.NestedInI.nestedI: R|kotlin/Unit|>|(R|<local>/vString|) R|<local>/k|.R|/J1.getImpl|().R|FakeOverride</SuperI.NestedInI.nestedI: R|kotlin/Unit|>|(R|<local>/vString|)
R|<local>/k|.R|/J1.getImpl|().R|FakeOverride</SuperI.NestedInI.nestedI: R|kotlin/Unit|>|(R|<local>/vInt|) R|<local>/k|.R|/J1.getImpl|().R|FakeOverride</SuperI.NestedInI.nestedI: R|kotlin/Unit|>|(R|<local>/vInt|)
R|<local>/k|.R|/J1.getNestedSubClass|().<Inapplicable(INAPPLICABLE): [/SuperClass.NestedInSuperClass.nested]>#(String()) R|<local>/k|.R|/J1.getNestedSubClass|().<Inapplicable(INAPPLICABLE): [/SuperClass.NestedInSuperClass.nested]>#(String())
R|<local>/k|.R|/J1.getNestedSubClass|().<Inapplicable(INAPPLICABLE): [/SuperClass.NestedInSuperClass.nested]>#(Int(1)) R|<local>/k|.R|/J1.getNestedSubClass|().R|/SuperClass.NestedInSuperClass.nested|(Int(1))
} }
FILE: K2.kt FILE: K2.kt
public open class KFirst : R|SuperClass<kotlin/String>|, R|SuperI<kotlin/Int>| { public open class KFirst : R|SuperClass<kotlin/String>|, R|SuperI<kotlin/Int>| {
@@ -25,10 +25,10 @@ FILE: multipleImplicitReceivers.kt
} }
public final fun test(fooImpl: R|IFoo|, invokeImpl: R|IInvoke|): R|kotlin/Unit| { public final fun test(fooImpl: R|IFoo|, invokeImpl: R|IInvoke|): R|kotlin/Unit| {
R|kotlin/with|<R|A|, R|kotlin/Int|>(Q|A|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> { R|kotlin/with|<R|A|, R|kotlin/Int|>(Q|A|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
R|kotlin/with|<R|IFoo|, R|kotlin/Int|>(R|<local>/fooImpl|, <L> = with@fun R|IFoo|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> { R|kotlin/with|<R|IFoo|, R|kotlin/Int|>(R|<local>/fooImpl|, <L> = with@fun R|IFoo|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
(this@R|/IFoo|, this@R|special/anonymous|).R|/IFoo.foo| (this@R|/IFoo|, this@R|special/anonymous|).R|/IFoo.foo|
R|kotlin/with|<R|IInvoke|, R|kotlin/Int|>(R|<local>/invokeImpl|, <L> = with@fun R|IInvoke|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> { R|kotlin/with|<R|IInvoke|, R|kotlin/Int|>(R|<local>/invokeImpl|, <L> = with@fun R|IInvoke|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
(this@R|/IInvoke|, (this@R|/IFoo|, this@R|special/anonymous|).R|/IFoo.foo|).R|/IInvoke.invoke|() (this@R|/IInvoke|, (this@R|/IFoo|, this@R|special/anonymous|).R|/IFoo.foo|).R|/IInvoke.invoke|()
} }
) )
@@ -8,7 +8,7 @@ FILE: tryWithLambdaInside.kt
public final fun bar(): R|kotlin/collections/List<kotlin/String>| { public final fun bar(): R|kotlin/collections/List<kotlin/String>| {
^bar try { ^bar try {
R|/foo|().R|kotlin/collections/filter|<R|kotlin/String|>(<L> = filter@fun <implicit>.<anonymous>(): <implicit> <kind=UNKNOWN> { R|/foo|().R|kotlin/collections/filter|<R|kotlin/String|>(<L> = filter@fun <implicit>.<anonymous>(): <implicit> <kind=UNKNOWN> {
>(it#.length#, Int(2)) >(it#.length#, IntegerLiteral(2))
} }
) )
} }
+11
View File
@@ -0,0 +1,11 @@
fun test(b: Byte, s: Short, i: Int, l: Long) {
val x1 = 1.rangeTo(b)
val x2 = 1.rangeTo(s)
val x3 = 1.rangeTo(i)
val x4 = 1.rangeTo(l)
val x5 = b.rangeTo(1)
val x6 = s.rangeTo(1)
val x7 = i.rangeTo(1)
val x8 = l.rangeTo(1)
}
@@ -0,0 +1,11 @@
FILE: rangeTo.kt
public final fun test(b: R|kotlin/Byte|, s: R|kotlin/Short|, i: R|kotlin/Int|, l: R|kotlin/Long|): R|kotlin/Unit| {
lval x1: R|kotlin/ranges/IntRange| = Int(1).R|kotlin/Int.rangeTo|(R|<local>/b|)
lval x2: R|kotlin/ranges/IntRange| = Int(1).R|kotlin/Int.rangeTo|(R|<local>/s|)
lval x3: R|kotlin/ranges/IntRange| = Int(1).R|kotlin/Int.rangeTo|(R|<local>/i|)
lval x4: R|kotlin/ranges/LongRange| = Int(1).R|kotlin/Int.rangeTo|(R|<local>/l|)
lval x5: R|kotlin/ranges/IntRange| = R|<local>/b|.R|kotlin/Byte.rangeTo|(Int(1))
lval x6: R|kotlin/ranges/IntRange| = R|<local>/s|.R|kotlin/Short.rangeTo|(Int(1))
lval x7: R|kotlin/ranges/IntRange| = R|<local>/i|.R|kotlin/Int.rangeTo|(Int(1))
lval x8: R|kotlin/ranges/LongRange| = R|<local>/l|.R|kotlin/Long.rangeTo|(Int(1))
}
@@ -275,6 +275,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/arguments/incorrectFunctionalType.kt"); runTest("compiler/fir/resolve/testData/resolve/arguments/incorrectFunctionalType.kt");
} }
@TestMetadata("integerLiteralTypes.kt")
public void testIntegerLiteralTypes() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/integerLiteralTypes.kt");
}
@TestMetadata("invoke.kt") @TestMetadata("invoke.kt")
public void testInvoke() throws Exception { public void testInvoke() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/invoke.kt"); runTest("compiler/fir/resolve/testData/resolve/arguments/invoke.kt");
@@ -305,6 +310,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/arguments/lambdaInUnresolvedCall.kt"); runTest("compiler/fir/resolve/testData/resolve/arguments/lambdaInUnresolvedCall.kt");
} }
@TestMetadata("operatorsOverLiterals.kt")
public void testOperatorsOverLiterals() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/operatorsOverLiterals.kt");
}
@TestMetadata("overloadByReceiver.kt") @TestMetadata("overloadByReceiver.kt")
public void testOverloadByReceiver() throws Exception { public void testOverloadByReceiver() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/overloadByReceiver.kt"); runTest("compiler/fir/resolve/testData/resolve/arguments/overloadByReceiver.kt");
@@ -158,6 +158,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic
runTest("compiler/fir/resolve/testData/resolve/stdlib/problems.kt"); runTest("compiler/fir/resolve/testData/resolve/stdlib/problems.kt");
} }
@TestMetadata("rangeTo.kt")
public void testRangeTo() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/rangeTo.kt");
}
@TestMetadata("recursiveBug.kt") @TestMetadata("recursiveBug.kt")
public void testRecursiveBug() throws Exception { public void testRecursiveBug() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/recursiveBug.kt"); runTest("compiler/fir/resolve/testData/resolve/stdlib/recursiveBug.kt");
@@ -48,6 +48,8 @@ abstract class FirField : FirPureAbstractElement(), FirVariable<FirField>, FirCa
abstract override fun <D> transformReceiverTypeRef(transformer: FirTransformer<D>, data: D): FirField abstract override fun <D> transformReceiverTypeRef(transformer: FirTransformer<D>, data: D): FirField
abstract override fun <D> transformInitializer(transformer: FirTransformer<D>, data: D): FirField
abstract override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirField abstract override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirField
abstract override fun <D> transformSetter(transformer: FirTransformer<D>, data: D): FirField abstract override fun <D> transformSetter(transformer: FirTransformer<D>, data: D): FirField
@@ -54,6 +54,8 @@ abstract class FirProperty : FirPureAbstractElement(), FirVariable<FirProperty>,
abstract override fun <D> transformReceiverTypeRef(transformer: FirTransformer<D>, data: D): FirProperty abstract override fun <D> transformReceiverTypeRef(transformer: FirTransformer<D>, data: D): FirProperty
abstract override fun <D> transformInitializer(transformer: FirTransformer<D>, data: D): FirProperty
abstract override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirProperty abstract override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirProperty
abstract override fun <D> transformSetter(transformer: FirTransformer<D>, data: D): FirProperty abstract override fun <D> transformSetter(transformer: FirTransformer<D>, data: D): FirProperty
@@ -48,6 +48,8 @@ abstract class FirValueParameter : FirPureAbstractElement(), FirVariable<FirValu
abstract override fun <D> transformReceiverTypeRef(transformer: FirTransformer<D>, data: D): FirValueParameter abstract override fun <D> transformReceiverTypeRef(transformer: FirTransformer<D>, data: D): FirValueParameter
abstract override fun <D> transformInitializer(transformer: FirTransformer<D>, data: D): FirValueParameter
abstract override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirValueParameter abstract override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirValueParameter
abstract override fun <D> transformSetter(transformer: FirTransformer<D>, data: D): FirValueParameter abstract override fun <D> transformSetter(transformer: FirTransformer<D>, data: D): FirValueParameter
@@ -44,6 +44,8 @@ interface FirVariable<F : FirVariable<F>> : FirCallableDeclaration<F>, FirNamedD
override fun <D> transformReceiverTypeRef(transformer: FirTransformer<D>, data: D): FirVariable<F> override fun <D> transformReceiverTypeRef(transformer: FirTransformer<D>, data: D): FirVariable<F>
fun <D> transformInitializer(transformer: FirTransformer<D>, data: D): FirVariable<F>
fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirVariable<F> fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirVariable<F>
fun <D> transformSetter(transformer: FirTransformer<D>, data: D): FirVariable<F> fun <D> transformSetter(transformer: FirTransformer<D>, data: D): FirVariable<F>
@@ -65,6 +65,7 @@ class FirDefaultSetterValueParameter(
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirDefaultSetterValueParameter { override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirDefaultSetterValueParameter {
transformReturnTypeRef(transformer, data) transformReturnTypeRef(transformer, data)
transformReceiverTypeRef(transformer, data) transformReceiverTypeRef(transformer, data)
transformInitializer(transformer, data)
transformGetter(transformer, data) transformGetter(transformer, data)
transformSetter(transformer, data) transformSetter(transformer, data)
transformOtherChildren(transformer, data) transformOtherChildren(transformer, data)
@@ -81,6 +82,11 @@ class FirDefaultSetterValueParameter(
return this return this
} }
override fun <D> transformInitializer(transformer: FirTransformer<D>, data: D): FirDefaultSetterValueParameter {
initializer = initializer?.transformSingle(transformer, data)
return this
}
override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirDefaultSetterValueParameter { override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirDefaultSetterValueParameter {
getter = getter?.transformSingle(transformer, data) getter = getter?.transformSingle(transformer, data)
return this return this
@@ -92,7 +98,6 @@ class FirDefaultSetterValueParameter(
} }
override fun <D> transformOtherChildren(transformer: FirTransformer<D>, data: D): FirDefaultSetterValueParameter { override fun <D> transformOtherChildren(transformer: FirTransformer<D>, data: D): FirDefaultSetterValueParameter {
initializer = initializer?.transformSingle(transformer, data)
delegate = delegate?.transformSingle(transformer, data) delegate = delegate?.transformSingle(transformer, data)
annotations.transformInplace(transformer, data) annotations.transformInplace(transformer, data)
defaultValue = defaultValue?.transformSingle(transformer, data) defaultValue = defaultValue?.transformSingle(transformer, data)
@@ -76,6 +76,10 @@ class FirFieldImpl(
return this return this
} }
override fun <D> transformInitializer(transformer: FirTransformer<D>, data: D): FirFieldImpl {
return this
}
override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirFieldImpl { override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirFieldImpl {
return this return this
} }
@@ -46,6 +46,8 @@ interface FirModifiableVariable<F : FirVariable<F>> : FirVariable<F>, FirAbstra
override fun <D> transformReceiverTypeRef(transformer: FirTransformer<D>, data: D): FirModifiableVariable<F> override fun <D> transformReceiverTypeRef(transformer: FirTransformer<D>, data: D): FirModifiableVariable<F>
override fun <D> transformInitializer(transformer: FirTransformer<D>, data: D): FirModifiableVariable<F>
override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirModifiableVariable<F> override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirModifiableVariable<F>
override fun <D> transformSetter(transformer: FirTransformer<D>, data: D): FirModifiableVariable<F> override fun <D> transformSetter(transformer: FirTransformer<D>, data: D): FirModifiableVariable<F>
@@ -76,6 +76,7 @@ class FirPropertyImpl(
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirPropertyImpl { override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirPropertyImpl {
transformReturnTypeRef(transformer, data) transformReturnTypeRef(transformer, data)
transformReceiverTypeRef(transformer, data) transformReceiverTypeRef(transformer, data)
transformInitializer(transformer, data)
transformGetter(transformer, data) transformGetter(transformer, data)
transformSetter(transformer, data) transformSetter(transformer, data)
transformControlFlowGraphReference(transformer, data) transformControlFlowGraphReference(transformer, data)
@@ -94,6 +95,11 @@ class FirPropertyImpl(
return this return this
} }
override fun <D> transformInitializer(transformer: FirTransformer<D>, data: D): FirPropertyImpl {
initializer = initializer?.transformSingle(transformer, data)
return this
}
override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirPropertyImpl { override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirPropertyImpl {
getter = getter?.transformSingle(transformer, data) getter = getter?.transformSingle(transformer, data)
return this return this
@@ -115,7 +121,6 @@ class FirPropertyImpl(
} }
override fun <D> transformOtherChildren(transformer: FirTransformer<D>, data: D): FirPropertyImpl { override fun <D> transformOtherChildren(transformer: FirTransformer<D>, data: D): FirPropertyImpl {
initializer = initializer?.transformSingle(transformer, data)
delegate = delegate?.transformSingle(transformer, data) delegate = delegate?.transformSingle(transformer, data)
annotations.transformInplace(transformer, data) annotations.transformInplace(transformer, data)
typeParameters.transformInplace(transformer, data) typeParameters.transformInplace(transformer, data)
@@ -65,6 +65,7 @@ open class FirValueParameterImpl(
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirValueParameterImpl { override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirValueParameterImpl {
transformReturnTypeRef(transformer, data) transformReturnTypeRef(transformer, data)
transformReceiverTypeRef(transformer, data) transformReceiverTypeRef(transformer, data)
transformInitializer(transformer, data)
transformGetter(transformer, data) transformGetter(transformer, data)
transformSetter(transformer, data) transformSetter(transformer, data)
transformOtherChildren(transformer, data) transformOtherChildren(transformer, data)
@@ -81,6 +82,11 @@ open class FirValueParameterImpl(
return this return this
} }
override fun <D> transformInitializer(transformer: FirTransformer<D>, data: D): FirValueParameterImpl {
initializer = initializer?.transformSingle(transformer, data)
return this
}
override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirValueParameterImpl { override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirValueParameterImpl {
getter = getter?.transformSingle(transformer, data) getter = getter?.transformSingle(transformer, data)
return this return this
@@ -92,7 +98,6 @@ open class FirValueParameterImpl(
} }
override fun <D> transformOtherChildren(transformer: FirTransformer<D>, data: D): FirValueParameterImpl { override fun <D> transformOtherChildren(transformer: FirTransformer<D>, data: D): FirValueParameterImpl {
initializer = initializer?.transformSingle(transformer, data)
delegate = delegate?.transformSingle(transformer, data) delegate = delegate?.transformSingle(transformer, data)
annotations.transformInplace(transformer, data) annotations.transformInplace(transformer, data)
defaultValue = defaultValue?.transformSingle(transformer, data) defaultValue = defaultValue?.transformSingle(transformer, data)

Some files were not shown because too many files have changed in this diff Show More