[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 Comparable = "Comparable".baseId()
val Number = "Number".baseId()
fun byName(name: String) = name.baseId()
fun reflectByName(name: String) = name.reflectId()
@@ -5,10 +5,14 @@
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.ConeClassifierLookupTag
import org.jetbrains.kotlin.name.ClassId
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.*
sealed class ConeKotlinTypeProjection : TypeArgumentMarker {
@@ -230,3 +234,33 @@ open class ConeTypeVariable(name: String) : TypeVariableMarker {
class ConeTypeVariableTypeConstructor(val debugName: String) : ConeClassifierLookupTag(), TypeVariableTypeConstructorMarker {
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 ConeIntegerLiteralType -> "ILT: $value"
} + 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.impl.FirTypePlaceholderProjection
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.FqName
import org.jetbrains.kotlin.name.Name
@@ -728,38 +727,38 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
private fun FlowContent.generate(expression: FirConstExpression<*>) {
val value = expression.value
if (value == null && expression.kind != IrConstKind.Null) {
if (value == null && expression.kind != FirConstKind.Null) {
return error {
+"null value"
}
}
when (expression.kind) {
IrConstKind.Null -> keyword("null")
IrConstKind.Boolean -> keyword(value.toString())
IrConstKind.String, IrConstKind.Char ->
FirConstKind.Null -> keyword("null")
FirConstKind.Boolean -> keyword(value.toString())
FirConstKind.String, FirConstKind.Char ->
stringLiteral(value)
IrConstKind.Byte -> {
FirConstKind.Byte -> {
+value.toString()
keyword("B")
}
IrConstKind.Short -> {
FirConstKind.Short -> {
+value.toString()
keyword("S")
}
IrConstKind.Int -> {
FirConstKind.Int -> {
+value.toString()
keyword("I")
}
IrConstKind.Long -> {
FirConstKind.Long -> {
+value.toString()
keyword("L")
}
IrConstKind.Float -> {
FirConstKind.Float -> {
+value.toString()
keyword("F")
}
IrConstKind.Double -> {
FirConstKind.Double -> {
+value.toString()
keyword("D")
}
@@ -784,6 +783,7 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
+"!!"
}
is ConeIntersectionType -> resolved { generate(type) }
is ConeIntegerLiteralType -> inlineUnsupported(type)
}
if (type.typeArguments.isNotEmpty()) {
+"<"
@@ -73,6 +73,7 @@ fun ConeKotlinType.toIrType(session: FirSession, declarationStorage: Fir2IrDecla
intersectedTypes.first().toIrType(session, declarationStorage, definitelyNotNull)
}
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.firSymbolProvider
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.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.impl.*
import org.jetbrains.kotlin.fir.types.*
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.IrStatement
import org.jetbrains.kotlin.ir.builders.*
@@ -71,6 +75,8 @@ class Fir2IrVisitor(
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 declarationStorage = Fir2IrDeclarationStorage(session, symbolTable, moduleDescriptor)
@@ -822,6 +828,11 @@ class Fir2IrVisitor(
}
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)
.applyReceivers(functionCall)
}
@@ -916,10 +927,23 @@ class Fir2IrVisitor(
override fun <T> visitConstExpression(constExpression: FirConstExpression<T>, data: Any?): IrElement {
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(
startOffset, endOffset,
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) {
is ConeClassLikeType -> mapToCanonicalString(session)
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}]")
is ConeLookupTagBasedType -> lookupTag.name.asString()
}
@@ -222,7 +222,7 @@ private fun ConeKotlinType.mapToCanonicalString(session: FirSession): String {
return when (this) {
is ConeClassLikeType -> mapToCanonicalString(session)
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}]")
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.FirResolvedTypeRefImpl
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.impl.JavaElementImpl
import org.jetbrains.kotlin.name.ClassId
@@ -275,7 +275,7 @@ private fun JavaAnnotationArgument.toFirExpression(
}
// 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 {
for (element in this@createArrayOfCall) {
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 {
return when (this) {
is Byte -> FirConstExpressionImpl(null, IrConstKind.Byte, this)
is Short -> FirConstExpressionImpl(null, IrConstKind.Short, this)
is Int -> FirConstExpressionImpl(null, IrConstKind.Int, this)
is Long -> FirConstExpressionImpl(null, IrConstKind.Long, this)
is Char -> FirConstExpressionImpl(null, IrConstKind.Char, this)
is Float -> FirConstExpressionImpl(null, IrConstKind.Float, this)
is Double -> FirConstExpressionImpl(null, IrConstKind.Double, this)
is Boolean -> FirConstExpressionImpl(null, IrConstKind.Boolean, this)
is String -> FirConstExpressionImpl(null, IrConstKind.String, this)
is ByteArray -> toList().createArrayOfCall(session, IrConstKind.Byte)
is ShortArray -> toList().createArrayOfCall(session, IrConstKind.Short)
is IntArray -> toList().createArrayOfCall(session, IrConstKind.Int)
is LongArray -> toList().createArrayOfCall(session, IrConstKind.Long)
is CharArray -> toList().createArrayOfCall(session, IrConstKind.Char)
is FloatArray -> toList().createArrayOfCall(session, IrConstKind.Float)
is DoubleArray -> toList().createArrayOfCall(session, IrConstKind.Double)
is BooleanArray -> toList().createArrayOfCall(session, IrConstKind.Boolean)
null -> FirConstExpressionImpl(null, IrConstKind.Null, null)
is Byte -> FirConstExpressionImpl(null, FirConstKind.Byte, this)
is Short -> FirConstExpressionImpl(null, FirConstKind.Short, this)
is Int -> FirConstExpressionImpl(null, FirConstKind.Int, this)
is Long -> FirConstExpressionImpl(null, FirConstKind.Long, this)
is Char -> FirConstExpressionImpl(null, FirConstKind.Char, this)
is Float -> FirConstExpressionImpl(null, FirConstKind.Float, this)
is Double -> FirConstExpressionImpl(null, FirConstKind.Double, this)
is Boolean -> FirConstExpressionImpl(null, FirConstKind.Boolean, this)
is String -> FirConstExpressionImpl(null, FirConstKind.String, this)
is ByteArray -> toList().createArrayOfCall(session, FirConstKind.Byte)
is ShortArray -> toList().createArrayOfCall(session, FirConstKind.Short)
is IntArray -> toList().createArrayOfCall(session, FirConstKind.Int)
is LongArray -> toList().createArrayOfCall(session, FirConstKind.Long)
is CharArray -> toList().createArrayOfCall(session, FirConstKind.Char)
is FloatArray -> toList().createArrayOfCall(session, FirConstKind.Float)
is DoubleArray -> toList().createArrayOfCall(session, FirConstKind.Double)
is BooleanArray -> toList().createArrayOfCall(session, FirConstKind.Boolean)
null -> FirConstExpressionImpl(null, FirConstKind.Null, null)
else -> FirErrorExpressionImpl(null, FirSimpleDiagnostic("Unknown value in JavaLiteralAnnotationArgument: $this", DiagnosticKind.Java))
}
@@ -111,4 +111,8 @@ class FirJavaField(
get() = 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.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
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.*
import org.jetbrains.kotlin.fir.expressions.impl.FirConstExpressionImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
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.types.*
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_VALUE_FQ_NAME
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)
return when (classId.relativeClassName.asString()) {
"Boolean" -> FirConstExpressionImpl(null, IrConstKind.Boolean, value.toBoolean())
"Char" -> FirConstExpressionImpl(null, IrConstKind.Char, value.singleOrNull() ?: return null)
"Byte" -> FirConstExpressionImpl(null, IrConstKind.Byte, number.toByteOrNull(radix) ?: return null)
"Short" -> FirConstExpressionImpl(null, IrConstKind.Short, number.toShortOrNull(radix) ?: return null)
"Int" -> FirConstExpressionImpl(null, IrConstKind.Int, number.toIntOrNull(radix) ?: return null)
"Long" -> FirConstExpressionImpl(null, IrConstKind.Long, number.toLongOrNull(radix) ?: return null)
"Float" -> FirConstExpressionImpl(null, IrConstKind.Float, value.toFloatOrNull() ?: return null)
"Double" -> FirConstExpressionImpl(null, IrConstKind.Double, value.toDoubleOrNull() ?: return null)
"String" -> FirConstExpressionImpl(null, IrConstKind.String, value)
"Boolean" -> FirConstExpressionImpl(null, FirConstKind.Boolean, value.toBoolean())
"Char" -> FirConstExpressionImpl(null, FirConstKind.Char, value.singleOrNull() ?: return null)
"Byte" -> FirConstExpressionImpl(null, FirConstKind.Byte, number.toByteOrNull(radix) ?: return null)
"Short" -> FirConstExpressionImpl(null, FirConstKind.Short, number.toShortOrNull(radix) ?: return null)
"Int" -> FirConstExpressionImpl(null, FirConstKind.Int, number.toIntOrNull(radix) ?: return null)
"Long" -> FirConstExpressionImpl(null, FirConstKind.Long, number.toLongOrNull(radix) ?: return null)
"Float" -> FirConstExpressionImpl(null, FirConstKind.Float, value.toFloatOrNull() ?: return null)
"Double" -> FirConstExpressionImpl(null, FirConstKind.Double, value.toDoubleOrNull() ?: return null)
"String" -> FirConstExpressionImpl(null, FirConstKind.String, value)
else -> null
}
}
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
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.impl.FirConstExpressionImpl
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.types.FirResolvedTypeRef
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.descriptors.NullDefaultValue
import org.jetbrains.kotlin.load.java.descriptors.StringDefaultValue
@@ -276,7 +276,7 @@ class JavaClassEnhancementScope(
).enhance(session, jsr305State, predefinedEnhancementInfo?.parametersInfo?.getOrNull(index))
val firResolvedTypeRef = signatureParts.type
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)
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.ConeTypeParameterTypeImpl
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.OPEN_QUOTE
import org.jetbrains.kotlin.name.FqName
@@ -224,40 +223,50 @@ abstract class BaseFirBuilder<T>(val session: FirSession, val context: Context =
else -> null
}
return when (type) {
INTEGER_CONSTANT ->
if (convertedText is Long &&
(hasLongSuffix(text) || hasUnsignedLongSuffix(text) || hasUnsignedSuffix(text) ||
convertedText > Int.MAX_VALUE || convertedText < Int.MIN_VALUE)
) {
FirConstExpressionImpl(
expression.getSourceOrNull(), IrConstKind.Long, convertedText, FirSimpleDiagnostic("Incorrect long: $text", DiagnosticKind.Syntax)
INTEGER_CONSTANT -> {
val kind = when {
convertedText !is Long -> return FirErrorExpressionImpl(
expression.getSourceOrNull(),
FirSimpleDiagnostic(
"Incorrect constant expression: $text",
DiagnosticKind.IllegalConstExpression
)
)
} else if (convertedText is Number) {
// TODO: support byte / short
FirConstExpressionImpl(
expression.getSourceOrNull(), IrConstKind.Int, convertedText.toInt(), FirSimpleDiagnostic("Incorrect int: $text", DiagnosticKind.Syntax)
)
} else {
FirErrorExpressionImpl(expression.getSourceOrNull(), FirSimpleDiagnostic("Incorrect constant expression: $text", DiagnosticKind.IllegalConstExpression))
hasLongSuffix(text) || hasUnsignedSuffix(text) || hasUnsignedLongSuffix(text) -> {
FirConstKind.Long
}
else -> {
FirConstKind.IntegerLiteral
}
}
FirConstExpressionImpl(
expression.getSourceOrNull(),
kind,
convertedText,
FirSimpleDiagnostic("Incorrect integer literal: $text", DiagnosticKind.Syntax)
)
}
FLOAT_CONSTANT ->
if (convertedText is Float) {
FirConstExpressionImpl(
expression.getSourceOrNull(), IrConstKind.Float, convertedText, FirSimpleDiagnostic("Incorrect float: $text", DiagnosticKind.Syntax)
expression.getSourceOrNull(), FirConstKind.Float, convertedText, FirSimpleDiagnostic("Incorrect float: $text", DiagnosticKind.Syntax)
)
} else {
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 ->
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 ->
FirConstExpressionImpl(expression.getSourceOrNull(), IrConstKind.Boolean, convertedText as Boolean)
FirConstExpressionImpl(expression.getSourceOrNull(), FirConstKind.Boolean, convertedText as Boolean)
NULL ->
FirConstExpressionImpl(expression.getSourceOrNull(), IrConstKind.Null, null)
FirConstExpressionImpl(expression.getSourceOrNull(), FirConstKind.Null, null)
else ->
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
LITERAL_STRING_TEMPLATE_ENTRY -> {
sb.append(entry.asText)
FirConstExpressionImpl(entry.getSourceOrNull(), IrConstKind.String, entry.asText)
FirConstExpressionImpl(entry.getSourceOrNull(), FirConstKind.String, entry.asText)
}
ESCAPE_STRING_TEMPLATE_ENTRY -> {
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 -> {
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.impl.FirImplicitKPropertyTypeRef
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.name.Name
import org.jetbrains.kotlin.psi.*
@@ -149,7 +148,7 @@ fun FirExpression.generateNotNullOrOther(
baseSource,
FirOperatorCallImpl(baseSource, FirOperation.EQ).apply {
arguments += subjectExpression
arguments += FirConstExpressionImpl(baseSource, IrConstKind.Null, null)
arguments += FirConstExpressionImpl(baseSource, FirConstKind.Null, null)
},
FirSingleExpressionBlock(other)
)
@@ -326,7 +325,7 @@ fun FirModifiableVariable<*>.generateAccessorsByDelegate(session: FirSession, me
if (member) FirQualifiedAccessExpressionImpl(null).apply {
calleeReference = FirExplicitThisReference(null, null)
}
else FirConstExpressionImpl(null, IrConstKind.Null, null)
else FirConstExpressionImpl(null, FirConstKind.Null, null)
fun propertyRef() = FirCallableReferenceAccessImpl(null).apply {
calleeReference = FirResolvedNamedReferenceImpl(null, variable.name, variable.symbol)
@@ -17,5 +17,5 @@ FILE: expectActual.kt
public? final? actual fun foo(): <implicit> {
^foo String(Hello)
}
public? final? actual val x: <implicit> = Int(42)
public? final? actual val x: <implicit> = IntegerLiteral(42)
public? get(): <implicit>
@@ -11,7 +11,7 @@ FILE: simpleClass.kt
super<R|kotlin/Any|>()
}
private final? val baz: <implicit> = Int(42)
private final? val baz: <implicit> = IntegerLiteral(42)
private get(): <implicit>
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 {
^get Int(42)
^get IntegerLiteral(42)
}
public? open? override fun concat(other: List<Int>): List<Int> {
@@ -7,18 +7,18 @@ FILE: annotated.kt
}
public? final? fun foo(arg: Int): Int {
when () {
==(@Ann() arg#, Int(0)) -> {
@Ann() ^foo Int(1)
==(@Ann() arg#, IntegerLiteral(0)) -> {
@Ann() ^foo IntegerLiteral(1)
}
}
@Ann() when () {
==(arg#, Int(1)) -> {
^foo @Ann() Int(1)
==(arg#, IntegerLiteral(1)) -> {
^foo @Ann() IntegerLiteral(1)
}
}
^foo Int(42)
^foo IntegerLiteral(42)
}
public? final? data class Two : R|kotlin/Any| {
public? constructor(x: Int, y: Int): R|Two| {
@@ -1,8 +1,8 @@
FILE: arrayAccess.kt
public? final? val p: <implicit> = Int(0)
public? final? val p: <implicit> = IntegerLiteral(0)
public? get(): <implicit>
public? final? fun foo(): <implicit> {
^foo Int(1)
^foo IntegerLiteral(1)
}
public? final? class Wrapper : R|kotlin/Any| {
public? constructor(v: IntArray): R|Wrapper| {
@@ -14,5 +14,5 @@ FILE: arrayAccess.kt
}
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
public? final? fun test(): R|kotlin/Unit| {
lval x: <implicit> = intArrayOf#(Int(1), Int(2), Int(3))
x#.set#(Int(1), Int(0))
lval x: <implicit> = intArrayOf#(IntegerLiteral(1), IntegerLiteral(2), IntegerLiteral(3))
x#.set#(IntegerLiteral(1), IntegerLiteral(0))
}
public? final? fun foo(): <implicit> {
^foo Int(1)
^foo IntegerLiteral(1)
}
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 {
^grade when (g#) {
==($subj$, Int(6)) || ==($subj$, Int(7)) -> {
==($subj$, IntegerLiteral(6)) || ==($subj$, IntegerLiteral(7)) -> {
String(Outstanding)
}
==($subj$, Int(5)) -> {
==($subj$, IntegerLiteral(5)) -> {
String(Excellent)
}
==($subj$, Int(4)) -> {
==($subj$, IntegerLiteral(4)) -> {
String(Good)
}
==($subj$, Int(3)) -> {
==($subj$, IntegerLiteral(3)) -> {
String(Mediocre)
}
Int(1).rangeTo#(Int(2)).contains#($subj$) -> {
IntegerLiteral(1).rangeTo#(IntegerLiteral(2)).contains#($subj$) -> {
String(Fail)
}
($subj$ is Number) -> {
@@ -7,7 +7,7 @@ FILE: callableReferences.kt
public? final? fun foo(): R|kotlin/Unit| {
}
public? final? val bar: <implicit> = Int(0)
public? final? val bar: <implicit> = IntegerLiteral(0)
public? get(): <implicit>
}
@@ -3,10 +3,10 @@ FILE: calls.kt
^distance x#.plus#(y#)
}
public? final? fun test(): Int {
^test Int(3).distance#(Int(4))
^test IntegerLiteral(3).distance#(IntegerLiteral(4))
}
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? constructor(x: Int): R|My| {
@@ -30,7 +30,7 @@ FILE: calls.kt
}
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| {
println#(first#.x#)
@@ -38,5 +38,5 @@ FILE: calls.kt
first#.foo#()
second#?.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| {
super<R|kotlin/Any|>()
}
@@ -1,6 +1,6 @@
FILE: for.kt
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#()
while(R|<local>/<iterator>|.hasNext#()) {
lval i: <implicit> = R|<local>/<iterator>|.next#()
@@ -9,14 +9,14 @@ FILE: for.kt
}
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#()
while(R|<local>/<iterator>|.hasNext#()) {
lval element: <implicit> = R|<local>/<iterator>|.next#()
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#()
while(R|<local>/<iterator>|.hasNext#()) {
lval element: <implicit> = R|<local>/<iterator>|.next#()
@@ -23,7 +23,7 @@ FILE: lambda.kt
}
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 {
lval l1: <implicit> = fun <implicit>.<anonymous>(t: Tuple): <implicit> {
@@ -40,8 +40,8 @@ FILE: lambda.kt
)
^foo use#(<L> = use@fun <implicit>.<anonymous>(): <implicit> {
when () {
==(it#.x#, Int(0)) -> {
^foo Int(0)
==(it#.x#, IntegerLiteral(0)) -> {
^foo IntegerLiteral(0)
}
}
@@ -52,8 +52,8 @@ FILE: lambda.kt
public? final? fun bar(): Int {
^bar use#(<L> = lambda@fun <implicit>.<anonymous>(): <implicit> {
when () {
==(it#.x#, Int(0)) -> {
^bar Int(0)
==(it#.x#, IntegerLiteral(0)) -> {
^bar IntegerLiteral(0)
}
}
@@ -77,7 +77,7 @@ FILE: lambda.kt
public? get(): <implicit>
public? final? val another: <implicit> = fun <implicit>.<anonymous>(): <implicit> {
Int(42)
IntegerLiteral(42)
}
public? get(): <implicit>
@@ -14,7 +14,7 @@ FILE: lambdaAndAnonymousFunction.kt
}
public? final? fun test_2(): R|kotlin/Unit| {
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 {
^sum x#.plus#(f#(y#.plus#(z#)))
}
@@ -30,7 +30,7 @@ FILE: locals.kt
}
.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#)
}
)
@@ -1,15 +1,15 @@
FILE: modifications.kt
public? final? fun simple(): R|kotlin/Unit| {
lvar x: <implicit> = Int(10)
+=(x#, Int(20))
-=(x#, Int(5))
/=(x#, Int(5))
*=(x#, Int(10))
lvar x: <implicit> = IntegerLiteral(10)
+=(x#, IntegerLiteral(20))
-=(x#, IntegerLiteral(5))
/=(x#, IntegerLiteral(5))
*=(x#, IntegerLiteral(10))
}
public? final? fun List<String>.modify(): R|kotlin/Unit| {
+=(this#, String(Alpha))
+=(this#, String(Omega))
}
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> {
^orFourtyTwo when (lval <elvis>: <implicit> = arg#) {
==($subj$, Null(null)) -> {
Int(42)
IntegerLiteral(42)
}
else -> {
R|<local>/<elvis>|
@@ -5,7 +5,7 @@ FILE: these.kt
}
public? final? fun foo(): Int {
^foo Int(1)
^foo IntegerLiteral(1)
}
public? final? fun bar(): Int {
@@ -1,6 +1,6 @@
FILE: unary.kt
public? final? fun test(): R|kotlin/Unit| {
lvar x: <implicit> = Int(0)
lvar x: <implicit> = IntegerLiteral(0)
lval x1: <implicit> = {
lval <unary>: <implicit> = x#
x# = R|<local>/<unary>|.inc#()
@@ -26,7 +26,7 @@ FILE: unary.kt
}
when () {
==(x#, Int(0)).not#() -> {
==(x#, IntegerLiteral(0)).not#() -> {
println#(String(000))
}
}
@@ -58,15 +58,15 @@ FILE: unary.kt
}
public? final? fun test3(arr: Array<Int>): R|kotlin/Unit| {
lval x1: <implicit> = {
lval <unary>: <implicit> = arr#.get#(Int(0))
arr#.set#(Int(0), R|<local>/<unary>|.inc#())
lval <unary>: <implicit> = arr#.get#(IntegerLiteral(0))
arr#.set#(IntegerLiteral(0), R|<local>/<unary>|.inc#())
R|<local>/<unary>|
}
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#()
arr#.set#(Int(1), R|<local>/<unary-result>|)
arr#.set#(IntegerLiteral(1), R|<local>/<unary-result>|)
R|<local>/<unary-result>|
}
@@ -82,15 +82,15 @@ FILE: unary.kt
}
public? final? fun test4(y: Y): R|kotlin/Unit| {
lval x1: <implicit> = {
lval <unary>: <implicit> = y#.arr#.get#(Int(0))
y#.arr#.set#(Int(0), R|<local>/<unary>|.inc#())
lval <unary>: <implicit> = y#.arr#.get#(IntegerLiteral(0))
y#.arr#.set#(IntegerLiteral(0), R|<local>/<unary>|.inc#())
R|<local>/<unary>|
}
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#()
y#.arr#.set#(Int(1), R|<local>/<unary-result>|)
y#.arr#.set#(IntegerLiteral(1), R|<local>/<unary-result>|)
R|<local>/<unary-result>|
}
@@ -1,8 +1,8 @@
FILE: variables.kt
public? final? fun foo(): R|kotlin/Unit| {
lval x: <implicit> = Int(1)
lvar y: <implicit> = x#.plus#(Int(1))
lval z: <implicit> = y#.times#(Int(2))
lval x: <implicit> = IntegerLiteral(1)
lvar y: <implicit> = x#.plus#(IntegerLiteral(1))
lval z: <implicit> = y#.times#(IntegerLiteral(2))
y# = y#.plus#(z#)
lval w: <implicit> = y#.minus#(x#)
^foo w#
@@ -1,12 +1,12 @@
FILE: while.kt
public? final? fun foo(limit: Int): R|kotlin/Unit| {
lvar k: <implicit> = Int(0)
lvar k: <implicit> = IntegerLiteral(0)
some@while(<(k#, limit#)) {
lval <unary>: <implicit> = k#
k# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
println#(k#)
while(==(k#, Int(13))) {
while(==(k#, IntegerLiteral(13))) {
lval <unary>: <implicit> = k#
k# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
@@ -18,7 +18,7 @@ FILE: while.kt
when () {
>(k#, limit#) -> {
continue@@@[==(k#, Int(13))]
continue@@@[==(k#, IntegerLiteral(13))]
}
}
@@ -35,5 +35,5 @@ FILE: while.kt
R|<local>/<unary>|
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.FirNamedReference
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.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeProjection
@@ -36,7 +37,11 @@ fun FirFunctionCall.copy(
typeArguments: List<FirTypeProjection> = this.typeArguments,
resultType: FirTypeRef = this.typeRef
): FirFunctionCall {
return FirFunctionCallImpl(source).apply {
return if (this is FirIntegerOperatorCall) {
FirIntegerOperatorCall(source)
} else {
FirFunctionCallImpl(source)
}.apply {
this.safe = safe
this.annotations.addAll(annotations)
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.impl.*
import org.jetbrains.kotlin.fir.symbols.invoke
import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.name.Name
@@ -74,15 +72,56 @@ class FirCallResolver(
fun resolveCallAndSelectCandidate(functionCall: FirFunctionCall, file: FirFile): FirFunctionCall {
qualifiedResolver.reset()
@Suppress("NAME_SHADOWING")
val functionCall = functionCall.transformExplicitReceiver(transformer, ResolutionMode.ContextIndependent)
var functionCall = functionCall.transformExplicitReceiver(transformer, ResolutionMode.ContextIndependent)
.also { dataFlowAnalyzer.enterQualifiedAccessExpression(functionCall) }
.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 arguments = functionCall.arguments
val typeArguments = functionCall.typeArguments
val name = functionCall.calleeReference.name
val info = CallInfo(
CallKind.Function,
@@ -108,34 +147,7 @@ class FirCallResolver(
} else {
conflictResolver.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = true)
}
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
return ResolutionResult(info, result.currentApplicability, reducedCandidates)
}
fun <T : FirQualifiedAccess> resolveVariableAccessAndSelectCandidate(qualifiedAccess: T, file: FirFile): FirStatement {
@@ -5,11 +5,12 @@
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.ConeTypeContext
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(
errorTypesEqualToAnything: 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.impl.FirErrorTypeRefImpl
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.Annotation.Argument.Value.Type.*
import org.jetbrains.kotlin.metadata.deserialization.Flags
@@ -111,15 +111,15 @@ abstract class AbstractAnnotationDeserializer(
// TODO: val isUnsigned = Flags.IS_UNSIGNED.get(value.flags)
val result: FirExpression = when (value.type) {
BYTE -> const(IrConstKind.Byte, value.intValue.toByte())
CHAR -> const(IrConstKind.Char, value.intValue.toChar())
SHORT -> const(IrConstKind.Short, value.intValue.toShort())
INT -> const(IrConstKind.Int, value.intValue.toInt())
LONG -> const(IrConstKind.Long, value.intValue)
FLOAT -> const(IrConstKind.Float, value.floatValue)
DOUBLE -> const(IrConstKind.Double, value.doubleValue)
BOOLEAN -> const(IrConstKind.Boolean, (value.intValue != 0L))
STRING -> const(IrConstKind.String, nameResolver.getString(value.stringValue))
BYTE -> const(FirConstKind.Byte, value.intValue.toByte())
CHAR -> const(FirConstKind.Char, value.intValue.toChar())
SHORT -> const(FirConstKind.Short, value.intValue.toShort())
INT -> const(FirConstKind.Int, value.intValue.toInt())
LONG -> const(FirConstKind.Long, value.intValue)
FLOAT -> const(FirConstKind.Float, value.floatValue)
DOUBLE -> const(FirConstKind.Double, value.doubleValue)
BOOLEAN -> const(FirConstKind.Boolean, (value.intValue != 0L))
STRING -> const(FirConstKind.String, nameResolver.getString(value.stringValue))
ANNOTATION -> deserializeAnnotation(value.annotation, nameResolver)
CLASS -> FirGetClassCallImpl(null).apply {
val classId = nameResolver.getClassId(value.classId)
@@ -152,5 +152,5 @@ abstract class AbstractAnnotationDeserializer(
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.UNKNOWN -> original.withNullability(nullability)
} as T
is ConeIntegerLiteralType -> this
else -> error("sealed: ${this::class}")
}
}
@@ -57,7 +57,8 @@ class FirSamResolverImpl(
is ConeClassErrorType, is ConeStubType -> null
// TODO: support those types as well
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
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.FirRegularClass
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.impl.ConeClassLikeTypeImpl
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 ConeIntegerLiteralType -> {
scopeSession.getOrBuild(
FirIntegerLiteralTypeScope.ILT_SYMBOL,
FirIntegerLiteralTypeScope.SCOPE_SESSION_KEY
) {
FirIntegerLiteralTypeScope(useSiteSession)
}
}
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.ResolutionStageRunner
import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer
import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.phasedFir
import org.jetbrains.kotlin.fir.resolve.transformers.*
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -39,6 +37,8 @@ interface BodyResolveComponents : SessionHolder {
val doubleColonExpressionResolver: FirDoubleColonExpressionResolver
val syntheticCallGenerator: FirSyntheticCallGenerator
val dataFlowAnalyzer: FirDataFlowAnalyzer
val integerLiteralTypeApproximator: IntegerLiteralTypeApproximationTransformer
val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater
val <D> AbstractFirBasedSymbol<D>.phasedFir: D where D : FirDeclaration, D : FirSymbolOwner<D>
get() = phasedFir(session, FirResolvePhase.DECLARATIONS)
@@ -6,14 +6,13 @@
package org.jetbrains.kotlin.fir.resolve.calls
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.arrayElementType
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.resolve.OverloadabilitySpecificityCallbacks
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.resolve.calls.results.isSignatureNotLessSpecific
import org.jetbrains.kotlin.resolve.calls.results.*
import org.jetbrains.kotlin.types.checker.requireOrDescribe
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
abstract class AbstractConeCallConflictResolver(
private val specificityComparator: TypeSpecificityComparator,
@@ -50,11 +49,39 @@ abstract class AbstractConeCallConflictResolver(
return createEmptyConstraintSystem().isSignatureNotLessSpecific(
call1,
call2,
OverloadabilitySpecificityCallbacks,
SpecificityComparisonWithNumerics,
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> {
return when (val declaration = call.symbol.fir) {
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.references.FirResolvedNamedReference
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.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.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
@@ -165,7 +169,15 @@ fun Candidate.resolveSubCallArgument(
isSafeCall,
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)
resolvePlainArgumentType(csBuilder, argumentType, expectedType, sink, isReceiver, isDispatch, isSafeCall)
}
@@ -183,6 +195,14 @@ fun Candidate.resolvePlainExpressionArgument(
if (expectedType == null) return
val argumentType = typeProvider(argument)?.coneTypeSafe<ConeKotlinType>() ?: return
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(
@@ -273,6 +293,7 @@ internal fun Candidate.resolveArgument(
}
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 expectedType = getExpectedTypeWithSAMConversion(session, argument, basicExpectedType) ?: basicExpectedType
return this.substitutor.substituteOrSelf(expectedType)
@@ -260,7 +260,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext,
TypeSubstitutorMarker {
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
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
}
override fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker {
TODO()
}
override fun KotlinTypeMarker.removeExactAnnotation(): KotlinTypeMarker {
// TODO
return this
@@ -314,7 +310,11 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext,
}
override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker? {
// TODO: implement
return null
return ConeIntegerLiteralTypeImpl.findCommonSuperType(explicitSupertypes)
}
override fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker {
require(this is ConeIntegerLiteralType)
return this.getApproximatedType()
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType
import org.jetbrains.kotlin.fir.returnExpressions
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
@@ -33,7 +34,8 @@ fun Candidate.computeCompletionMode(
if (expectedType != null) return KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL
// 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 {
// 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.types.*
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.Name
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -51,6 +50,8 @@ class FirDataFlowAnalyzer(private val components: FirAbstractBodyResolveTransfor
private val variablesForWhenConditions = mutableMapOf<WhenBranchConditionExitNode, DataFlowVariable>()
private var contractDescriptionVisitingMode = false
/*
* 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<*>
when {
leftConst?.kind == IrConstKind.Null -> processEqNull(node, rightOperand, operation)
rightConst?.kind == IrConstKind.Null -> processEqNull(node, leftOperand, operation)
leftConst?.kind == FirConstKind.Null -> processEqNull(node, rightOperand, operation)
rightConst?.kind == FirConstKind.Null -> processEqNull(node, leftOperand, operation)
leftConst != null -> processEqWithConst(node, rightOperand, leftConst, operation)
rightConst != null -> processEqWithConst(node, leftOperand, rightConst, operation)
operation != FirOperation.EQ && operation != FirOperation.IDENTITY -> return
@@ -248,7 +249,7 @@ class FirDataFlowAnalyzer(private val components: FirAbstractBodyResolveTransfor
// propagating facts for (... == true) and (... == false)
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 shouldInvert = isEq xor constValue
@@ -556,6 +557,7 @@ class FirDataFlowAnalyzer(private val components: FirAbstractBodyResolveTransfor
val conditionalEffects = contractDescription.effects.filterIsInstance<ConeConditionalEffectDeclaration>()
if (conditionalEffects.isEmpty()) return
val argumentsMapping = createArgumentsMapping(functionCall) ?: return
contractDescriptionVisitingMode = true
graphBuilder.enterContract(functionCall).mergeIncomingFlow()
val functionCallVariable = getOrCreateVariable(functionCall)
for (conditionalEffect in conditionalEffects) {
@@ -594,6 +596,7 @@ class FirDataFlowAnalyzer(private val components: FirAbstractBodyResolveTransfor
}
}
graphBuilder.exitContract(functionCall).mergeIncomingFlow()
contractDescriptionVisitingMode = true
}
@@ -622,6 +625,7 @@ class FirDataFlowAnalyzer(private val components: FirAbstractBodyResolveTransfor
}
fun exitConstExpresion(constExpression: FirConstExpression<*>) {
if (constExpression.resultType is FirResolvedTypeRef && !contractDescriptionVisitingMode) return
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.references.impl.FirSimpleNamedReference
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
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? {
return when (constantReference) {
ConeBooleanConstantReference.TRUE -> FirConstExpressionImpl(null, IrConstKind.Boolean, true)
ConeBooleanConstantReference.FALSE -> FirConstExpressionImpl(null, IrConstKind.Boolean, false)
ConeBooleanConstantReference.TRUE -> FirConstExpressionImpl(null, FirConstKind.Boolean, true)
ConeBooleanConstantReference.FALSE -> FirConstExpressionImpl(null, FirConstKind.Boolean, false)
ConeConstantReference.NULL -> createConstNull()
else -> null
}
@@ -71,7 +71,7 @@ private object ConeConditionalEffectToFirVisitor : ConeContractDescriptionVisito
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? {
@@ -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.impl.FirCallableSymbol
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.Name
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
@@ -47,6 +48,11 @@ class FirVariableExpectedError : FirDiagnostic() {
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 {
return when (symbol) {
is FirClassLikeSymbol<*> -> symbol.classId.asString()
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.diagnostics
import org.jetbrains.kotlin.diagnostics.Severity.*
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.psi.KtElement
import kotlin.reflect.full.memberProperties
@@ -27,6 +28,7 @@ object FirErrors {
val RECURSION_IN_IMPLICIT_TYPES = DiagnosticFactory0.create<KtElement>(ERROR)
val ERROR_FROM_JAVA_RESOLUTION = DiagnosticFactory0.create<KtElement>(ERROR)
val OTHER_ERROR = DiagnosticFactory0.create<KtElement>(ERROR)
val TYPE_MISMATCH = DiagnosticFactory2.create<KtElement, ConeKotlinType, ConeKotlinType>(ERROR)
init {
val klass = FirErrors::class
@@ -57,6 +57,7 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
is FirAmbiguityError -> FirErrors.AMBIGUITY.onSource(source, diagnostic.candidates)
is FirOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.onSource(source, diagnostic.candidates)
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 FirStubDiagnostic -> null
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.calls.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.*
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.FirBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
@@ -98,12 +96,14 @@ class FirCallCompleter(
return call.transformSingle(
FirCallCompletionResultsWriterTransformer(
session, finalSubstitutor, returnTypeCalculator,
inferenceComponents.approximator
inferenceComponents.approximator,
integerOperatorsTypeUpdater,
integerLiteralTypeApproximator
),
null
)
}
return call
return call.transformSingle(integerOperatorsTypeUpdater, null)
}
private inner class LambdaAnalyzerImpl(
@@ -70,6 +70,7 @@ abstract class AbstractConeSubstitutor : ConeSubstitutor() {
is ConeDefinitelyNotNullType -> this.substituteOriginal()
is ConeIntersectionType -> this.substituteIntersectedTypes()
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.FirNamedReferenceWithCandidate
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.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substituteOrNull
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
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.types.*
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.visitors.CompositeTransformResult
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.TypeApproximatorConfiguration
import org.jetbrains.kotlin.types.Variance
@@ -37,12 +41,14 @@ class FirCallCompletionResultsWriterTransformer(
override val session: FirSession,
private val finalSubstitutor: ConeSubstitutor,
private val typeCalculator: ReturnTypeCalculator,
private val typeApproximator: AbstractTypeApproximator
) : FirAbstractTreeTransformer<Nothing?>(phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) {
private val typeApproximator: AbstractTypeApproximator,
private val integerOperatorsTypeUpdater: IntegerOperatorsTypeUpdater,
private val integerApproximator: IntegerLiteralTypeApproximationTransformer
) : FirAbstractTreeTransformer<ExpectedArgumentType?>(phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) {
override fun transformQualifiedAccessExpression(
qualifiedAccessExpression: FirQualifiedAccessExpression,
data: Nothing?
data: ExpectedArgumentType?
): CompositeTransformResult<FirStatement> {
val calleeReference =
qualifiedAccessExpression.calleeReference as? FirNamedReferenceWithCandidate ?: return qualifiedAccessExpression.compose()
@@ -92,9 +98,8 @@ class FirCallCompletionResultsWriterTransformer(
override fun transformCallableReferenceAccess(
callableReferenceAccess: FirCallableReferenceAccess,
data: Nothing?
data: ExpectedArgumentType?
): CompositeTransformResult<FirStatement> {
val calleeReference =
callableReferenceAccess.calleeReference as? FirNamedReferenceWithCandidate ?: return callableReferenceAccess.compose()
@@ -120,7 +125,7 @@ class FirCallCompletionResultsWriterTransformer(
override fun transformVariableAssignment(
variableAssignment: FirVariableAssignment,
data: Nothing?
data: ExpectedArgumentType?
): CompositeTransformResult<FirStatement> {
val calleeReference = variableAssignment.calleeReference as? FirNamedReferenceWithCandidate
?: return variableAssignment.compose()
@@ -134,9 +139,8 @@ class FirCallCompletionResultsWriterTransformer(
).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 functionCall = functionCall.transformArguments(this, data) as FirFunctionCall
val subCandidate = calleeReference.candidate
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,
typeArguments = typeArguments,
calleeReference = FirResolvedNamedReferenceImpl(
calleeReference.source,
calleeReference.name,
calleeReference.candidateSymbol
),
dispatchReceiver = subCandidate.dispatchReceiverExpression(),
extensionReceiver = subCandidate.extensionReceiverExpression()
typeArguments = typeArguments
).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(
delegatedConstructorCall: FirDelegatedConstructorCall,
data: Nothing?
data: ExpectedArgumentType?
): CompositeTransformResult<FirStatement> {
val calleeReference = delegatedConstructorCall.calleeReference as? FirNamedReferenceWithCandidate ?: return delegatedConstructorCall.compose()
val subCandidate = calleeReference.candidate
val result = delegatedConstructorCall.transformArguments(this, data)
return result.transformCalleeReference(StoreCalleeReference, FirResolvedNamedReferenceImpl(
calleeReference.source,
calleeReference.name,
calleeReference.candidateSymbol
)).compose()
val result = delegatedConstructorCall.transformArguments(this, calleeReference.candidate.createArgumentsMapping())
return result.transformCalleeReference(
StoreCalleeReference,
FirResolvedNamedReferenceImpl(
calleeReference.source,
calleeReference.name,
calleeReference.candidateSymbol
)
).compose()
}
private fun computeTypeArguments(
@@ -213,11 +244,15 @@ class FirCallCompletionResultsWriterTransformer(
override fun transformAnonymousFunction(
anonymousFunction: FirAnonymousFunction,
data: Nothing?
data: ExpectedArgumentType?
): CompositeTransformResult<FirStatement> {
val expectedReturnType = data?.getExpectedType(anonymousFunction)
?.takeIf { it.isBuiltinFunctionalType }
?.let { it.typeArguments.last() as? ConeClassLikeType }
val initialType = anonymousFunction.returnTypeRef.coneTypeSafe<ConeKotlinType>()
if (initialType != null) {
val finalType = finalSubstitutor.substituteOrNull(initialType)
val finalType = expectedReturnType ?: finalSubstitutor.substituteOrNull(initialType)
val resultType = anonymousFunction.returnTypeRef.withReplacedConeType(finalType)
@@ -225,23 +260,26 @@ class FirCallCompletionResultsWriterTransformer(
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>()
if (initialType != null) {
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)
}
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 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()
@@ -261,7 +299,7 @@ class FirCallCompletionResultsWriterTransformer(
).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 tryExpression = tryExpression.transformChildren(this, data) as FirTryExpression
@@ -281,6 +319,40 @@ class FirCallCompletionResultsWriterTransformer(
calleeReference.candidateSymbol
)
).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 scopeSession: ScopeSession get() = components.scopeSession
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?
get() = when (this) {
@@ -122,7 +125,9 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
val callCompleter: FirCallCompleter = FirCallCompleter(transformer, this)
override val dataFlowAnalyzer: FirDataFlowAnalyzer = FirDataFlowAnalyzer(this)
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
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.transformers.FirSyntheticCallGenerator
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.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.types.ConeKotlinType
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.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.compose
@@ -168,9 +171,13 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
// ------------------------------- Jumps -------------------------------
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)
return result
return result.compose()
}
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.extractLambdaInfoFromFunctionalType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.ControlFlowGraphReferenceTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.*
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.transformVarargTypeToArrayType
@@ -104,6 +103,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
localScopes.addIfNotNull(primaryConstructorParametersScope)
components.withContainer(property) {
property.transformChildrenWithoutAccessors(returnTypeRef)
property.transformInitializer(integerLiteralTypeApproximator, null)
if (property.initializer != null) {
storeVariableReturnType(property)
}
@@ -125,7 +125,10 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
private fun transformLocalVariable(variable: FirProperty): CompositeTransformResult<FirDeclaration> {
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) {
storeVariableReturnType(variable)
}
@@ -138,7 +141,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
private fun FirProperty.transformChildrenWithoutAccessors(returnTypeRef: FirTypeRef): FirProperty {
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() {
@@ -380,6 +383,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
valueParameter.replaceResolvePhase(transformerPhase)
return valueParameter.compose() // TODO
}
val valueParameter = valueParameter.transformInitializer(integerLiteralTypeApproximator, valueParameter.returnTypeRef.coneTypeSafe())
return (transformDeclaration(valueParameter, withExpectedType(valueParameter.returnTypeRef)).single as FirStatement).compose()
}
@@ -464,9 +468,11 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
session,
ConeSubstitutor.Empty,
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() }
af.replaceReturnTypeRef(af.returnTypeRef.resolvedTypeFromPrototype(inferenceComponents.ctx.commonSuperTypeOrNull(returnTypes) ?: session.builtinTypes.unitType.coneTypeUnsafe()))
af.replaceTypeRef(af.constructFunctionalTypeRef(session))
@@ -5,10 +5,11 @@
package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
import org.jetbrains.kotlin.fir.BuiltinTypes
import org.jetbrains.kotlin.fir.FirCallResolver
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirTypeParametersOwner
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.expressions.*
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.FirExplicitThisReference
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.calls.candidate
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.transformers.IntegerLiteralTypeApproximationTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer
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.symbols.StandardClassIds
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.compose
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.Name
import org.jetbrains.kotlin.types.Variance
@@ -192,9 +192,10 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
override fun transformOperatorCall(operatorCall: FirOperatorCall, data: ResolutionMode): CompositeTransformResult<FirStatement> {
if (operatorCall.operation in FirOperation.BOOLEANS) {
// TODO: add approximation of integer literals
val result = (operatorCall.transformChildren(transformer, ResolutionMode.ContextIndependent) as FirOperatorCall).also {
it.resultType = operatorCall.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type)
}
}.transformSingle(integerLiteralTypeApproximator, null)
dataFlowAnalyzer.exitOperatorCall(result)
return result.compose()
}
@@ -259,8 +260,9 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
data: ResolutionMode
): CompositeTransformResult<FirStatement> {
val symbolProvider = session.firSymbolProvider
val resolved = transformExpression(typeOperatorCall, data).single
when ((resolved as FirTypeOperatorCall).operation) {
val resolved = (transformExpression(typeOperatorCall, data).single as FirTypeOperatorCall)
.transformArguments(integerLiteralTypeApproximator, null)
when (resolved.operation) {
FirOperation.IS, FirOperation.NOT_IS -> {
resolved.resultType = FirResolvedTypeRefImpl(
null,
@@ -279,7 +281,7 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
else -> error("Unknown type operator")
}
dataFlowAnalyzer.exitTypeOperatorCall(typeOperatorCall)
return resolved.compose()
return resolved.transform(integerLiteralTypeApproximator, null)
}
override fun transformBinaryLogicExpression(
@@ -313,6 +315,7 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
val completeAssignment = callCompleter.completeCall(resolvedAssignment, noExpectedType) // TODO: check
val expectedType = components.typeFromCallee(completeAssignment)
completeAssignment.transformRValue(transformer, withExpectedType(expectedType))
.transformRValue(integerLiteralTypeApproximator, expectedType.coneTypeSafe())
} else {
// This can happen in erroneous code only
resolvedAssignment
@@ -396,36 +399,57 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
}
override fun <T> transformConstExpression(constExpression: FirConstExpression<T>, data: ResolutionMode): CompositeTransformResult<FirStatement> {
// TODO: add support of IntegerLiteralType
constExpression.annotations.forEach { it.accept(this, data) }
val kind = constExpression.kind
val symbol = when (kind) {
IrConstKind.Null -> StandardClassIds.Nothing(symbolProvider)
IrConstKind.Boolean -> StandardClassIds.Boolean(symbolProvider)
IrConstKind.Char -> StandardClassIds.Char(symbolProvider)
IrConstKind.Byte -> StandardClassIds.Byte(symbolProvider)
IrConstKind.Short -> StandardClassIds.Short(symbolProvider)
IrConstKind.Int -> StandardClassIds.Int(symbolProvider)
IrConstKind.Long -> StandardClassIds.Long(symbolProvider)
IrConstKind.String -> StandardClassIds.String(symbolProvider)
IrConstKind.Float -> StandardClassIds.Float(symbolProvider)
IrConstKind.Double -> StandardClassIds.Double(symbolProvider)
FirConstKind.Null -> StandardClassIds.Nothing(symbolProvider)
FirConstKind.Boolean -> StandardClassIds.Boolean(symbolProvider)
FirConstKind.Char -> StandardClassIds.Char(symbolProvider)
FirConstKind.Byte -> StandardClassIds.Byte(symbolProvider)
FirConstKind.Short -> StandardClassIds.Short(symbolProvider)
FirConstKind.Int -> StandardClassIds.Int(symbolProvider)
FirConstKind.Long -> StandardClassIds.Long(symbolProvider)
FirConstKind.String -> StandardClassIds.String(symbolProvider)
FirConstKind.Float -> StandardClassIds.Float(symbolProvider)
FirConstKind.Double -> StandardClassIds.Double(symbolProvider)
FirConstKind.IntegerLiteral -> null
}
val type = ConeClassLikeTypeImpl(symbol.toLookupTag(), emptyArray(), isNullable = kind == IrConstKind.Null)
constExpression.resultType = FirResolvedTypeRefImpl(null, type)
val type = if (symbol != null) {
ConeClassLikeTypeImpl(symbol.toLookupTag(), emptyArray(), isNullable = kind == FirConstKind.Null)
} 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<*>)
constExpression.resultType = constExpression.resultType.resolvedTypeFromPrototype(type)
return constExpression.compose()
}
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: ResolutionMode): CompositeTransformResult<FirStatement> {
dataFlowAnalyzer.enterAnnotationCall(annotationCall)
return (annotationCall.transformChildren(transformer, data) as FirAnnotationCall).also {
dataFlowAnalyzer.exitAnnotationCall(it)
}.compose()
return (annotationCall.transformChildren(transformer, data) as FirAnnotationCall)
// TODO: it's temporary incorrect solution until we design resolve and completion for annotation calls
.transformArguments(integerLiteralTypeApproximator, null).also {
dataFlowAnalyzer.exitAnnotationCall(it)
}.compose()
}
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
override fun TypeConstructorMarker.isIntegerLiteralTypeConstructor(): Boolean {
// TODO()
return false
return this is ConeIntegerLiteralType
}
override fun SimpleTypeMarker.possibleIntegerTypes(): Collection<KotlinTypeMarker> {
TODO("not implemented")
return (this as? ConeIntegerLiteralType)?.possibleTypes ?: emptyList()
}
override fun SimpleTypeMarker.fastCorrespondingSupertypes(constructor: TypeConstructorMarker): List<SimpleTypeMarker>? {
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 {
return false
return this is ConeIntegerLiteralType
}
override fun KotlinTypeMarker.asSimpleType(): SimpleTypeMarker? {
@@ -65,6 +68,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is ConeIntersectionType -> this
is ConeFlexibleType -> null
is ConeStubType -> this
is ConeIntegerLiteralType -> this
else -> error("Unknown simpleType: $this")
}
}
@@ -134,6 +138,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is ConeIntersectionType -> this
is ConeStubType -> variable.typeConstructor
is ConeDefinitelyNotNullType -> original.typeConstructor()
is ConeIntegerLiteralType -> this
else -> error("?: $this")
}
}
@@ -210,6 +215,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is ConeIntersectionType -> 0
is FirRegularClassSymbol -> fir.typeParameters.size
is FirTypeAliasSymbol -> fir.typeParameters.size
is ConeIntegerLiteralType -> 0
else -> error("?!:10")
}
}
@@ -234,6 +240,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is FirTypeAliasSymbol -> listOfNotNull(fir.expandedConeType)
is ConeCapturedTypeConstructor -> supertypes!!
is ConeIntersectionType -> intersectedTypes
is ConeIntegerLiteralType -> supertypes
else -> error("?!:13")
}
}
@@ -280,7 +287,8 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
return when (this) {
is ConeCapturedTypeConstructor,
is ConeTypeVariableTypeConstructor,
is ConeIntersectionType -> false
is ConeIntersectionType,
is ConeIntegerLiteralType -> false
is AbstractFirBasedSymbol<*> -> true
else -> true
}
@@ -363,6 +371,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
if (this is ConeCapturedType) return true
if (this is ConeTypeVariableType) return false
if (this is ConeIntersectionType) return false
if (this is ConeIntegerLiteralType) return true
if (this is ConeStubType) return true
if (this is ConeDefinitelyNotNullType) return true
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 {
color=blue
12 [label="Enter block"];
13 [label="Const: Int(1)"];
13 [label="Const: IntegerLiteral(1)"];
14 [label="Exit block"];
}
15 [label="Exit when branch result"];
@@ -80,7 +80,7 @@ digraph binaryOperations_kt {
subgraph cluster_9 {
color=blue
30 [label="Enter block"];
31 [label="Const: Int(1)"];
31 [label="Const: IntegerLiteral(1)"];
32 [label="Exit block"];
}
33 [label="Exit when branch result"];
@@ -140,7 +140,7 @@ digraph binaryOperations_kt {
subgraph cluster_15 {
color=blue
53 [label="Enter block"];
54 [label="Const: Int(1)"];
54 [label="Const: IntegerLiteral(1)"];
55 [label="Exit block"];
}
56 [label="Exit when branch result"];
@@ -205,7 +205,7 @@ digraph binaryOperations_kt {
subgraph cluster_21 {
color=blue
76 [label="Enter block"];
77 [label="Const: Int(1)"];
77 [label="Const: IntegerLiteral(1)"];
78 [label="Exit block"];
}
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| {
when () {
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| {
when () {
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| {
when () {
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| {
when () {
R|<local>/b1| || R|<local>/b2| && R|<local>/b3| -> {
Int(1)
IntegerLiteral(1)
}
}
@@ -28,7 +28,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_4 {
color=blue
12 [label="Enter block"];
13 [label="Const: Int(1)"];
13 [label="Const: IntegerLiteral(1)"];
14 [label="Exit block"];
}
15 [label="Exit when branch result"];
@@ -81,7 +81,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_9 {
color=blue
31 [label="Enter block"];
32 [label="Const: Int(1)"];
32 [label="Const: IntegerLiteral(1)"];
33 [label="Exit block"];
}
34 [label="Exit when branch result"];
@@ -135,7 +135,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_14 {
color=blue
49 [label="Enter block"];
50 [label="Const: Int(1)"];
50 [label="Const: IntegerLiteral(1)"];
51 [label="Exit block"];
}
52 [label="Exit when branch result"];
@@ -188,7 +188,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_19 {
color=blue
68 [label="Enter block"];
69 [label="Const: Int(1)"];
69 [label="Const: IntegerLiteral(1)"];
70 [label="Exit block"];
}
71 [label="Exit when branch result"];
@@ -242,7 +242,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_24 {
color=blue
86 [label="Enter block"];
87 [label="Const: Int(1)"];
87 [label="Const: IntegerLiteral(1)"];
88 [label="Exit block"];
}
89 [label="Exit when branch result"];
@@ -295,7 +295,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_29 {
color=blue
105 [label="Enter block"];
106 [label="Const: Int(1)"];
106 [label="Const: IntegerLiteral(1)"];
107 [label="Exit block"];
}
108 [label="Exit when branch result"];
@@ -349,7 +349,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_34 {
color=blue
123 [label="Enter block"];
124 [label="Const: Int(1)"];
124 [label="Const: IntegerLiteral(1)"];
125 [label="Exit block"];
}
126 [label="Exit when branch result"];
@@ -402,7 +402,7 @@ digraph booleanOperatorsWithConsts_kt {
subgraph cluster_39 {
color=blue
142 [label="Enter block"];
143 [label="Const: Int(1)"];
143 [label="Const: IntegerLiteral(1)"];
144 [label="Exit block"];
}
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| {
when () {
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| {
when () {
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| {
when () {
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| {
when () {
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| {
when () {
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| {
when () {
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| {
when () {
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| {
when () {
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|"];
15 [label="Access variable 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|)
}
)"];
@@ -44,44 +44,42 @@ digraph complex_kt {
21 [label="Enter block"];
22 [label="Const: String(Can't parse json response)"];
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|"];
26 [label="Const: String(Can't parse json response)"];
27 [label="Access variable R|<local>/syntaxException|"];
28 [label="Function call: <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|)"];
29 [label="Throw: throw <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|)"];
30 [label="Stub" style="filled" fillcolor=gray];
31 [label="Exit block" style="filled" fillcolor=gray];
26 [label="Function call: <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|)"];
27 [label="Throw: throw <Unresolved name: ResponseParseException>#(String(Can't parse json response), R|<local>/syntaxException|)"];
28 [label="Stub" style="filled" fillcolor=gray];
29 [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 {
color=blue
33 [label="Catch enter"];
31 [label="Catch enter"];
subgraph cluster_7 {
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|"];
36 [label="Access variable R|<local>/ioException|"];
37 [label="Access variable R|<local>/ioException|"];
38 [label="Function call: <Unresolved name: IOException>#(R|<local>/ioException|)"];
39 [label="Throw: throw <Unresolved name: IOException>#(R|<local>/ioException|)"];
40 [label="Stub" style="filled" fillcolor=gray];
41 [label="Exit block" style="filled" fillcolor=gray];
36 [label="Function call: <Unresolved name: IOException>#(R|<local>/ioException|)"];
37 [label="Throw: throw <Unresolved name: IOException>#(R|<local>/ioException|)"];
38 [label="Stub" style="filled" fillcolor=gray];
39 [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`>|"];
45 [label="Exit function fetchPluginReleaseDate" style="filled" fillcolor=red];
42 [label="Variable declaration: lval pluginDTOs: R|kotlin/Array<class error: Symbol not found, for `PluginDTO`>|"];
43 [label="Exit function fetchPluginReleaseDate" style="filled" fillcolor=red];
}
subgraph cluster_8 {
color=blue
46 [label="Enter annotation"];
47 [label="Access variable <Unresolved name: IOException>#"];
48 [label="Access variable <Unresolved name: ResponseParseException>#"];
49 [label="Exit annotation"];
44 [label="Enter annotation"];
45 [label="Access variable <Unresolved name: IOException>#"];
46 [label="Access variable <Unresolved name: ResponseParseException>#"];
47 [label="Exit annotation"];
}
0 -> {1};
@@ -94,7 +92,7 @@ digraph complex_kt {
7 -> {8};
8 -> {9};
9 -> {10};
10 -> {45 33 20 11};
10 -> {43 31 20 11};
11 -> {12};
12 -> {13};
13 -> {14};
@@ -103,54 +101,54 @@ digraph complex_kt {
16 -> {17};
17 -> {18};
18 -> {19};
19 -> {43};
20 -> {45 21};
19 -> {41};
20 -> {43 21};
21 -> {22};
22 -> {23};
23 -> {24};
24 -> {25};
25 -> {26};
26 -> {27};
27 -> {28};
28 -> {29};
29 -> {45};
27 -> {43};
27 -> {28} [style=dotted];
28 -> {29} [style=dotted];
29 -> {30} [style=dotted];
30 -> {31} [style=dotted];
31 -> {32} [style=dotted];
32 -> {43} [style=dotted];
33 -> {45 34};
30 -> {41} [style=dotted];
31 -> {43 32};
32 -> {33};
33 -> {34};
34 -> {35};
35 -> {36};
36 -> {37};
37 -> {38};
38 -> {39};
39 -> {45};
37 -> {43};
37 -> {38} [style=dotted];
38 -> {39} [style=dotted];
39 -> {40} [style=dotted];
40 -> {41} [style=dotted];
41 -> {42} [style=dotted];
42 -> {43} [style=dotted];
41 -> {42};
42 -> {43};
43 -> {44};
44 -> {45};
45 -> {46};
46 -> {47};
47 -> {48};
48 -> {49};
subgraph cluster_9 {
color=red
50 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
51 [label="Function call: <Unresolved name: GsonBuilder>#()"];
52 [label="Function call: <Unresolved name: GsonBuilder>#().<Unresolved name: create>#()"];
53 [label="Access variable <Unresolved name: it>#"];
54 [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]>#()"];
48 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
49 [label="Function call: <Unresolved name: GsonBuilder>#()"];
50 [label="Function call: <Unresolved name: GsonBuilder>#().<Unresolved name: create>#()"];
51 [label="Access variable <Unresolved name: it>#"];
52 [label="Access variable <Unresolved name: inputStream>#"];
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|"];
57 [label="Access variable R|kotlin/jvm/java|"];
58 [label="Access variable R|kotlin/jvm/java|"];
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];
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="Exit function anonymousFunction" style="filled" fillcolor=red];
}
48 -> {49};
49 -> {50};
50 -> {51};
51 -> {52};
52 -> {53};
@@ -159,98 +157,96 @@ digraph complex_kt {
55 -> {56};
56 -> {57};
57 -> {58};
58 -> {59};
59 -> {60};
subgraph cluster_10 {
color=red
61 [label="Enter function close" style="filled" fillcolor=red];
62 [label="Exit function close" style="filled" fillcolor=red];
59 [label="Enter function close" style="filled" fillcolor=red];
60 [label="Exit function close" style="filled" fillcolor=red];
}
61 -> {62};
59 -> {60};
subgraph cluster_11 {
color=red
63 [label="Enter function closeFinally" style="filled" fillcolor=red];
61 [label="Enter function closeFinally" style="filled" fillcolor=red];
subgraph cluster_12 {
color=blue
64 [label="Enter when"];
62 [label="Enter when"];
subgraph cluster_13 {
color=blue
65 [label="Enter when branch condition "];
66 [label="Access variable this@R|/closeFinally|"];
67 [label="Const: Null(null)"];
68 [label="Operator =="];
69 [label="Exit when branch condition"];
63 [label="Enter when branch condition "];
64 [label="Access variable this@R|/closeFinally|"];
65 [label="Const: Null(null)"];
66 [label="Operator =="];
67 [label="Exit when branch condition"];
}
subgraph cluster_14 {
color=blue
70 [label="Enter when branch condition "];
71 [label="Access variable R|<local>/cause|"];
72 [label="Const: Null(null)"];
73 [label="Operator =="];
74 [label="Exit when branch condition"];
68 [label="Enter when branch condition "];
69 [label="Access variable R|<local>/cause|"];
70 [label="Const: Null(null)"];
71 [label="Operator =="];
72 [label="Exit when branch condition"];
}
subgraph cluster_15 {
color=blue
75 [label="Enter when branch condition else"];
76 [label="Exit when branch condition"];
73 [label="Enter when branch condition else"];
74 [label="Exit when branch condition"];
}
77 [label="Enter when branch result"];
75 [label="Enter when branch result"];
subgraph cluster_16 {
color=blue
78 [label="Enter block"];
76 [label="Enter block"];
subgraph cluster_17 {
color=blue
79 [label="Try expression enter"];
77 [label="Try expression enter"];
subgraph cluster_18 {
color=blue
80 [label="Try main block enter"];
78 [label="Try main block enter"];
subgraph cluster_19 {
color=blue
81 [label="Enter block"];
82 [label="Function call: this@R|/AutoCloseable|.R|/AutoCloseable.close|()"];
83 [label="Exit block"];
79 [label="Enter block"];
80 [label="Function call: this@R|/AutoCloseable|.R|/AutoCloseable.close|()"];
81 [label="Exit block"];
}
84 [label="Try main block exit"];
82 [label="Try main block exit"];
}
subgraph cluster_20 {
color=blue
85 [label="Catch enter"];
83 [label="Catch enter"];
subgraph cluster_21 {
color=blue
86 [label="Enter block"];
87 [label="Access variable R|<local>/cause|"];
88 [label="Access variable R|<local>/closeException|"];
89 [label="Function call: R|<local>/cause|.R|kotlin/addSuppressed|(R|<local>/closeException|)"];
90 [label="Exit block"];
84 [label="Enter block"];
85 [label="Access variable R|<local>/cause|"];
86 [label="Access variable R|<local>/closeException|"];
87 [label="Function call: R|<local>/cause|.R|kotlin/addSuppressed|(R|<local>/closeException|)"];
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"];
95 [label="Enter when branch result"];
92 [label="Exit when branch result"];
93 [label="Enter when branch result"];
subgraph cluster_22 {
color=blue
96 [label="Enter block"];
97 [label="Function call: this@R|/AutoCloseable|.R|/AutoCloseable.close|()"];
98 [label="Exit block"];
94 [label="Enter block"];
95 [label="Function call: this@R|/AutoCloseable|.R|/AutoCloseable.close|()"];
96 [label="Exit block"];
}
99 [label="Exit when branch result"];
100 [label="Enter when branch result"];
97 [label="Exit when branch result"];
98 [label="Enter when branch result"];
subgraph cluster_23 {
color=blue
101 [label="Enter block"];
102 [label="Exit block"];
99 [label="Enter block"];
100 [label="Exit block"];
}
103 [label="Exit when branch result"];
104 [label="Exit when"];
101 [label="Exit when branch result"];
102 [label="Exit when"];
}
105 [label="Jump: ^closeFinally when () {
103 [label="Jump: ^closeFinally when () {
==(this@R|/closeFinally|, Null(null)) -> {
}
==(R|<local>/cause|, Null(null)) -> {
@@ -267,118 +263,120 @@ digraph complex_kt {
}
}
"];
106 [label="Stub" style="filled" fillcolor=gray];
107 [label="Exit function closeFinally" style="filled" fillcolor=red];
104 [label="Stub" style="filled" fillcolor=gray];
105 [label="Exit function closeFinally" style="filled" fillcolor=red];
}
61 -> {62};
62 -> {63};
63 -> {64};
64 -> {65};
65 -> {66};
66 -> {67};
67 -> {68};
67 -> {98 68};
68 -> {69};
69 -> {100 70};
69 -> {70};
70 -> {71};
71 -> {72};
72 -> {73};
72 -> {93 73};
73 -> {74};
74 -> {95 75};
74 -> {75};
75 -> {76};
76 -> {77};
77 -> {78};
78 -> {79};
78 -> {105 83 79};
79 -> {80};
80 -> {107 85 81};
80 -> {81};
81 -> {82};
82 -> {83};
83 -> {84};
84 -> {92};
85 -> {107 86};
82 -> {90};
83 -> {105 84};
84 -> {85};
85 -> {86};
86 -> {87};
87 -> {88};
88 -> {89};
89 -> {90};
90 -> {91};
91 -> {92};
92 -> {93};
92 -> {102};
93 -> {94};
94 -> {104};
94 -> {95};
95 -> {96};
96 -> {97};
97 -> {98};
97 -> {102};
98 -> {99};
99 -> {104};
99 -> {100};
100 -> {101};
101 -> {102};
102 -> {103};
103 -> {104};
104 -> {105};
105 -> {107};
105 -> {106} [style=dotted];
106 -> {107} [style=dotted];
103 -> {105};
103 -> {104} [style=dotted];
104 -> {105} [style=dotted];
subgraph cluster_24 {
color=red
108 [label="Enter function firstIsInstanceOrNull" style="filled" fillcolor=red];
109 [label="Access variable this@R|/firstIsInstanceOrNull|"];
110 [label="Variable declaration: lval <range>: R|kotlin/sequences/Sequence<*>|"];
111 [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?>|>|()"];
113 [label="Variable declaration: lval <iterator>: R|kotlin/collections/Iterator<kotlin/Any?>|"];
106 [label="Enter function firstIsInstanceOrNull" style="filled" fillcolor=red];
107 [label="Access variable this@R|/firstIsInstanceOrNull|"];
108 [label="Variable declaration: lval <range>: R|kotlin/sequences/Sequence<*>|"];
109 [label="Access variable R|<local>/<range>|"];
110 [label="Function call: R|<local>/<range>|.R|FakeOverride<kotlin/sequences/Sequence.iterator: R|kotlin/collections/Iterator<kotlin/Any?>|>|()"];
111 [label="Variable declaration: lval <iterator>: R|kotlin/collections/Iterator<kotlin/Any?>|"];
subgraph cluster_25 {
color=blue
114 [label="Enter while loop"];
112 [label="Enter while loop"];
subgraph cluster_26 {
color=blue
115 [label="Enter loop condition"];
116 [label="Access variable R|<local>/<iterator>|"];
117 [label="Function call: R|<local>/<iterator>|.R|kotlin/collections/Iterator.hasNext|()"];
118 [label="Exit loop condition"];
113 [label="Enter loop condition"];
114 [label="Access variable R|<local>/<iterator>|"];
115 [label="Function call: R|<local>/<iterator>|.R|kotlin/collections/Iterator.hasNext|()"];
116 [label="Exit loop condition"];
}
subgraph cluster_27 {
color=blue
119 [label="Enter loop block"];
117 [label="Enter loop block"];
subgraph cluster_28 {
color=blue
120 [label="Enter block"];
121 [label="Access variable R|<local>/<iterator>|"];
122 [label="Function call: R|<local>/<iterator>|.R|FakeOverride<kotlin/collections/Iterator.next: R|kotlin/Any?|>|()"];
123 [label="Variable declaration: lval element: R|kotlin/Any?|"];
118 [label="Enter block"];
119 [label="Access variable R|<local>/<iterator>|"];
120 [label="Function call: R|<local>/<iterator>|.R|FakeOverride<kotlin/collections/Iterator.next: R|kotlin/Any?|>|()"];
121 [label="Variable declaration: lval element: R|kotlin/Any?|"];
subgraph cluster_29 {
color=blue
124 [label="Enter when"];
122 [label="Enter when"];
subgraph cluster_30 {
color=blue
125 [label="Enter when branch condition "];
126 [label="Access variable R|<local>/element|"];
127 [label="Type operator: element is T"];
128 [label="Exit when branch condition"];
123 [label="Enter when branch condition "];
124 [label="Access variable R|<local>/element|"];
125 [label="Type operator: element is T"];
126 [label="Exit when branch condition"];
}
129 [label="Synthetic else branch"];
130 [label="Enter when branch result"];
127 [label="Synthetic else branch"];
128 [label="Enter when branch result"];
subgraph cluster_31 {
color=blue
131 [label="Enter block"];
132 [label="Access variable R|<local>/element|"];
133 [label="Jump: ^firstIsInstanceOrNull R|<local>/element|"];
134 [label="Stub" style="filled" fillcolor=gray];
135 [label="Exit block" style="filled" fillcolor=gray];
129 [label="Enter block"];
130 [label="Access variable R|<local>/element|"];
131 [label="Jump: ^firstIsInstanceOrNull R|<local>/element|"];
132 [label="Stub" style="filled" fillcolor=gray];
133 [label="Exit block" style="filled" fillcolor=gray];
}
136 [label="Exit when branch result" style="filled" fillcolor=gray];
137 [label="Exit when"];
134 [label="Exit when branch result" style="filled" fillcolor=gray];
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)"];
142 [label="Jump: ^firstIsInstanceOrNull Null(null)"];
143 [label="Stub" style="filled" fillcolor=gray];
144 [label="Exit function firstIsInstanceOrNull" style="filled" fillcolor=red];
139 [label="Const: Null(null)"];
140 [label="Jump: ^firstIsInstanceOrNull Null(null)"];
141 [label="Stub" style="filled" fillcolor=gray];
142 [label="Exit function firstIsInstanceOrNull" style="filled" fillcolor=red];
}
106 -> {107};
107 -> {108};
108 -> {109};
109 -> {110};
110 -> {111};
@@ -387,9 +385,9 @@ digraph complex_kt {
113 -> {114};
114 -> {115};
115 -> {116};
116 -> {117};
116 -> {138 117};
117 -> {118};
118 -> {140 119};
118 -> {119};
119 -> {120};
120 -> {121};
121 -> {122};
@@ -397,25 +395,23 @@ digraph complex_kt {
123 -> {124};
124 -> {125};
125 -> {126};
126 -> {127};
127 -> {128};
128 -> {130 129};
129 -> {137};
126 -> {128 127};
127 -> {135};
128 -> {129};
129 -> {130};
130 -> {131};
131 -> {132};
132 -> {133};
133 -> {144};
131 -> {142};
131 -> {132} [style=dotted];
132 -> {133} [style=dotted];
133 -> {134} [style=dotted];
134 -> {135} [style=dotted];
135 -> {136} [style=dotted];
136 -> {137} [style=dotted];
137 -> {138};
135 -> {136};
136 -> {137};
137 -> {113};
138 -> {139};
139 -> {115};
140 -> {141};
141 -> {142};
142 -> {144};
142 -> {143} [style=dotted];
143 -> {144} [style=dotted];
139 -> {140};
140 -> {142};
140 -> {141} [style=dotted];
141 -> {142} [style=dotted];
}
@@ -190,7 +190,7 @@ digraph propertiesAndInitBlocks_kt {
subgraph cluster_18 {
color=blue
53 [label="Enter block"];
54 [label="Const: Int(0)"];
54 [label="Const: IntegerLiteral(0)"];
55 [label="Exit block"];
}
56 [label="Exit finally"];
@@ -52,7 +52,7 @@ FILE: propertiesAndInitBlocks.kt
Int(2)
}
finally {
Int(0)
IntegerLiteral(0)
}
public get(): R|kotlin/Int|
@@ -50,7 +50,7 @@ digraph returnValuesFromLambda_kt {
19 [label="Function call: R|/C.C|()"];
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 () {
R|<local>/b| -> {
^@run R|/B.B|()
@@ -124,7 +124,7 @@ digraph returnValuesFromLambda_kt {
36 [label="Stub" 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
}
)" style="filled" fillcolor=gray];
@@ -14,7 +14,7 @@ FILE: returnValuesFromLambda.kt
}
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 () {
R|<local>/b| -> {
^@run R|/B.B|()
@@ -32,7 +32,7 @@ FILE: returnValuesFromLambda.kt
)
}
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
}
)
@@ -14,3 +14,14 @@ class B3_1 : <!AMBIGUITY!>A3<!>("")
class B3_2 : A3("", "asas")
class B3_3 : A3("", true)
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| {
lval x: R|kotlin/Unit| = when (R|<local>/b|) {
==($subj$, Boolean(true)) -> {
Int(1)
IntegerLiteral(1)
}
}
+1 -1
View File
@@ -33,7 +33,7 @@ class TestProperty {
return intConst + 1
}
}
1
return 1
}
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| {
@@ -69,9 +69,9 @@ FILE: main.kt
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| {
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|
@@ -199,7 +199,7 @@ digraph safeCalls_kt {
73 [label="Stub" 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
}
)" style="filled" fillcolor=gray];
@@ -207,7 +207,7 @@ digraph safeCalls_kt {
77 [label="Enter safe call" 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];
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
}
)?.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 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
}
)?.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| {
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|A|, R|kotlin/Int|>(R|<local>/a|, <L> = with@fun R|A|.<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/Int| <kind=EXACTLY_ONCE> {
this@R|/A|.R|/A.foo|()
(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|B|, R|kotlin/Int|>(R|<local>/b|, <L> = with@fun R|B|.<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/Int| <kind=EXACTLY_ONCE> {
this@R|/B|.R|/B.foo|()
(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
k.getImpl().nestedI(vInt)
k.getNestedSubClass().<!INAPPLICABLE_CANDIDATE!>nested<!>("")
k.getNestedSubClass().<!INAPPLICABLE_CANDIDATE!>nested<!>(1)
k.getNestedSubClass().nested(1)
}
// 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>/vInt|)
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
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| {
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|IFoo|, R|kotlin/Int|>(R|<local>/fooImpl|, <L> = with@fun R|IFoo|.<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/Int| <kind=EXACTLY_ONCE> {
(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|()
}
)
@@ -8,7 +8,7 @@ FILE: tryWithLambdaInside.kt
public final fun bar(): R|kotlin/collections/List<kotlin/String>| {
^bar try {
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");
}
@TestMetadata("integerLiteralTypes.kt")
public void testIntegerLiteralTypes() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/integerLiteralTypes.kt");
}
@TestMetadata("invoke.kt")
public void testInvoke() throws Exception {
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");
}
@TestMetadata("operatorsOverLiterals.kt")
public void testOperatorsOverLiterals() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/operatorsOverLiterals.kt");
}
@TestMetadata("overloadByReceiver.kt")
public void testOverloadByReceiver() throws Exception {
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");
}
@TestMetadata("rangeTo.kt")
public void testRangeTo() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/rangeTo.kt");
}
@TestMetadata("recursiveBug.kt")
public void testRecursiveBug() throws Exception {
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> transformInitializer(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
@@ -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> transformInitializer(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
@@ -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> transformInitializer(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
@@ -44,6 +44,8 @@ interface FirVariable<F : FirVariable<F>> : FirCallableDeclaration<F>, FirNamedD
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> transformSetter(transformer: FirTransformer<D>, data: D): FirVariable<F>
@@ -65,6 +65,7 @@ class FirDefaultSetterValueParameter(
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirDefaultSetterValueParameter {
transformReturnTypeRef(transformer, data)
transformReceiverTypeRef(transformer, data)
transformInitializer(transformer, data)
transformGetter(transformer, data)
transformSetter(transformer, data)
transformOtherChildren(transformer, data)
@@ -81,6 +82,11 @@ class FirDefaultSetterValueParameter(
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 {
getter = getter?.transformSingle(transformer, data)
return this
@@ -92,7 +98,6 @@ class FirDefaultSetterValueParameter(
}
override fun <D> transformOtherChildren(transformer: FirTransformer<D>, data: D): FirDefaultSetterValueParameter {
initializer = initializer?.transformSingle(transformer, data)
delegate = delegate?.transformSingle(transformer, data)
annotations.transformInplace(transformer, data)
defaultValue = defaultValue?.transformSingle(transformer, data)
@@ -76,6 +76,10 @@ class FirFieldImpl(
return this
}
override fun <D> transformInitializer(transformer: FirTransformer<D>, data: D): FirFieldImpl {
return this
}
override fun <D> transformGetter(transformer: FirTransformer<D>, data: D): FirFieldImpl {
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> transformInitializer(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>
@@ -76,6 +76,7 @@ class FirPropertyImpl(
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirPropertyImpl {
transformReturnTypeRef(transformer, data)
transformReceiverTypeRef(transformer, data)
transformInitializer(transformer, data)
transformGetter(transformer, data)
transformSetter(transformer, data)
transformControlFlowGraphReference(transformer, data)
@@ -94,6 +95,11 @@ class FirPropertyImpl(
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 {
getter = getter?.transformSingle(transformer, data)
return this
@@ -115,7 +121,6 @@ class FirPropertyImpl(
}
override fun <D> transformOtherChildren(transformer: FirTransformer<D>, data: D): FirPropertyImpl {
initializer = initializer?.transformSingle(transformer, data)
delegate = delegate?.transformSingle(transformer, data)
annotations.transformInplace(transformer, data)
typeParameters.transformInplace(transformer, data)
@@ -65,6 +65,7 @@ open class FirValueParameterImpl(
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirValueParameterImpl {
transformReturnTypeRef(transformer, data)
transformReceiverTypeRef(transformer, data)
transformInitializer(transformer, data)
transformGetter(transformer, data)
transformSetter(transformer, data)
transformOtherChildren(transformer, data)
@@ -81,6 +82,11 @@ open class FirValueParameterImpl(
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 {
getter = getter?.transformSingle(transformer, data)
return this
@@ -92,7 +98,6 @@ open class FirValueParameterImpl(
}
override fun <D> transformOtherChildren(transformer: FirTransformer<D>, data: D): FirValueParameterImpl {
initializer = initializer?.transformSingle(transformer, data)
delegate = delegate?.transformSingle(transformer, data)
annotations.transformInplace(transformer, data)
defaultValue = defaultValue?.transformSingle(transformer, data)

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