[FIR] Completely unwrap original argument when computing type arguments
When computing the conversion type for a type operator call, the argument needs to be fully unwrapped before getting the resolved type. This avoids the situation when the argument is a when-subject and the assumed original type is not correct. Before, only smart-casts were unwrapped, and this change will also unwrap when-subjects (as well as a few other FirExpressions). ^KT-62114 Fixed
This commit is contained in:
+1
-1
@@ -839,7 +839,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
|
|||||||
val firClass = type.lookupTag.toSymbol(session)?.fir ?: return this
|
val firClass = type.lookupTag.toSymbol(session)?.fir ?: return this
|
||||||
if (firClass.typeParameters.isEmpty()) return this
|
if (firClass.typeParameters.isEmpty()) return this
|
||||||
|
|
||||||
val originalType = argument.unwrapSmartcastExpression().resolvedType
|
val originalType = argument.unwrapExpression().resolvedType
|
||||||
val newType = components.computeRepresentativeTypeForBareType(type, originalType)
|
val newType = components.computeRepresentativeTypeForBareType(type, originalType)
|
||||||
?: if (firClass.isLocal && (operation == FirOperation.AS || operation == FirOperation.SAFE_AS)) {
|
?: if (firClass.isLocal && (operation == FirOperation.AS || operation == FirOperation.SAFE_AS)) {
|
||||||
(firClass as FirClass).defaultType()
|
(firClass as FirClass).defaultType()
|
||||||
|
|||||||
@@ -151,6 +151,16 @@ fun FirVariableAssignment.unwrapLValue(): FirQualifiedAccessExpression? {
|
|||||||
val FirElement.calleeReference: FirReference?
|
val FirElement.calleeReference: FirReference?
|
||||||
get() = (this as? FirResolvable)?.calleeReference ?: (this as? FirVariableAssignment)?.calleeReference
|
get() = (this as? FirResolvable)?.calleeReference ?: (this as? FirVariableAssignment)?.calleeReference
|
||||||
|
|
||||||
|
fun FirExpression.unwrapExpression(): FirExpression =
|
||||||
|
when (this) {
|
||||||
|
is FirWhenSubjectExpression -> whenRef.value.subject?.unwrapExpression() ?: this
|
||||||
|
is FirSmartCastExpression -> originalExpression.unwrapExpression()
|
||||||
|
is FirCheckedSafeCallSubject -> originalReceiverRef.value.unwrapExpression()
|
||||||
|
is FirCheckNotNullCall -> argument.unwrapExpression()
|
||||||
|
is FirDesugaredAssignmentValueReferenceExpression -> expressionRef.value.unwrapExpression()
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
|
|
||||||
fun FirExpression.unwrapSmartcastExpression(): FirExpression =
|
fun FirExpression.unwrapSmartcastExpression(): FirExpression =
|
||||||
when (this) {
|
when (this) {
|
||||||
is FirSmartCastExpression -> originalExpression
|
is FirSmartCastExpression -> originalExpression
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// ISSUE: KT-62114
|
||||||
|
|
||||||
open class A {
|
open class A {
|
||||||
class B : A() {
|
class B : A() {
|
||||||
val a = "FAIL"
|
val a = "FAIL"
|
||||||
@@ -27,3 +29,26 @@ class C {
|
|||||||
else return ""
|
else return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class Received<out T> {
|
||||||
|
sealed class Error<out T> : Received<T>() {
|
||||||
|
data class SomeError<out T>(val details: T?) : Error<T>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val Received<String>.thisRaisesUnresolvedReference: Boolean
|
||||||
|
get() = if (this is Received.Error<*>) {
|
||||||
|
when (this) {
|
||||||
|
is Received.Error.SomeError -> details?.length == 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
val Received<String>.thisIsFine: Boolean
|
||||||
|
get() = if (this is Received.Error<*>) {
|
||||||
|
if (this is Received.Error.SomeError) { details?.length == 0 }
|
||||||
|
else false
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// ISSUE: KT-62114
|
||||||
|
|
||||||
open class A {
|
open class A {
|
||||||
class B : A() {
|
class B : A() {
|
||||||
val a = "FAIL"
|
val a = "FAIL"
|
||||||
@@ -27,3 +29,26 @@ class C {
|
|||||||
else return ""
|
else return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class Received<out T> {
|
||||||
|
sealed class Error<out T> : Received<T>() {
|
||||||
|
data class SomeError<out T>(val details: T?) : Error<T>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val Received<String>.thisRaisesUnresolvedReference: Boolean
|
||||||
|
get() = if (this is Received.Error<*>) {
|
||||||
|
when (<!DEBUG_INFO_SMARTCAST!>this<!>) {
|
||||||
|
is Received.Error.SomeError -> <!DEBUG_INFO_IMPLICIT_RECEIVER_SMARTCAST!>details<!>?.length == 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
val Received<String>.thisIsFine: Boolean
|
||||||
|
get() = if (this is Received.Error<*>) {
|
||||||
|
if (this is Received.Error.SomeError) { <!DEBUG_INFO_IMPLICIT_RECEIVER_SMARTCAST!>details<!>?.length == 0 }
|
||||||
|
else false
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
|
public val Received<kotlin.String>.thisIsFine: kotlin.Boolean
|
||||||
|
public val Received<kotlin.String>.thisRaisesUnresolvedReference: kotlin.Boolean
|
||||||
public fun A?.bar(): kotlin.Unit
|
public fun A?.bar(): kotlin.Unit
|
||||||
public fun A.gav(): kotlin.String
|
public fun A.gav(): kotlin.String
|
||||||
|
|
||||||
@@ -36,3 +38,28 @@ public final class C {
|
|||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
public final fun A?.complex(): kotlin.String
|
public final fun A?.complex(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class Received</*0*/ out T> {
|
||||||
|
protected constructor Received</*0*/ out T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
public sealed class Error</*0*/ out T> : Received<T> {
|
||||||
|
protected constructor Error</*0*/ out T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
public final data class SomeError</*0*/ out T> : Received.Error<T> {
|
||||||
|
public constructor SomeError</*0*/ out T>(/*0*/ details: T?)
|
||||||
|
public final val details: T?
|
||||||
|
public final operator /*synthesized*/ fun component1(): T?
|
||||||
|
public final /*synthesized*/ fun copy(/*0*/ details: T? = ...): Received.Error.SomeError<T>
|
||||||
|
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user