FIR: more accurate handling of dispatch receiver values

This commit fixes resolve priorities (see changed test data),
e.g. top-levels now have less priority than implicit receiver members
This commit is contained in:
Mikhail Glukhikh
2019-08-20 18:19:47 +03:00
parent fcb0b1b5eb
commit 5d6a526eec
11 changed files with 179 additions and 81 deletions
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.resultType
import org.jetbrains.kotlin.fir.resolve.typeForQualifier import org.jetbrains.kotlin.fir.resolve.typeForQualifier
import org.jetbrains.kotlin.fir.resolve.typeFromCallee import org.jetbrains.kotlin.fir.resolve.typeFromCallee
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.ConeSymbol import org.jetbrains.kotlin.fir.symbols.ConeSymbol
@@ -36,8 +37,8 @@ import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
class FirCallResolver( class FirCallResolver(
private val transformer: FirBodyResolveTransformer, private val transformer: FirBodyResolveTransformer,
private val scopes: List<FirScope>, private val topLevelScopes: List<FirScope>,
private val localScopes: List<FirScope>, private val localScopes: List<FirLocalScope>,
private val implicitReceiverStack: List<ImplicitReceiverValue>, private val implicitReceiverStack: List<ImplicitReceiverValue>,
private val qualifiedResolver: FirQualifiedNameResolver private val qualifiedResolver: FirQualifiedNameResolver
) : BodyResolveComponents by transformer { ) : BodyResolveComponents by transformer {
@@ -64,9 +65,11 @@ class FirCallResolver(
file, file,
transformer.container transformer.container
) { it.resultType } ) { it.resultType }
val resolver = CallResolver(returnTypeCalculator, inferenceComponents, resolutionStageRunner) val resolver = CallResolver(
resolver.callInfo = info returnTypeCalculator, inferenceComponents, resolutionStageRunner,
resolver.scopes = (scopes + localScopes).asReversed() topLevelScopes = topLevelScopes.asReversed(),
localScopes = localScopes.asReversed()
)
val consumer = createFunctionConsumer(session, name, info, inferenceComponents, resolver.collector, resolver) val consumer = createFunctionConsumer(session, name, info, inferenceComponents, resolver.collector, resolver)
val result = resolver.runTowerResolver(consumer, implicitReceiverStack.asReversed()) val result = resolver.runTowerResolver(consumer, implicitReceiverStack.asReversed())
@@ -154,9 +157,11 @@ class FirCallResolver(
file, file,
transformer.container transformer.container
) { it.resultType } ) { it.resultType }
val resolver = CallResolver(returnTypeCalculator, inferenceComponents, resolutionStageRunner) val resolver = CallResolver(
resolver.callInfo = info returnTypeCalculator, inferenceComponents, resolutionStageRunner,
resolver.scopes = (scopes + localScopes).asReversed() topLevelScopes = topLevelScopes.asReversed(),
localScopes = localScopes.asReversed()
)
val consumer = createVariableAndObjectConsumer( val consumer = createVariableAndObjectConsumer(
session, session,
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
enum class TowerDataKind { enum class TowerDataKind {
EMPTY, EMPTY,
@@ -17,10 +18,10 @@ enum class TowerDataKind {
class CallResolver( class CallResolver(
val typeCalculator: ReturnTypeCalculator, val typeCalculator: ReturnTypeCalculator,
val components: InferenceComponents, val components: InferenceComponents,
val resolutionStageRunner: ResolutionStageRunner val resolutionStageRunner: ResolutionStageRunner,
val topLevelScopes: List<FirScope>,
val localScopes: List<FirLocalScope>
) { ) {
var callInfo: CallInfo? = null
var scopes: List<FirScope>? = null
val session: FirSession get() = components.session val session: FirSession get() = components.session
@@ -44,10 +45,39 @@ class CallResolver(
group++ group++
) )
for (scope in scopes!!) { for (scope in localScopes) {
towerDataConsumer.consume( towerDataConsumer.consume(
TowerDataKind.TOWER_LEVEL, TowerDataKind.TOWER_LEVEL,
ScopeTowerLevel(session, scope, implicitReceiverValue), ScopeTowerLevel(session, scope, implicitExtensionReceiver = implicitReceiverValue),
group++
)
}
for (implicitDispatchReceiverValue in implicitReceiverValues) {
val implicitScope = implicitDispatchReceiverValue.implicitScope
if (implicitScope != null) {
towerDataConsumer.consume(
TowerDataKind.TOWER_LEVEL,
ScopeTowerLevel(session, implicitScope, implicitExtensionReceiver = implicitReceiverValue),
group++
)
}
if (implicitDispatchReceiverValue is ImplicitDispatchReceiverValue) {
val implicitCompanionScope = implicitDispatchReceiverValue.implicitCompanionScope
if (implicitCompanionScope != null) {
towerDataConsumer.consume(
TowerDataKind.TOWER_LEVEL,
ScopeTowerLevel(session, implicitCompanionScope, implicitExtensionReceiver = implicitReceiverValue),
group++
)
}
}
}
for (scope in topLevelScopes) {
towerDataConsumer.consume(
TowerDataKind.TOWER_LEVEL,
ScopeTowerLevel(session, scope, implicitExtensionReceiver = implicitReceiverValue),
group++ group++
) )
} }
@@ -64,15 +94,27 @@ class CallResolver(
towerDataConsumer = consumer towerDataConsumer = consumer
var group = 0 var group = 0
// Member of explicit receiver' type
towerDataConsumer.consume(TowerDataKind.EMPTY, TowerScopeLevel.Empty, group++) towerDataConsumer.consume(TowerDataKind.EMPTY, TowerScopeLevel.Empty, group++)
for (scope in scopes!!) { // Member of local scope
for (scope in localScopes) {
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, scope), group++) towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, scope), group++)
} }
var blockDispatchReceivers = false var blockDispatchReceivers = false
// Member of implicit receiver' type
for (implicitReceiverValue in implicitReceiverValues) { for (implicitReceiverValue in implicitReceiverValues) {
val implicitScope = implicitReceiverValue.implicitScope
if (implicitScope != null) {
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, implicitScope), group++)
}
if (implicitReceiverValue is ImplicitDispatchReceiverValue) { if (implicitReceiverValue is ImplicitDispatchReceiverValue) {
val implicitCompanionScope = implicitReceiverValue.implicitCompanionScope
if (implicitCompanionScope != null) {
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, implicitCompanionScope), group++)
}
if (blockDispatchReceivers) { if (blockDispatchReceivers) {
continue continue
} }
@@ -83,6 +125,11 @@ class CallResolver(
group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, collector, group) group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, collector, group)
} }
// Member of top-level scope
for (scope in topLevelScopes) {
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, scope), group++)
}
return collector return collector
} }
} }
@@ -5,8 +5,14 @@
package org.jetbrains.kotlin.fir.resolve.calls package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.classId
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.renderWithType import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
@@ -32,14 +38,28 @@ class ExpressionReceiverValue(
?: ConeKotlinErrorType("No type calculated for: ${explicitReceiverExpression.renderWithType()}") // TODO: assert here ?: ConeKotlinErrorType("No type calculated for: ${explicitReceiverExpression.renderWithType()}") // TODO: assert here
} }
interface ImplicitReceiverValue : ReceiverValue { abstract class ImplicitReceiverValue(
final override val type: ConeKotlinType,
useSiteSession: FirSession,
scopeSession: ScopeSession
) : ReceiverValue {
val implicitScope: FirScope? = type.scope(useSiteSession, scopeSession)
} }
class ImplicitDispatchReceiverValue( class ImplicitDispatchReceiverValue(
val boundSymbol: FirClassSymbol, val boundSymbol: FirClassSymbol,
override val type: ConeKotlinType type: ConeKotlinType,
) : ImplicitReceiverValue symbolProvider: FirSymbolProvider,
useSiteSession: FirSession,
scopeSession: ScopeSession
) : ImplicitReceiverValue(type, useSiteSession, scopeSession) {
val implicitCompanionScope: FirScope? = boundSymbol.fir.companionObject?.let { companionObject ->
symbolProvider.getClassUseSiteMemberScope(companionObject.classId, useSiteSession, scopeSession)
}
}
class ImplicitExtensionReceiverValue( class ImplicitExtensionReceiverValue(
override val type: ConeKotlinType type: ConeKotlinType,
) : ImplicitReceiverValue useSiteSession: FirSession,
scopeSession: ScopeSession
) : ImplicitReceiverValue(type, useSiteSession, scopeSession)
@@ -69,6 +69,7 @@ abstract class SessionBasedTowerLevel(val session: FirSession) : TowerScopeLevel
protected fun AbstractFirBasedSymbol<*>.dispatchReceiverValue(): ClassDispatchReceiverValue? { protected fun AbstractFirBasedSymbol<*>.dispatchReceiverValue(): ClassDispatchReceiverValue? {
return when (this) { return when (this) {
is FirNamedFunctionSymbol -> fir.dispatchReceiverValue(session) is FirNamedFunctionSymbol -> fir.dispatchReceiverValue(session)
is FirPropertySymbol -> fir.dispatchReceiverValue(session)
is FirClassSymbol -> ClassDispatchReceiverValue(fir.symbol) is FirClassSymbol -> ClassDispatchReceiverValue(fir.symbol)
else -> null else -> null
} }
@@ -53,7 +53,6 @@ open class FirBodyResolveTransformer(
private val booleanType = FirImplicitBooleanTypeRef(null) private val booleanType = FirImplicitBooleanTypeRef(null)
final override val symbolProvider = session.service<FirSymbolProvider>() final override val symbolProvider = session.service<FirSymbolProvider>()
val scopes = mutableListOf<FirScope>()
private var packageFqName = FqName.ROOT private var packageFqName = FqName.ROOT
final override lateinit var file: FirFile final override lateinit var file: FirFile
@@ -67,6 +66,7 @@ open class FirBodyResolveTransformer(
} }
private val localScopes = mutableListOf<FirLocalScope>() private val localScopes = mutableListOf<FirLocalScope>()
private val topLevelScopes = mutableListOf<FirScope>()
private val implicitReceiverStack = mutableListOf<ImplicitReceiverValue>() private val implicitReceiverStack = mutableListOf<ImplicitReceiverValue>()
final override val inferenceComponents = inferenceComponents(session, returnTypeCalculator, scopeSession) final override val inferenceComponents = inferenceComponents(session, returnTypeCalculator, scopeSession)
@@ -77,7 +77,7 @@ open class FirBodyResolveTransformer(
final override val resolutionStageRunner: ResolutionStageRunner = ResolutionStageRunner(inferenceComponents) final override val resolutionStageRunner: ResolutionStageRunner = ResolutionStageRunner(inferenceComponents)
private val callResolver: FirCallResolver = FirCallResolver( private val callResolver: FirCallResolver = FirCallResolver(
this, this,
scopes, topLevelScopes,
localScopes, localScopes,
implicitReceiverStack, implicitReceiverStack,
qualifiedResolver qualifiedResolver
@@ -94,9 +94,9 @@ open class FirBodyResolveTransformer(
override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult<FirFile> { override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult<FirFile> {
packageFqName = file.packageFqName packageFqName = file.packageFqName
this.file = file this.file = file
return withScopeCleanup(scopes) { return withScopeCleanup(topLevelScopes) {
scopes.addImportingScopes(file, session) topLevelScopes.addImportingScopes(file, session)
scopes += FirTopLevelDeclaredMemberScope(file, session) topLevelScopes += FirTopLevelDeclaredMemberScope(file, session)
super.transformFile(file, data) super.transformFile(file, data)
} }
} }
@@ -139,27 +139,20 @@ open class FirBodyResolveTransformer(
} }
override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult<FirDeclaration> { override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup(scopes) { val oldConstructorScope = primaryConstructorParametersScope
val oldConstructorScope = primaryConstructorParametersScope primaryConstructorParametersScope = null
primaryConstructorParametersScope = null val type = regularClass.defaultType()
val type = regularClass.defaultType() val result = withLabelAndReceiverType(regularClass.name, regularClass, type) {
scopes.addIfNotNull(type.scope(session, scopeSession)) val constructor = regularClass.declarations.firstOrNull() as? FirConstructor
val companionObject = regularClass.companionObject if (constructor?.isPrimary == true) {
if (companionObject != null) { primaryConstructorParametersScope = FirLocalScope().apply {
scopes.addIfNotNull(symbolProvider.getClassUseSiteMemberScope(companionObject.classId, session, scopeSession)) constructor.valueParameters.forEach { this.storeDeclaration(it) }
}
val result = withLabelAndReceiverType(regularClass.name, regularClass, type) {
val constructor = regularClass.declarations.firstOrNull() as? FirConstructor
if (constructor?.isPrimary == true) {
primaryConstructorParametersScope = FirLocalScope().apply {
constructor.valueParameters.forEach { this.storeDeclaration(it) }
}
} }
super.transformRegularClass(regularClass, data)
} }
primaryConstructorParametersScope = oldConstructorScope super.transformRegularClass(regularClass, data)
result
} }
primaryConstructorParametersScope = oldConstructorScope
return result
} }
override fun transformUncheckedNotNullCast( override fun transformUncheckedNotNullCast(
@@ -359,17 +352,15 @@ open class FirBodyResolveTransformer(
): FirAnonymousFunction { ): FirAnonymousFunction {
val receiverTypeRef = anonymousFunction.receiverTypeRef val receiverTypeRef = anonymousFunction.receiverTypeRef
fun transform(): FirAnonymousFunction { fun transform(): FirAnonymousFunction {
return withScopeCleanup(scopes) { val expectedReturnType =
scopes.addIfNotNull(receiverTypeRef?.coneTypeSafe<ConeKotlinType>()?.scope(session, scopeSession)) lambdaResolution.expectedReturnTypeRef ?: anonymousFunction.returnTypeRef.takeUnless { it is FirImplicitTypeRef }
val expectedReturnType = lambdaResolution.expectedReturnTypeRef ?: anonymousFunction.returnTypeRef.takeUnless { it is FirImplicitTypeRef }
val result = super.transformAnonymousFunction(anonymousFunction, expectedReturnType).single as FirAnonymousFunction val result = super.transformAnonymousFunction(anonymousFunction, expectedReturnType).single as FirAnonymousFunction
val body = result.body val body = result.body
if (result.returnTypeRef is FirImplicitTypeRef && body != null) { return if (result.returnTypeRef is FirImplicitTypeRef && body != null) {
result.transformReturnTypeRef(this, body.resultType) result.transformReturnTypeRef(this, body.resultType)
result result
} else { } else {
result result
}
} }
} }
@@ -563,18 +554,14 @@ open class FirBodyResolveTransformer(
if (function is FirNamedFunction) { if (function is FirNamedFunction) {
localScopes.lastOrNull()?.storeDeclaration(function) localScopes.lastOrNull()?.storeDeclaration(function)
} }
return withScopeCleanup(scopes) { val result = transformFunction(function, returnTypeRef).single as FirFunction<*>
scopes.addIfNotNull(receiverTypeRef?.coneTypeSafe<ConeKotlinType>()?.scope(session, scopeSession)) val body = result.body
return if (result is FirTypedDeclaration && result.returnTypeRef is FirImplicitTypeRef && body != null) {
val result = transformFunction(function, returnTypeRef).single as FirFunction<*> result.transformReturnTypeRef(this, body.resultType)
val body = result.body result
if (result is FirTypedDeclaration && result.returnTypeRef is FirImplicitTypeRef && body != null) { } else {
result.transformReturnTypeRef(this, body.resultType) result
result }.compose()
} else {
result
}.compose()
}
} }
override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Any?): CompositeTransformResult<FirDeclaration> { override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Any?): CompositeTransformResult<FirDeclaration> {
@@ -783,10 +770,16 @@ open class FirBodyResolveTransformer(
private inline fun <T> withLabelAndReceiverType(labelName: Name, owner: FirElement, type: ConeKotlinType, block: () -> T): T { private inline fun <T> withLabelAndReceiverType(labelName: Name, owner: FirElement, type: ConeKotlinType, block: () -> T): T {
labels.put(labelName, type) labels.put(labelName, type)
when (owner) { implicitReceiverStack += when (owner) {
is FirRegularClass -> implicitReceiverStack += ImplicitDispatchReceiverValue(owner.symbol, type) is FirRegularClass -> {
is FirFunction<*> -> implicitReceiverStack += ImplicitExtensionReceiverValue(type) ImplicitDispatchReceiverValue(owner.symbol, type, symbolProvider, session, scopeSession)
else -> throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}") }
is FirFunction<*> -> {
ImplicitExtensionReceiverValue(type, session, scopeSession)
}
else -> {
throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}")
}
} }
val result = block() val result = block()
implicitReceiverStack.removeAt(implicitReceiverStack.size - 1) implicitReceiverStack.removeAt(implicitReceiverStack.size - 1)
@@ -37,11 +37,11 @@ FILE: access.kt
} }
public final fun R|Foo|.check(): <ERROR TYPE REF: Inapplicable(INAPPLICABLE): [kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus]> { public final fun R|Foo|.check(): <ERROR TYPE REF: Inapplicable(INAPPLICABLE): [kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus]> {
^check R|/Foo.abc|().<Inapplicable(INAPPLICABLE): [kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus]>#(R|/bar|()) ^check R|/Foo.abc|().<Inapplicable(INAPPLICABLE): [kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus]>#(R|/Bar.bar|())
} }
public final fun R|Foo|.check2(): R|kotlin/String| { public final fun R|Foo|.check2(): R|kotlin/String| {
^check2 String().R|kotlin/String.plus|(R|/bar|()) ^check2 String().R|kotlin/String.plus|(R|/Bar.bar|())
} }
} }
@@ -10,4 +10,16 @@ class Foo {
operator fun invoke(): Foo { return this } operator fun invoke(): Foo { return this }
fun bar() = x() // Should resolve to invoke fun bar() = x() // Should resolve to invoke
}
class Bar {
fun x() {}
val x: Bar = Bar()
operator fun invoke(): Bar { return this }
fun baz() {
x() // Should resolve to fun x()
}
} }
@@ -18,3 +18,23 @@ FILE: explicitReceiver.kt
} }
} }
public final class Bar : R|kotlin/Any| {
public constructor(): R|Bar| {
super<R|kotlin/Any|>()
}
public final fun x(): R|kotlin/Unit| {
}
public final val x: R|Bar| = R|/Bar.Bar|()
public get(): R|Bar|
public final operator fun invoke(): R|Bar| {
^invoke this#
}
public final fun baz(): R|kotlin/Unit| {
R|/Bar.x|()
}
}
@@ -13,8 +13,8 @@ FILE: extension.kt
public final val x: R|kotlin/Int| = Int(0) public final val x: R|kotlin/Int| = Int(0)
public get(): R|kotlin/Int| public get(): R|kotlin/Int|
public final fun foo(): R|kotlin/Unit| { public final fun foo(): R|Foo| {
^foo R|/x|() ^foo R|/Foo.x|.R|/Foo.invoke|()
} }
} }
@@ -4,7 +4,7 @@ FILE: recursiveBug.kt
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
public final val result: R|kotlin/String| = R|kotlin/run|<R|kotlin/String|>(<L> = run@fun <anonymous>(): R|kotlin/String| { public final val result: R|kotlin/String| = R|kotlin/run|<R|Foo|, R|kotlin/String|>(<L> = run@fun R|Foo|.<anonymous>(it: R|Foo|): R|kotlin/String| {
R|<local>/name|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/String|>|() R|<local>/name|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/String|>|()
} }
) )
@@ -1,9 +1,9 @@
FILE fqName:<root> fileName:/implicitCastToNonNull.kt FILE fqName:<root> fileName:/implicitCastToNonNull.kt
FUN name:test1 visibility:public modality:FINAL <> (x:kotlin.String?) returnType:kotlin.Int FUN name:test1 visibility:public modality:FINAL <> (x:kotlin.String?) returnType:IrErrorType
VALUE_PARAMETER name:x index:0 type:kotlin.String? VALUE_PARAMETER name:x index:0 type:kotlin.String?
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test1 (x: kotlin.String?): kotlin.Int declared in <root>' RETURN type=kotlin.Nothing from='public final fun test1 (x: kotlin.String?): IrErrorType declared in <root>'
WHEN type=kotlin.Int origin=IF WHEN type=IrErrorType origin=IF
BRANCH BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'x: kotlin.String? declared in <root>.test1' type=kotlin.String? origin=null arg0: GET_VAR 'x: kotlin.String? declared in <root>.test1' type=kotlin.String? origin=null
@@ -11,13 +11,13 @@ FILE fqName:<root> fileName:/implicitCastToNonNull.kt
then: CONST Int type=kotlin.Int value=0 then: CONST Int type=kotlin.Int value=0
BRANCH BRANCH
if: CONST Boolean type=kotlin.Boolean value=true if: CONST Boolean type=kotlin.Boolean value=true
then: ERROR_CALL 'No getter found for R|kotlin/String.length|' type=kotlin.Int then: ERROR_CALL 'Unresolved reference: <Inapplicable(WRONG_RECEIVER): [kotlin/String.length]>#' type=IrErrorType
FUN name:test2 visibility:public modality:FINAL <T> (x:T of <root>.test2) returnType:kotlin.Int FUN name:test2 visibility:public modality:FINAL <T> (x:T of <root>.test2) returnType:IrErrorType
TYPE_PARAMETER name:T index:0 variance: superTypes:[] TYPE_PARAMETER name:T index:0 variance: superTypes:[]
VALUE_PARAMETER name:x index:0 type:T of <root>.test2 VALUE_PARAMETER name:x index:0 type:T of <root>.test2
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test2 <T> (x: T of <root>.test2): kotlin.Int declared in <root>' RETURN type=kotlin.Nothing from='public final fun test2 <T> (x: T of <root>.test2): IrErrorType declared in <root>'
WHEN type=kotlin.Int origin=IF WHEN type=IrErrorType origin=IF
BRANCH BRANCH
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
arg0: GET_VAR 'x: T of <root>.test2 declared in <root>.test2' type=T of <root>.test2 origin=null arg0: GET_VAR 'x: T of <root>.test2 declared in <root>.test2' type=T of <root>.test2 origin=null
@@ -25,7 +25,7 @@ FILE fqName:<root> fileName:/implicitCastToNonNull.kt
then: CONST Int type=kotlin.Int value=0 then: CONST Int type=kotlin.Int value=0
BRANCH BRANCH
if: CONST Boolean type=kotlin.Boolean value=true if: CONST Boolean type=kotlin.Boolean value=true
then: ERROR_CALL 'No getter found for R|kotlin/CharSequence.length|' type=kotlin.Int then: ERROR_CALL 'Unresolved reference: <Inapplicable(WRONG_RECEIVER): [kotlin/CharSequence.length]>#' type=IrErrorType
FUN name:test3 visibility:public modality:FINAL <T> (x:kotlin.Any) returnType:IrErrorType [inline] FUN name:test3 visibility:public modality:FINAL <T> (x:kotlin.Any) returnType:IrErrorType [inline]
TYPE_PARAMETER name:T index:0 variance: superTypes:[] TYPE_PARAMETER name:T index:0 variance: superTypes:[]
VALUE_PARAMETER name:x index:0 type:kotlin.Any VALUE_PARAMETER name:x index:0 type:kotlin.Any