[FIR] Transform annotations of type refs in body resolve stage

Also fix building CFG for annotation calls
This commit is contained in:
Dmitriy Novozhilov
2021-04-12 18:51:15 +03:00
committed by TeamCityServer
parent aec13defc4
commit 1f0ecade34
25 changed files with 96 additions and 45 deletions
@@ -5,7 +5,7 @@ interface I {
} }
class A { class A {
fun too(): @Annotation Unit {} fun too(): <!NOT_AN_ANNOTATION_CLASS, NOT_AN_ANNOTATION_CLASS!>@Annotation<!> Unit {}
fun foo(): <!REDUNDANT_RETURN_UNIT_TYPE!>Unit<!> fun foo(): <!REDUNDANT_RETURN_UNIT_TYPE!>Unit<!>
{ {
@@ -69,9 +69,9 @@ FILE: main.kt
public get(): R|kotlin/String| public get(): R|kotlin/String|
} }
@R|annotations/WithString|(String(xyz)) public final class Second : @R|annotations/WithInt|(IntegerLiteral(0)) R|test/First| { @R|annotations/WithString|(String(xyz)) public final class Second : @R|annotations/WithInt|(Int(0)) R|test/First| {
public constructor(y: R|kotlin/Char|): R|test/Second| { public constructor(y: R|kotlin/Char|): R|test/Second| {
super<@R|annotations/WithInt|(IntegerLiteral(0)) R|test/First|>() super<@R|annotations/WithInt|(Int(0)) R|test/First|>()
} }
public final val y: R|kotlin/Char| = R|<local>/y| public final val y: R|kotlin/Char| = R|<local>/y|
@@ -61,12 +61,14 @@ open class FirBodyResolveTransformer(
} }
override fun transformTypeRef(typeRef: FirTypeRef, data: ResolutionMode): FirResolvedTypeRef { override fun transformTypeRef(typeRef: FirTypeRef, data: ResolutionMode): FirResolvedTypeRef {
if (typeRef is FirResolvedTypeRef) { val resolvedTypeRef = if (typeRef is FirResolvedTypeRef) {
return typeRef typeRef
} } else {
return typeResolverTransformer.withFile(context.file) { typeResolverTransformer.withFile(context.file) {
transformTypeRef(typeRef, FirCompositeScope(components.createCurrentScopeList())) transformTypeRef(typeRef, FirCompositeScope(components.createCurrentScopeList()))
}
} }
return resolvedTypeRef.transformAnnotations(this, data)
} }
override fun transformImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: ResolutionMode): FirTypeRef { override fun transformImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: ResolutionMode): FirTypeRef {
@@ -782,14 +782,15 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
annotationCall: FirAnnotationCall, annotationCall: FirAnnotationCall,
status: FirAnnotationResolveStatus status: FirAnnotationResolveStatus
): FirAnnotationCall { ): FirAnnotationCall {
dataFlowAnalyzer.enterAnnotationCall(annotationCall)
return withFirArrayOfCallTransformer { return withFirArrayOfCallTransformer {
annotationCall.transformAnnotationTypeRef(transformer, ResolutionMode.ContextIndependent) annotationCall.transformAnnotationTypeRef(transformer, ResolutionMode.ContextIndependent)
if (status == FirAnnotationResolveStatus.PartiallyResolved) return annotationCall if (status == FirAnnotationResolveStatus.PartiallyResolved) return annotationCall
val result = callResolver.resolveAnnotationCall(annotationCall) ?: return annotationCall dataFlowAnalyzer.enterAnnotationCall(annotationCall)
val result = callResolver.resolveAnnotationCall(annotationCall)
dataFlowAnalyzer.exitAnnotationCall(result ?: annotationCall)
if (result == null) return annotationCall
callCompleter.completeCall(result, noExpectedType) callCompleter.completeCall(result, noExpectedType)
result.replaceResolveStatus(status) result.replaceResolveStatus(status)
dataFlowAnalyzer.exitAnnotationCall(result)
annotationCall annotationCall
} }
} }
@@ -4,10 +4,10 @@
@Target(AnnotationTarget.TYPE) @Target(AnnotationTarget.TYPE)
annotation class Anno(val value: String) annotation class Anno(val value: String)
fun foo(x: String): @Anno(Lorem, ipsum::class, "dolor", sit-amet) String { // OK fun foo(x: String): @Anno(<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>Lorem<!>, <!TOO_MANY_ARGUMENTS, TOO_MANY_ARGUMENTS!><!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>ipsum<!>::class<!>, <!TOO_MANY_ARGUMENTS, TOO_MANY_ARGUMENTS!>"dolor"<!>, <!TOO_MANY_ARGUMENTS, TOO_MANY_ARGUMENTS!><!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>sit<!>-<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>amet<!><!>) String { // OK
return x return x
} }
abstract class Foo : @Anno(o_O) Throwable() // OK abstract class Foo : @Anno(<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>o_O<!>) Throwable() // OK
abstract class Bar<T : @Anno(O_o) Any> // OK abstract class Bar<T : @Anno(<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>O_o<!>) Any> // OK
@@ -6,7 +6,7 @@ interface B : A
interface C : A interface C : A
@Suppress("INVISIBLE_REFERENCE") @Suppress("INVISIBLE_REFERENCE")
fun <K> select(x: K, y: K): @kotlin.internal.Exact K = x fun <K> select(x: K, y: K): <!HIDDEN, HIDDEN!>@kotlin.internal.Exact<!> K = x
fun foo(a: Any) {} fun foo(a: Any) {}
@@ -6,7 +6,7 @@ interface B : A
interface C : A interface C : A
@Suppress("INVISIBLE_REFERENCE") @Suppress("INVISIBLE_REFERENCE")
fun <K> select(x: K, y: K): @kotlin.internal.Exact K = x fun <K> select(x: K, y: K): <!HIDDEN, HIDDEN!>@kotlin.internal.Exact<!> K = x
fun foo(a: Any) {} fun foo(a: Any) {}
@@ -6,7 +6,7 @@ interface ISample
fun <K> elvisSimple(x: K?, y: K): K = y fun <K> elvisSimple(x: K?, y: K): K = y
@Suppress("INVISIBLE_REFERENCE") @Suppress("INVISIBLE_REFERENCE")
fun <K> elvisExact(x: K?, y: K): @kotlin.internal.Exact K = y fun <K> elvisExact(x: K?, y: K): <!HIDDEN, HIDDEN!>@kotlin.internal.Exact<!> K = y
fun <T : Number> materialize(): T? = TODO() fun <T : Number> materialize(): T? = TODO()
@@ -6,7 +6,7 @@ interface ISample
fun <K> elvisSimple(x: K?, y: K): K = y fun <K> elvisSimple(x: K?, y: K): K = y
@Suppress("INVISIBLE_REFERENCE") @Suppress("INVISIBLE_REFERENCE")
fun <K> elvisExact(x: K?, y: K): @kotlin.internal.Exact K = y fun <K> elvisExact(x: K?, y: K): <!HIDDEN, HIDDEN!>@kotlin.internal.Exact<!> K = y
fun <T : Number> materialize(): T? = null fun <T : Number> materialize(): T? = null
fun <T> Any?.materialize(): T = null as T fun <T> Any?.materialize(): T = null as T
@@ -6,7 +6,7 @@
import kotlin.internal.Exact import kotlin.internal.Exact
class Inv<I>(val arg: I) class Inv<I>(val arg: I)
class InvExact<E>(val arg: @kotlin.internal.Exact E) class InvExact<E>(val arg: <!HIDDEN, HIDDEN!>@kotlin.internal.Exact<!> E)
interface Base interface Base
class Derived : Base class Derived : Base
@@ -0,0 +1,20 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// FILE: Foo.java
public class Foo {
public static <K, V> void create(java.util.Map<? extends K, ? extends V> m) { return null; }
}
// FILE: test.kt
fun test(properties: Map<String, String>, nullableProperties: Map<String, String>?) {
val f1 = Foo.create(select1(properties, myEmptyMap()))
val f2 = Foo.create(nullableProperties ?: myEmptyMap())
}
fun <T, R> myEmptyMap(): Map<T, R> = TODO()
@Suppress("INVISIBLE_REFERENCE")
fun <S> select1(x: S, y: S): <!HIDDEN, HIDDEN!>@kotlin.internal.Exact<!> S = y
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// !LANGUAGE: +NewInference // !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
@@ -18,4 +17,4 @@ fun test(properties: Map<String, String>, nullableProperties: Map<String, String
fun <T, R> myEmptyMap(): Map<T, R> = TODO() fun <T, R> myEmptyMap(): Map<T, R> = TODO()
@Suppress("INVISIBLE_REFERENCE") @Suppress("INVISIBLE_REFERENCE")
fun <S> select1(x: S, y: S): @kotlin.internal.Exact S = y fun <S> select1(x: S, y: S): @kotlin.internal.Exact S = y
@@ -0,0 +1,30 @@
//!DIAGNOSTICS: -UNUSED_PARAMETER
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <R> Iterable<*>.filterIsInstance1(): List<@kotlin.internal.NoInfer R> = throw Exception()
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <R> List<*>.filterIsInstance2(): <!HIDDEN, HIDDEN!>@kotlin.internal.NoInfer<!> List<R> = throw Exception()
fun test(list: List<Int>) {
list.filterIsInstance1<Int>().map { it * 2 }
list.filterIsInstance2<Int>().filter { it > 10 }
}
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <R> foo(t: R): List<@kotlin.internal.NoInfer R> = throw Exception("$t")
fun test() {
foo(1).map { it * 2 }
}
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <R> List<R>.foo(): <!HIDDEN, HIDDEN!>@kotlin.internal.NoInfer<!> R = throw Exception()
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <R> bar(r: R, f: Function1<@kotlin.internal.NoInfer R, Unit>): Nothing = throw Exception()
fun test1() {
listOf("").foo().length
bar(1) { x -> x + 1 }
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
//!DIAGNOSTICS: -UNUSED_PARAMETER //!DIAGNOSTICS: -UNUSED_PARAMETER
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@@ -28,4 +27,4 @@ fun <R> bar(r: R, f: Function1<@kotlin.internal.NoInfer R, Unit>): Nothing = thr
fun test1() { fun test1() {
listOf("").foo().length listOf("").foo().length
bar(1) { x -> x + 1 } bar(1) { x -> x + 1 }
} }
@@ -7,7 +7,7 @@
public fun <T> Iterable<T>.contains1(element: T): Int<!> = null!! public fun <T> Iterable<T>.contains1(element: T): Int<!> = null!!
<!CONFLICTING_OVERLOADS!>@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") <!CONFLICTING_OVERLOADS!>@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public fun <T> Iterable<T>.contains1(element: @kotlin.internal.NoInfer T): Boolean<!> = null!! public fun <T> Iterable<T>.contains1(element: <!HIDDEN, HIDDEN!>@kotlin.internal.NoInfer<!> T): Boolean<!> = null!!
fun test() { fun test() {
@@ -2,13 +2,13 @@
// !WITH_NEW_INFERENCE // !WITH_NEW_INFERENCE
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <T> test1(t1: T, t2: @kotlin.internal.NoInfer T): T = t1 fun <T> test1(t1: T, t2: <!HIDDEN, HIDDEN!>@kotlin.internal.NoInfer<!> T): T = t1
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <T> @kotlin.internal.NoInfer T.test2(t1: T): T = t1 fun <T> <!HIDDEN, HIDDEN!>@kotlin.internal.NoInfer<!> T.test2(t1: T): T = t1
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <T> test3(t1: @kotlin.internal.NoInfer T): T = t1 fun <T> test3(t1: <!HIDDEN, HIDDEN!>@kotlin.internal.NoInfer<!> T): T = t1
fun usage() { fun usage() {
test1(1, "312") test1(1, "312")
@@ -17,7 +17,7 @@ fun usage() {
} }
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <T> List<T>.contains1(e: @kotlin.internal.NoInfer T): Boolean = true fun <T> List<T>.contains1(e: <!HIDDEN, HIDDEN!>@kotlin.internal.NoInfer<!> T): Boolean = true
fun test(i: Int?, a: Any, l: List<Int>) { fun test(i: Int?, a: Any, l: List<Int>) {
l.contains1(a) l.contains1(a)
@@ -26,7 +26,7 @@ fun test(i: Int?, a: Any, l: List<Int>) {
} }
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <T> assertEquals1(e1: T, e2: @kotlin.internal.NoInfer T): Boolean = true fun <T> assertEquals1(e1: T, e2: <!HIDDEN, HIDDEN!>@kotlin.internal.NoInfer<!> T): Boolean = true
fun test(s: String) { fun test(s: String) {
assertEquals1(s, 11) assertEquals1(s, 11)
@@ -2,7 +2,7 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
private object TopLevelTypeVariable { private object TopLevelTypeVariable {
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "HIDDEN")
fun <T> foo(): @kotlin.internal.NoInfer T = TODO() fun <T> foo(): @kotlin.internal.NoInfer T = TODO()
fun <K> bar(k: K) {} fun <K> bar(k: K) {}
@@ -15,7 +15,7 @@ private object TopLevelTypeVariable {
private object NestedTypeVariable { private object NestedTypeVariable {
class Inv<T> class Inv<T>
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "HIDDEN")
fun <T> foo(): Inv<@kotlin.internal.NoInfer T> = TODO() fun <T> foo(): Inv<@kotlin.internal.NoInfer T> = TODO()
fun <K> bar(p: Inv<K>) {} fun <K> bar(p: Inv<K>) {}
@@ -23,4 +23,4 @@ private object NestedTypeVariable {
fun test() { fun test() {
bar(foo<String>()) bar(foo<String>())
} }
} }
@@ -4,7 +4,7 @@ private object NestedTypeVariable {
private constructor NestedTypeVariable() private constructor NestedTypeVariable()
public final fun </*0*/ K> bar(/*0*/ p: NestedTypeVariable.Inv<K>): kotlin.Unit public final fun </*0*/ K> bar(/*0*/ p: NestedTypeVariable.Inv<K>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public final fun </*0*/ T> foo(): NestedTypeVariable.Inv<T> @kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "HIDDEN"}) public final fun </*0*/ T> foo(): NestedTypeVariable.Inv<T>
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun test(): kotlin.Unit public final fun test(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@@ -21,7 +21,7 @@ private object TopLevelTypeVariable {
private constructor TopLevelTypeVariable() private constructor TopLevelTypeVariable()
public final fun </*0*/ K> bar(/*0*/ k: K): kotlin.Unit public final fun </*0*/ K> bar(/*0*/ k: K): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public final fun </*0*/ T> foo(): T @kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "HIDDEN"}) public final fun </*0*/ T> foo(): T
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun test(): kotlin.Unit public final fun test(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@@ -2,6 +2,6 @@
@Target(AnnotationTarget.TYPE) @Target(AnnotationTarget.TYPE)
annotation class Ann(val x: Int) annotation class Ann(val x: Int)
fun case_1(x: String): @Ann(unresolved_reference) String { fun case_1(x: String): @Ann(<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>unresolved_reference<!>) String {
return x return x
} }
@@ -5,4 +5,4 @@
@Target(AnnotationTarget.TYPE) @Target(AnnotationTarget.TYPE)
annotation class Ann(val x: Int) annotation class Ann(val x: Int)
abstract class Foo : @Ann(unresolved_reference) Any() abstract class Foo : @Ann(<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>unresolved_reference<!>) Any()
@@ -8,7 +8,7 @@ annotation class Ann(val x: Int)
fun foo(i: Inv<@Ann(unresolved_reference) String>) {} fun foo(i: Inv<@Ann(unresolved_reference) String>) {}
// TESTCASE NUMBER: 2 // TESTCASE NUMBER: 2
fun test(vararg a: @Ann(unresolved_reference) Any) {} fun test(vararg a: @Ann(<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>unresolved_reference<!>) Any) {}
// TESTCASE NUMBER: 3 // TESTCASE NUMBER: 3
class A<T>(a: @Ann(unresolved_reference) T) class A<T>(a: @Ann(<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>unresolved_reference<!>) T)
@@ -3,7 +3,7 @@
annotation class Ann(val x: Int) annotation class Ann(val x: Int)
// TESTCASE NUMBER: 1 // TESTCASE NUMBER: 1
abstract class Bar<T : @Ann(unresolved_reference) Any> abstract class Bar<T : @Ann(<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>unresolved_reference<!>) Any>
/* /*
* TESTCASE NUMBER: 2 * TESTCASE NUMBER: 2
@@ -10,7 +10,7 @@ annotation class Ann(val x: Int)
* UNEXPECTED BEHAVIOUR * UNEXPECTED BEHAVIOUR
*/ */
fun case_1(a: Any) { fun case_1(a: Any) {
if (a is @Ann(unresolved_reference) String) return if (a is @Ann(<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>unresolved_reference<!>) String) return
} }
/* /*
@@ -18,7 +18,7 @@ fun case_1(a: Any) {
* UNEXPECTED BEHAVIOUR * UNEXPECTED BEHAVIOUR
*/ */
fun case_2(a: Any) { fun case_2(a: Any) {
a as @Ann(unresolved_reference) String // OK, no error in IDE and in the compiler a as @Ann(<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>unresolved_reference<!>) String // OK, no error in IDE and in the compiler
} }
/* /*
@@ -28,10 +28,10 @@ fun case_2(a: Any) {
fun case_3_1(a: Any) {} fun case_3_1(a: Any) {}
fun case_3_2(a: Any) { fun case_3_2(a: Any) {
case_3_1(a as @Ann(unresolved_reference) String) // OK, no error in IDE and in the compiler case_3_1(a as @Ann(<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>unresolved_reference<!>) String) // OK, no error in IDE and in the compiler
} }
// TESTCASE NUMBER: 4 // TESTCASE NUMBER: 4
fun case_4(a: Any) { fun case_4(a: Any) {
val x = a as @Ann(unresolved_reference) String // ERROR, has error in IDE and in the compiler val x = a as @Ann(<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>unresolved_reference<!>) String // ERROR, has error in IDE and in the compiler
} }
@@ -18,4 +18,4 @@ val case_1 = object : TypeToken<@Ann(unresolved_reference) String>() {}
*/ */
interface A interface A
val case_2 = object: @Ann(unresolved_reference) A {} val case_2 = object: @Ann(<!TOO_MANY_ARGUMENTS, TOO_MANY_ARGUMENTS, TOO_MANY_ARGUMENTS, TOO_MANY_ARGUMENTS, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>unresolved_reference<!>) A {}
@@ -9,4 +9,4 @@ annotation class Ann
var <T> T.test var <T> T.test
get() = 11 get() = 11
set(value: @Ann(unresolved_reference) Int) {} set(value: @Ann(<!TOO_MANY_ARGUMENTS, TOO_MANY_ARGUMENTS, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>unresolved_reference<!>) Int) {}