FIR: support DefinitelyNotNull types
#KT-49465 Fixed
This commit is contained in:
@@ -30,7 +30,7 @@ FILE fqName:<root> fileName:/bangbang.kt
|
||||
VALUE_PARAMETER name:a index:0 type:X of <root>.test3
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test3 <X> (a: X of <root>.test3): X of <root>.test3 declared in <root>'
|
||||
CALL 'public final fun CHECK_NOT_NULL <T0> (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=X of <root>.test3 origin=EXCLEXCL
|
||||
CALL 'public final fun CHECK_NOT_NULL <T0> (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type={X of <root>.test3 & Any} origin=EXCLEXCL
|
||||
<T0>: X of <root>.test3
|
||||
arg0: GET_VAR 'a: X of <root>.test3 declared in <root>.test3' type=X of <root>.test3 origin=null
|
||||
FUN name:useString visibility:public modality:FINAL <> (s:kotlin.String) returnType:kotlin.Unit
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
FILE fqName:<root> fileName:/implicitCastToNonNull.kt
|
||||
FUN name:test1 visibility:public modality:FINAL <> (x:kotlin.String?) returnType:kotlin.Int
|
||||
VALUE_PARAMETER name:x index:0 type:kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test1 (x: kotlin.String?): kotlin.Int declared in <root>'
|
||||
WHEN type=kotlin.Int origin=IF
|
||||
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
|
||||
arg0: GET_VAR 'x: kotlin.String? declared in <root>.test1' type=kotlin.String? origin=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value=null
|
||||
then: CONST Int type=kotlin.Int value=0
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CALL 'public open fun <get-length> (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=GET_PROPERTY
|
||||
$this: GET_VAR 'x: kotlin.String? declared in <root>.test1' type=kotlin.String? origin=null
|
||||
FUN name:test2 visibility:public modality:FINAL <T> (x:T of <root>.test2) returnType:kotlin.Int
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.CharSequence?]
|
||||
VALUE_PARAMETER name:x index:0 type:T of <root>.test2
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test2 <T> (x: T of <root>.test2): kotlin.Int declared in <root>'
|
||||
WHEN type=kotlin.Int origin=IF
|
||||
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
|
||||
arg0: GET_VAR 'x: T of <root>.test2 declared in <root>.test2' type=T of <root>.test2 origin=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value=null
|
||||
then: CONST Int type=kotlin.Int value=0
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CALL 'public abstract fun <get-length> (): kotlin.Int declared in kotlin.CharSequence' type=kotlin.Int origin=GET_PROPERTY
|
||||
$this: GET_VAR 'x: T of <root>.test2 declared in <root>.test2' type=T of <root>.test2 origin=null
|
||||
FUN name:test3 visibility:public modality:FINAL <T> (x:kotlin.Any) returnType:kotlin.Int [inline]
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.CharSequence?]
|
||||
VALUE_PARAMETER name:x index:0 type:kotlin.Any
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test3 <T> (x: kotlin.Any): kotlin.Int [inline] declared in <root>'
|
||||
WHEN type=kotlin.Int origin=IF
|
||||
BRANCH
|
||||
if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=T of <root>.test3
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test3' type=kotlin.Any origin=null
|
||||
then: CONST Int type=kotlin.Int value=0
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CALL 'public abstract fun <get-length> (): kotlin.Int declared in kotlin.CharSequence' type=kotlin.Int origin=GET_PROPERTY
|
||||
$this: TYPE_OP type={T of <root>.test3 & Any} origin=IMPLICIT_CAST typeOperand={T of <root>.test3 & Any}
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test3' type=kotlin.Any origin=null
|
||||
FUN name:test4 visibility:public modality:FINAL <T> (x:kotlin.Any?) returnType:kotlin.Int [inline]
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.CharSequence]
|
||||
VALUE_PARAMETER name:x index:0 type:kotlin.Any?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test4 <T> (x: kotlin.Any?): kotlin.Int [inline] declared in <root>'
|
||||
WHEN type=kotlin.Int origin=IF
|
||||
BRANCH
|
||||
if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=T of <root>.test4
|
||||
GET_VAR 'x: kotlin.Any? declared in <root>.test4' type=kotlin.Any? origin=null
|
||||
then: CONST Int type=kotlin.Int value=0
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CALL 'public abstract fun <get-length> (): kotlin.Int declared in kotlin.CharSequence' type=kotlin.Int origin=GET_PROPERTY
|
||||
$this: TYPE_OP type=T of <root>.test4 origin=IMPLICIT_CAST typeOperand=T of <root>.test4
|
||||
GET_VAR 'x: kotlin.Any? declared in <root>.test4' type=kotlin.Any? origin=null
|
||||
FUN name:test5 visibility:public modality:FINAL <T, S> (x:T of <root>.test5, fn:kotlin.Function1<S of <root>.test5, kotlin.Unit>) returnType:kotlin.Unit
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[S of <root>.test5?]
|
||||
TYPE_PARAMETER name:S index:1 variance: superTypes:[kotlin.Any?]
|
||||
VALUE_PARAMETER name:x index:0 type:T of <root>.test5
|
||||
VALUE_PARAMETER name:fn index:1 type:kotlin.Function1<S of <root>.test5, kotlin.Unit>
|
||||
BLOCK_BODY
|
||||
WHEN type=kotlin.Unit origin=IF
|
||||
BRANCH
|
||||
if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ
|
||||
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
|
||||
arg0: GET_VAR 'x: T of <root>.test5 declared in <root>.test5' type=T of <root>.test5 origin=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value=null
|
||||
then: CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=INVOKE
|
||||
$this: GET_VAR 'fn: kotlin.Function1<S of <root>.test5, kotlin.Unit> declared in <root>.test5' type=kotlin.Function1<S of <root>.test5, kotlin.Unit> origin=VARIABLE_AS_FUNCTION
|
||||
p1: GET_VAR 'x: T of <root>.test5 declared in <root>.test5' type=T of <root>.test5 origin=null
|
||||
@@ -0,0 +1,33 @@
|
||||
fun test1(x: String?): Int {
|
||||
return when {
|
||||
EQEQ(arg0 = x, arg1 = null) -> 0
|
||||
else -> x.<get-length>()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : CharSequence?> test2(x: T): Int {
|
||||
return when {
|
||||
EQEQ(arg0 = x, arg1 = null) -> 0
|
||||
else -> x.<get-length>()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : CharSequence?> test3(x: Any): Int {
|
||||
return when {
|
||||
x !is T -> 0
|
||||
else -> x /*as (T & Any) */.<get-length>()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : CharSequence> test4(x: Any?): Int {
|
||||
return when {
|
||||
x !is T -> 0
|
||||
else -> x /*as T */.<get-length>()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : S?, S : Any?> test5(x: T, fn: Function1<S, Unit>) {
|
||||
when {
|
||||
EQEQ(arg0 = x, arg1 = null).not() -> fn.invoke(p1 = x)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
fun test1(x: String?) =
|
||||
if (x == null) 0 else x.length
|
||||
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
FILE fqName:<root> fileName:/implicitCastToTypeParameter.kt
|
||||
FUN name:test1 visibility:public modality:FINAL <T> ($receiver:kotlin.Any) returnType:T of <root>.test1? [inline]
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any]
|
||||
$receiver: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test1 <T> (): T of <root>.test1? [inline] declared in <root>'
|
||||
WHEN type=T of <root>.test1? origin=IF
|
||||
BRANCH
|
||||
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=T of <root>.test1
|
||||
GET_VAR '<this>: kotlin.Any declared in <root>.test1' type=kotlin.Any origin=null
|
||||
then: TYPE_OP type=T of <root>.test1 origin=IMPLICIT_CAST typeOperand=T of <root>.test1
|
||||
GET_VAR '<this>: kotlin.Any declared in <root>.test1' type=kotlin.Any origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CONST Null type=kotlin.Nothing? value=null
|
||||
CLASS INTERFACE name:Foo modality:ABSTRACT visibility:public superTypes:[kotlin.Any]
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Foo<T of <root>.Foo>
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
||||
overridden:
|
||||
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
|
||||
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
|
||||
overridden:
|
||||
public open fun hashCode (): kotlin.Int declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
|
||||
overridden:
|
||||
public open fun toString (): kotlin.String declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
PROPERTY name:asT visibility:public modality:FINAL [val]
|
||||
FUN name:<get-asT> visibility:public modality:FINAL <T> ($receiver:<root>.Foo<T of <root>.<get-asT>>) returnType:T of <root>.<get-asT>? [inline]
|
||||
correspondingProperty: PROPERTY name:asT visibility:public modality:FINAL [val]
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any]
|
||||
$receiver: VALUE_PARAMETER name:<this> type:<root>.Foo<T of <root>.<get-asT>>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun <get-asT> <T> (): T of <root>.<get-asT>? [inline] declared in <root>'
|
||||
WHEN type=T of <root>.<get-asT>? origin=IF
|
||||
BRANCH
|
||||
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=T of <root>.<get-asT>
|
||||
GET_VAR '<this>: <root>.Foo<T of <root>.<get-asT>> declared in <root>.<get-asT>' type=<root>.Foo<T of <root>.<get-asT>> origin=null
|
||||
then: TYPE_OP type=T of <root>.<get-asT> origin=IMPLICIT_CAST typeOperand=T of <root>.<get-asT>
|
||||
GET_VAR '<this>: <root>.Foo<T of <root>.<get-asT>> declared in <root>.<get-asT>' type=<root>.Foo<T of <root>.<get-asT>> origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CONST Null type=kotlin.Nothing? value=null
|
||||
CLASS CLASS name:Bar modality:FINAL visibility:public superTypes:[kotlin.Any]
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Bar<T of <root>.Bar>
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
CONSTRUCTOR visibility:public <> () returnType:<root>.Bar<T of <root>.Bar> [primary]
|
||||
BLOCK_BODY
|
||||
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Bar modality:FINAL visibility:public superTypes:[kotlin.Any]'
|
||||
FUN name:test visibility:public modality:FINAL <> ($this:<root>.Bar<T of <root>.Bar>, arg:kotlin.Any) returnType:kotlin.Unit
|
||||
$this: VALUE_PARAMETER name:<this> type:<root>.Bar<T of <root>.Bar>
|
||||
VALUE_PARAMETER name:arg index:0 type:kotlin.Any
|
||||
BLOCK_BODY
|
||||
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
|
||||
TYPE_OP type=T of <root>.Bar origin=CAST typeOperand=T of <root>.Bar
|
||||
GET_VAR 'arg: kotlin.Any declared in <root>.Bar.test' type=kotlin.Any origin=null
|
||||
CALL 'public final fun useT (t: T of <root>.Bar): kotlin.Unit declared in <root>.Bar' type=kotlin.Unit origin=null
|
||||
$this: GET_VAR '<this>: <root>.Bar<T of <root>.Bar> declared in <root>.Bar.test' type=<root>.Bar<T of <root>.Bar> origin=null
|
||||
t: TYPE_OP type={T of <root>.Bar & Any} origin=IMPLICIT_CAST typeOperand={T of <root>.Bar & Any}
|
||||
GET_VAR 'arg: kotlin.Any declared in <root>.Bar.test' type=kotlin.Any origin=null
|
||||
FUN name:useT visibility:public modality:FINAL <> ($this:<root>.Bar<T of <root>.Bar>, t:T of <root>.Bar) returnType:kotlin.Unit
|
||||
$this: VALUE_PARAMETER name:<this> type:<root>.Bar<T of <root>.Bar>
|
||||
VALUE_PARAMETER name:t index:0 type:T of <root>.Bar
|
||||
BLOCK_BODY
|
||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
||||
overridden:
|
||||
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
|
||||
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
|
||||
overridden:
|
||||
public open fun hashCode (): kotlin.Int declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
|
||||
overridden:
|
||||
public open fun toString (): kotlin.String declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
inline fun <reified T : Any> Any.test1(): T? {
|
||||
return when {
|
||||
<this> is T -> <this> /*as T */
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
interface Foo<T : Any?> {
|
||||
|
||||
}
|
||||
|
||||
val <reified T : Any> Foo<T>.asT: T?
|
||||
inline get(): T? {
|
||||
return when {
|
||||
<this> is T -> <this> /*as T */
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
class Bar<T : Any?> {
|
||||
constructor() /* primary */ {
|
||||
super/*Any*/()
|
||||
/* <init>() */
|
||||
|
||||
}
|
||||
|
||||
fun test(arg: Any) {
|
||||
arg as T /*~> Unit */
|
||||
<this>.useT(t = arg /*as (T & Any) */)
|
||||
}
|
||||
|
||||
fun useT(t: T) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
inline fun <reified T : Any> Any.test1(): T? =
|
||||
if (this is T) this else null
|
||||
|
||||
|
||||
Reference in New Issue
Block a user