Files
kotlin-fork/compiler/testData/ir/irText/expressions/when.txt
T
Pavel Kirpichenkov 07ca355af8 [NI] Fix smartcasts for conventional contains in when
Call argument for conventional `contains` after expanding `in` may come from a `when` subject during its branch analysis.
In this case data flow info from a previous when branch was not considered,
because data flow info for subject had been used instead of data flow before argument.
Use of the latter one for the conventional `contains` solves the issue.

The old FE uses `isExternal` property of value arguments to skip smartcast reporting on `when` subject,
if they come from branches. To prevent undesired smartcasts on `when` subject after branch analysis in the new FE,
`isExternal` arguments are skipped in diagnostic reporter and during recorded type update.

Also, the new FE interprets `isExternal` completely differently from the old FE.
In the old FE this property is used exclusively by `when` with subject.
In the new FE it is also used for parially resolved calls, lambda return arguments and receivers.
This may be preventing the use of data flow info before argument in the first place, but this assumption requires additional investigation.

^KT-36818 Fixed
2020-02-20 19:07:54 +03:00

167 lines
13 KiB
Plaintext
Vendored

FILE fqName:<root> fileName:/when.kt
CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.A
CONSTRUCTOR visibility:private <> () returnType:<root>.A [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS OBJECT name:A modality:FINAL visibility:public 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
FUN name:testWithSubject visibility:public modality:FINAL <> (x:kotlin.Any?) returnType:kotlin.String
VALUE_PARAMETER name:x index:0 type:kotlin.Any?
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testWithSubject (x: kotlin.Any?): kotlin.String declared in <root>'
BLOCK type=kotlin.String origin=WHEN
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Any? [val]
GET_VAR 'x: kotlin.Any? declared in <root>.testWithSubject' type=kotlin.Any? origin=null
WHEN type=kotlin.String origin=WHEN
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 'val tmp_0: kotlin.Any? [val] declared in <root>.testWithSubject' type=kotlin.Any? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: CONST String type=kotlin.String value="null"
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 'val tmp_0: kotlin.Any? [val] declared in <root>.testWithSubject' type=kotlin.Any? origin=null
arg1: GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
then: CONST String type=kotlin.String value="A"
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String
GET_VAR 'val tmp_0: kotlin.Any? [val] declared in <root>.testWithSubject' type=kotlin.Any? origin=null
then: CONST String type=kotlin.String value="String"
BRANCH
if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCL
$this: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Number
GET_VAR 'val tmp_0: kotlin.Any? [val] declared in <root>.testWithSubject' type=kotlin.Any? origin=null
then: CONST String type=kotlin.String value="!Number"
BRANCH
if: CALL 'public final fun contains <T> (element: T of kotlin.collections.contains): kotlin.Boolean [operator] declared in kotlin.collections' type=kotlin.Boolean origin=IN
<T>: kotlin.Number
$receiver: CALL 'public final fun setOf <T> (): kotlin.collections.Set<T of kotlin.collections.setOf> [inline] declared in kotlin.collections' type=kotlin.collections.Set<kotlin.Nothing> origin=null
<T>: kotlin.Nothing
element: TYPE_OP type=kotlin.Number origin=IMPLICIT_CAST typeOperand=kotlin.Number
GET_VAR 'val tmp_0: kotlin.Any? [val] declared in <root>.testWithSubject' type=kotlin.Any? origin=null
then: CONST String type=kotlin.String value="nothingness?"
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST String type=kotlin.String value="something"
FUN name:test visibility:public modality:FINAL <> (x:kotlin.Any?) returnType:kotlin.String
VALUE_PARAMETER name:x index:0 type:kotlin.Any?
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test (x: kotlin.Any?): kotlin.String declared in <root>'
WHEN type=kotlin.String origin=WHEN
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.Any? declared in <root>.test' type=kotlin.Any? origin=null
arg1: CONST Null type=kotlin.Nothing? value=null
then: CONST String type=kotlin.String value="null"
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.Any? declared in <root>.test' type=kotlin.Any? origin=null
arg1: GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
then: CONST String type=kotlin.String value="A"
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String
GET_VAR 'x: kotlin.Any? declared in <root>.test' type=kotlin.Any? origin=null
then: CONST String type=kotlin.String value="String"
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=kotlin.Number
GET_VAR 'x: kotlin.Any? declared in <root>.test' type=kotlin.Any? origin=null
then: CONST String type=kotlin.String value="!Number"
BRANCH
if: CALL 'public final fun contains <T> (element: T of kotlin.collections.contains): kotlin.Boolean [operator] declared in kotlin.collections' type=kotlin.Boolean origin=IN
<T>: kotlin.Number
$receiver: CALL 'public final fun setOf <T> (): kotlin.collections.Set<T of kotlin.collections.setOf> [inline] declared in kotlin.collections' type=kotlin.collections.Set<kotlin.Nothing> origin=null
<T>: kotlin.Nothing
element: TYPE_OP type=kotlin.Number origin=IMPLICIT_CAST typeOperand=kotlin.Number
GET_VAR 'x: kotlin.Any? declared in <root>.test' type=kotlin.Any? origin=null
then: CONST String type=kotlin.String value="nothingness?"
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST String type=kotlin.String value="something"
FUN name:testComma visibility:public modality:FINAL <> (x:kotlin.Int) returnType:kotlin.String
VALUE_PARAMETER name:x index:0 type:kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun testComma (x: kotlin.Int): kotlin.String declared in <root>'
BLOCK type=kotlin.String origin=WHEN
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val]
GET_VAR 'x: kotlin.Int declared in <root>.testComma' type=kotlin.Int origin=null
WHEN type=kotlin.String origin=WHEN
BRANCH
if: WHEN type=kotlin.Boolean origin=WHEN_COMMA
BRANCH
if: WHEN type=kotlin.Boolean origin=WHEN_COMMA
BRANCH
if: WHEN type=kotlin.Boolean origin=WHEN_COMMA
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 'val tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=1
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: 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 'val tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=2
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: 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 'val tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=3
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: 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 'val tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=4
then: CONST String type=kotlin.String value="1234"
BRANCH
if: WHEN type=kotlin.Boolean origin=WHEN_COMMA
BRANCH
if: WHEN type=kotlin.Boolean origin=WHEN_COMMA
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 'val tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=5
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: 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 'val tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=6
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: 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 'val tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=7
then: CONST String type=kotlin.String value="567"
BRANCH
if: WHEN type=kotlin.Boolean origin=WHEN_COMMA
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 'val tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=8
then: CONST Boolean type=kotlin.Boolean value=true
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: 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 'val tmp_1: kotlin.Int [val] declared in <root>.testComma' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=9
then: CONST String type=kotlin.String value="89"
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST String type=kotlin.String value="?"