[FIR] Approximate exotic return types for public declarations
This commit is contained in:
@@ -16,12 +16,12 @@ FILE: intersectionTypes.kt
|
|||||||
|
|
||||||
}
|
}
|
||||||
public final fun <K> select(x: R|K|, y: R|K|): R|K|
|
public final fun <K> select(x: R|K|, y: R|K|): R|K|
|
||||||
public final fun test(): R|it(A & B)| {
|
public final fun test(): R|kotlin/Any| {
|
||||||
^test R|/select|<R|it(A & B)|>(R|/Clazz1.Clazz1|(), R|/Clazz2.Clazz2|())
|
^test R|/select|<R|it(A & B)|>(R|/Clazz1.Clazz1|(), R|/Clazz2.Clazz2|())
|
||||||
}
|
}
|
||||||
public final fun <T> makeNull(x: R|T|): R|T?| {
|
public final fun <T> makeNull(x: R|T|): R|T?| {
|
||||||
^makeNull Null(null)
|
^makeNull Null(null)
|
||||||
}
|
}
|
||||||
public final fun testNull(): R|it(A? & B?)| {
|
public final fun testNull(): R|kotlin/Any?| {
|
||||||
^testNull R|/makeNull|<R|it(A & B)|>(R|/select|<R|it(A & B)|>(R|/Clazz1.Clazz1|(), R|/Clazz2.Clazz2|()))
|
^testNull R|/makeNull|<R|it(A & B)|>(R|/select|<R|it(A & B)|>(R|/Clazz1.Clazz1|(), R|/Clazz2.Clazz2|()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ FILE: whenElse.kt
|
|||||||
public get(): R|B|
|
public get(): R|B|
|
||||||
|
|
||||||
}
|
}
|
||||||
public final fun get(f: R|kotlin/Boolean|): R|it(kotlin/Comparable<it(A & kotlin/String)> & java/io/Serializable)| {
|
public final fun get(f: R|kotlin/Boolean|): R|kotlin/Any| {
|
||||||
^get when () {
|
^get when () {
|
||||||
R|<local>/f| -> {
|
R|<local>/f| -> {
|
||||||
Q|A|.R|/A.A1|
|
Q|A|.R|/A.A1|
|
||||||
|
|||||||
+41
-7
@@ -7,6 +7,10 @@ package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
|
import org.jetbrains.kotlin.fir.Visibilities.Internal
|
||||||
|
import org.jetbrains.kotlin.fir.Visibilities.Private
|
||||||
|
import org.jetbrains.kotlin.fir.Visibilities.Protected
|
||||||
|
import org.jetbrains.kotlin.fir.Visibilities.Public
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||||
@@ -28,6 +32,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
|||||||
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
|
||||||
import org.jetbrains.kotlin.fir.symbols.constructStarProjectedType
|
import org.jetbrains.kotlin.fir.symbols.constructStarProjectedType
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||||
@@ -37,6 +42,7 @@ import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
|
|||||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.visitors.*
|
import org.jetbrains.kotlin.fir.visitors.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) {
|
open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) {
|
||||||
@@ -503,7 +509,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
result.transformReturnTypeRef(
|
result.transformReturnTypeRef(
|
||||||
transformer,
|
transformer,
|
||||||
withExpectedType(
|
withExpectedType(
|
||||||
body.resultType.hideLocalTypeIfNeeded(simpleFunction?.visibility, simpleFunction?.isInline == true)
|
body.resultType.approximateTypeIfNeeded(simpleFunction?.visibility, simpleFunction?.isInline == true)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -911,7 +917,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
}
|
}
|
||||||
variable.transformReturnTypeRef(
|
variable.transformReturnTypeRef(
|
||||||
transformer,
|
transformer,
|
||||||
withExpectedType(expectedType.hideLocalTypeIfNeeded((variable as? FirProperty)?.visibility))
|
withExpectedType(expectedType.approximateTypeIfNeeded((variable as? FirProperty)?.visibility))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
variable.getter != null && variable.getter !is FirDefaultPropertyAccessor -> {
|
variable.getter != null && variable.getter !is FirDefaultPropertyAccessor -> {
|
||||||
@@ -933,7 +939,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
}
|
}
|
||||||
variable.transformReturnTypeRef(
|
variable.transformReturnTypeRef(
|
||||||
transformer,
|
transformer,
|
||||||
withExpectedType(expectedType?.hideLocalTypeIfNeeded((variable as? FirProperty)?.visibility))
|
withExpectedType(expectedType?.approximateTypeIfNeeded((variable as? FirProperty)?.visibility))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@@ -956,6 +962,34 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirTypeRef.approximateTypeIfNeeded(
|
||||||
|
containingCallableVisibility: Visibility?,
|
||||||
|
isInlineFunction: Boolean = false
|
||||||
|
): FirTypeRef {
|
||||||
|
val approximatedType = if (this is FirResolvedTypeRef &&
|
||||||
|
(containingCallableVisibility == Public || containingCallableVisibility == Protected)
|
||||||
|
) {
|
||||||
|
when (this.type) {
|
||||||
|
is ConeIntegerLiteralType,
|
||||||
|
is ConeCapturedType,
|
||||||
|
is ConeDefinitelyNotNullType,
|
||||||
|
is ConeIntersectionType -> {
|
||||||
|
this.withReplacedConeType(
|
||||||
|
inferenceComponents.approximator.approximateToSuperType(
|
||||||
|
this.type, TypeApproximatorConfiguration.PublicDeclaration
|
||||||
|
) as ConeKotlinType
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this
|
||||||
|
}
|
||||||
|
return approximatedType.hideLocalTypeIfNeeded(containingCallableVisibility, isInlineFunction)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Suppose a function without an explicit return type just returns an anonymous object:
|
* Suppose a function without an explicit return type just returns an anonymous object:
|
||||||
*
|
*
|
||||||
@@ -976,10 +1010,10 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
}
|
}
|
||||||
// Approximate types for non-private (all but package private or private) members.
|
// Approximate types for non-private (all but package private or private) members.
|
||||||
// Also private inline functions, as per KT-33917.
|
// Also private inline functions, as per KT-33917.
|
||||||
if (containingCallableVisibility == Visibilities.Public ||
|
if (containingCallableVisibility == Public ||
|
||||||
containingCallableVisibility == Visibilities.Protected ||
|
containingCallableVisibility == Protected ||
|
||||||
containingCallableVisibility == Visibilities.Internal ||
|
containingCallableVisibility == Internal ||
|
||||||
(containingCallableVisibility == Visibilities.Private && isInlineFunction)
|
(containingCallableVisibility == Private && isInlineFunction)
|
||||||
) {
|
) {
|
||||||
val firClass =
|
val firClass =
|
||||||
(((this as? FirResolvedTypeRef)
|
(((this as? FirResolvedTypeRef)
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// !LANGUAGE: +StrictJavaNullabilityAssertions
|
// !LANGUAGE: +StrictJavaNullabilityAssertions
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// SKIP_JDK6
|
// SKIP_JDK6
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
class A (val p: String, p1: String, p2: String) {
|
class A (val p: String, p1: String, p2: String) {
|
||||||
|
|
||||||
var cond1 :String = ""
|
var cond1 :String = ""
|
||||||
|
|||||||
+2
-2
@@ -29,6 +29,6 @@ fun chained2(arg: First) = run {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test(arg: First) {
|
fun test(arg: First) {
|
||||||
chained1(arg).first()
|
chained1(arg).<!UNRESOLVED_REFERENCE!>first<!>()
|
||||||
chained2(arg).first()
|
chained2(arg).<!UNRESOLVED_REFERENCE!>first<!>()
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -33,6 +33,6 @@ fun intersectArgWithSmartCastFromLambda(arg: One, arg2: Base) = argOrFn(arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
intersectAfterSmartCast(O1, O2).base()
|
intersectAfterSmartCast(O1, O2).<!UNRESOLVED_REFERENCE!>base<!>()
|
||||||
intersectArgWithSmartCastFromLambda(O1, O2).base()
|
intersectArgWithSmartCastFromLambda(O1, O2).<!UNRESOLVED_REFERENCE!>base<!>()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -18,5 +18,5 @@ fun smartCastAfterIntersection(a: One, b: Two) = run {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test(one: One, two: Two) {
|
fun test(one: One, two: Two) {
|
||||||
smartCastAfterIntersection(one, two)?.base()
|
smartCastAfterIntersection(one, two)?.<!UNRESOLVED_REFERENCE!>base<!>()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -21,5 +21,5 @@ fun <S> intersectNoBound(vararg elements: S): S = TODO()
|
|||||||
fun some(a: One, b: Two, c: Three) = intersectNoBound(intersect(a, b), c)
|
fun some(a: One, b: Two, c: Three) = intersectNoBound(intersect(a, b), c)
|
||||||
|
|
||||||
fun test(arg: Base, arg2: Base) {
|
fun test(arg: Base, arg2: Base) {
|
||||||
some(O1, O2, O3).base()
|
some(O1, O2, O3).<!UNRESOLVED_REFERENCE!>base<!>()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ FILE fqName:<root> fileName:/intersectionType2_NI.kt
|
|||||||
RETURN type=kotlin.Nothing from='public final fun run <T> (fn: kotlin.Function0<T of <root>.run>): T of <root>.run declared in <root>'
|
RETURN type=kotlin.Nothing from='public final fun run <T> (fn: kotlin.Function0<T of <root>.run>): T of <root>.run declared in <root>'
|
||||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=T of <root>.run origin=INVOKE
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=T of <root>.run origin=INVOKE
|
||||||
$this: GET_VAR 'fn: kotlin.Function0<T of <root>.run> declared in <root>.run' type=kotlin.Function0<T of <root>.run> origin=null
|
$this: GET_VAR 'fn: kotlin.Function0<T of <root>.run> declared in <root>.run' type=kotlin.Function0<T of <root>.run> origin=null
|
||||||
FUN name:foo visibility:public modality:FINAL <> () returnType:<root>.Foo
|
FUN name:foo visibility:public modality:FINAL <> () returnType:kotlin.Any
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from='public final fun foo (): <root>.Foo declared in <root>'
|
RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.Any declared in <root>'
|
||||||
CALL 'public final fun run <T> (fn: kotlin.Function0<T of <root>.run>): T of <root>.run declared in <root>' type=<root>.Foo origin=null
|
CALL 'public final fun run <T> (fn: kotlin.Function0<T of <root>.run>): T of <root>.run declared in <root>' type=<root>.Foo origin=null
|
||||||
<T>: <root>.Foo
|
<T>: <root>.Foo
|
||||||
fn: FUN_EXPR type=kotlin.Function0<<root>.Foo> origin=LAMBDA
|
fn: FUN_EXPR type=kotlin.Function0<<root>.Foo> origin=LAMBDA
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ FILE fqName:<root> fileName:/intersectionType2_OI.kt
|
|||||||
RETURN type=kotlin.Nothing from='public final fun run <T> (fn: kotlin.Function0<T of <root>.run>): T of <root>.run declared in <root>'
|
RETURN type=kotlin.Nothing from='public final fun run <T> (fn: kotlin.Function0<T of <root>.run>): T of <root>.run declared in <root>'
|
||||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=T of <root>.run origin=INVOKE
|
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=T of <root>.run origin=INVOKE
|
||||||
$this: GET_VAR 'fn: kotlin.Function0<T of <root>.run> declared in <root>.run' type=kotlin.Function0<T of <root>.run> origin=null
|
$this: GET_VAR 'fn: kotlin.Function0<T of <root>.run> declared in <root>.run' type=kotlin.Function0<T of <root>.run> origin=null
|
||||||
FUN name:foo visibility:public modality:FINAL <> () returnType:<root>.Foo
|
FUN name:foo visibility:public modality:FINAL <> () returnType:kotlin.Any
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from='public final fun foo (): <root>.Foo declared in <root>'
|
RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.Any declared in <root>'
|
||||||
CALL 'public final fun run <T> (fn: kotlin.Function0<T of <root>.run>): T of <root>.run declared in <root>' type=<root>.Foo origin=null
|
CALL 'public final fun run <T> (fn: kotlin.Function0<T of <root>.run>): T of <root>.run declared in <root>' type=<root>.Foo origin=null
|
||||||
<T>: <root>.Foo
|
<T>: <root>.Foo
|
||||||
fn: FUN_EXPR type=kotlin.Function0<<root>.Foo> origin=LAMBDA
|
fn: FUN_EXPR type=kotlin.Function0<<root>.Foo> origin=LAMBDA
|
||||||
|
|||||||
Reference in New Issue
Block a user