FIR: report ENUM_ENTRY_AS_TYPE and IS_ENUM_TYPE

These two diagnostics are similar: both are reported on type references
to enum entries. But `IS_ENUM_TYPE` is reported if the type ref is an
operand of `is` operator. To pass along this contextual information, a
boolean is added to FirSpecificTypeResolverTransformer.
This commit is contained in:
Tianyu Geng
2021-06-08 15:14:41 -07:00
committed by Mikhail Glukhikh
parent 6dc75c2e51
commit c648356887
18 changed files with 157 additions and 45 deletions
+22 -22
View File
@@ -6,49 +6,49 @@ enum class Color {
}
}
class MyColor(val x: <!UNRESOLVED_REFERENCE!>Color.RED<!>, y: <!UNRESOLVED_REFERENCE!>Color.RED<!>) : <!UNRESOLVED_REFERENCE!>Color.RED<!> {
class MyColor(val x: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>, y: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>) : <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> {
var z: <!UNRESOLVED_REFERENCE!>Color.RED<!> = Color.RED
set(arg: <!UNRESOLVED_REFERENCE!>Color.RED<!>) { z = arg }
var z: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> = Color.RED
set(arg: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>) { z = arg }
fun foo(arg: <!UNRESOLVED_REFERENCE!>Color.RED<!>): <!UNRESOLVED_REFERENCE!>Color.RED<!> = arg
fun foo(arg: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>): <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> = arg
fun bar(): <!UNRESOLVED_REFERENCE!>Color.RED<!> {
class Local : <!UNRESOLVED_REFERENCE!>Color.RED<!>
fun local(arg: <!UNRESOLVED_REFERENCE!>Color.RED<!>): <!UNRESOLVED_REFERENCE!>Color.RED<!> = arg
val temp: <!UNRESOLVED_REFERENCE!>Color.RED<!> = Color.RED
temp as? <!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>Color.RED<!>
if (temp is <!UNRESOLVED_REFERENCE!>Color.RED<!>) {
return temp as <!UNRESOLVED_REFERENCE!>Color.RED<!>
fun bar(): <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> {
class Local : <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>
fun local(arg: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>): <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> = arg
val temp: <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> = Color.RED
temp as? <!ENUM_ENTRY_AS_TYPE, ENUM_ENTRY_AS_TYPE!>Color.RED<!>
if (temp is <!IS_ENUM_ENTRY!>Color.RED<!>) {
return temp as <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>
}
val obj = object : <!UNRESOLVED_REFERENCE!>Color.RED<!> {}
if (obj is <!UNRESOLVED_REFERENCE!>Color.RED<!>) {
val obj = object : <!ENUM_ENTRY_AS_TYPE!>Color.RED<!> {}
if (obj is <!IS_ENUM_ENTRY!>Color.RED<!>) {
return obj
}
return Color.RED
}
}
fun create(): Array<<!UNRESOLVED_REFERENCE!>Color.RED<!>>? = null
fun create(): Array<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>? = null
interface Your<T : <!UNRESOLVED_REFERENCE!>Color.RED<!>>
interface Your<T : <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>
class His : Your<<!UNRESOLVED_REFERENCE!>Color.RED<!>>
class His : Your<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>
fun <T : <!UNRESOLVED_REFERENCE!>Color.RED<!>> otherCreate(): Array<T>? = null
fun <T : <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>> otherCreate(): Array<T>? = null
typealias RedAlias = <!UNRESOLVED_REFERENCE!>Color.RED<!>
typealias RedAlias = <!ENUM_ENTRY_AS_TYPE!>Color.RED<!>
typealias ArrayOfEnumEntry = Array<<!UNRESOLVED_REFERENCE!>Color.RED<!>>
typealias ArrayOfEnumEntry = Array<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>
typealias ArrayOfEnumEntryAlias = Array<RedAlias>
fun <T> bar(a: Any): T = a as T
fun <T> foo() {
foo<<!UNRESOLVED_REFERENCE!>Color.RED<!>>()
foo<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>()
foo<<!CANNOT_INFER_PARAMETER_TYPE!>RedAlias<!>>()
bar<<!UNRESOLVED_REFERENCE!>Color.RED<!>>(<!ARGUMENT_TYPE_MISMATCH!>Color.RED<!>)
bar<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>(<!ARGUMENT_TYPE_MISMATCH!>Color.RED<!>)
}
fun Array<<!UNRESOLVED_REFERENCE!>Color.RED<!>>.foo(entries: Array<<!UNRESOLVED_REFERENCE!>Color.RED<!>>): Array<<!UNRESOLVED_REFERENCE!>Color.RED<!>> = null!!
fun Array<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>.foo(entries: Array<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>>): Array<<!ENUM_ENTRY_AS_TYPE!>Color.RED<!>> = null!!
@@ -3,4 +3,4 @@ enum class MyEnum {
SECOND
}
fun foo(me: MyEnum): Boolean = if (me is <!UNRESOLVED_REFERENCE!>MyEnum.FIRST<!>) true else false
fun foo(me: MyEnum): Boolean = if (me is <!IS_ENUM_ENTRY!>MyEnum.FIRST<!>) true else false
@@ -2,4 +2,4 @@ enum class E {
ENTRY
}
class A : <!UNRESOLVED_REFERENCE!>E.ENTRY<!>
class A : <!ENUM_ENTRY_AS_TYPE!>E.ENTRY<!>
@@ -3,4 +3,4 @@ enum class MyEnum {
SECOND
}
fun foo(me: MyEnum): Boolean = me is <!UNRESOLVED_REFERENCE!>MyEnum.FIRST<!>
fun foo(me: MyEnum): Boolean = me is <!IS_ENUM_ENTRY!>MyEnum.FIRST<!>
@@ -13,8 +13,8 @@ enum class MyEnum {
fun foo(x: MyEnum): Int {
return <!NO_ELSE_IN_WHEN!>when<!> (x) {
is <!UNRESOLVED_REFERENCE!>MyEnum.A<!> -> 1
is <!UNRESOLVED_REFERENCE!>MyEnum.B<!> -> 2
is <!UNRESOLVED_REFERENCE!>MyEnum.C<!> -> 3
is <!IS_ENUM_ENTRY!>MyEnum.A<!> -> 1
is <!IS_ENUM_ENTRY!>MyEnum.B<!> -> 2
is <!IS_ENUM_ENTRY!>MyEnum.C<!> -> 3
}
}
@@ -15,7 +15,7 @@ enum class MyEnum {
fun foo(x: MyEnum): Int {
return <!NO_ELSE_IN_WHEN!>when<!> (x) {
MyEnum.A -> 1
is <!UNRESOLVED_REFERENCE!>MyEnum.B<!> -> 2
is <!UNRESOLVED_REFERENCE!>MyEnum.C<!> -> 3
is <!IS_ENUM_ENTRY!>MyEnum.B<!> -> 2
is <!IS_ENUM_ENTRY!>MyEnum.C<!> -> 3
}
}