IR: fix capturing of type parameters in local functions

collectPotentiallyCapturedTypeParameters no longer stops on the first
class when going through parents. This is needed because otherwise type
parameters of the containing class, and its outer classes, were never
considered "captured", and thus not duplicated/remapped later in
LocalDeclarationsLowering.

This led to the IR where a local function referenced generic type
parameters of the outer class. On JVM, local function is generated into
a private static function in that container class, and static functions
can't use generic type parameters, which crashed some bytecode
processing tools.

Also, add another explicit call to `seeType` to cover references to
generic type parameters in function return types.

 #KT-45941 Fixed
This commit is contained in:
Alexander Udalov
2021-04-28 17:40:11 +02:00
parent b389fd6667
commit c14a890e7e
12 changed files with 224 additions and 12 deletions
@@ -0,0 +1,8 @@
// WITH_SIGNATURES
class A<T>(val result: T) {
fun f(): T {
fun g(): T = result
return g()
}
}
@@ -0,0 +1,19 @@
@kotlin.Metadata
final class<Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function0<TT;>;> A$f$1 {
// source: 'genericClass.kt'
public final <()TT;> method invoke(): java.lang.Object
<null> method <init>(p0: A): void
enclosing method A.f()Ljava/lang/Object;
synthetic final field <null> this$0: A
inner (anonymous) class A$f$1
}
@kotlin.Metadata
public final class<<T:Ljava/lang/Object;>Ljava/lang/Object;> A {
// source: 'genericClass.kt'
public final <()TT;> method f(): java.lang.Object
public final <()TT;> method getResult(): java.lang.Object
public <(TT;)V> method <init>(p0: java.lang.Object): void
private final field <TT;> result: java.lang.Object
inner (anonymous) class A$f$1
}
@@ -0,0 +1,9 @@
@kotlin.Metadata
public final class<<T:Ljava/lang/Object;>Ljava/lang/Object;> A {
// source: 'genericClass.kt'
public final <()TT;> method f(): java.lang.Object
public final <()TT;> method getResult(): java.lang.Object
public <(TT;)V> method <init>(p0: java.lang.Object): void
private final static <<T:Ljava/lang/Object;>(LA<TT;>;)TT;> method f$g(p0: A): java.lang.Object
private final field <TT;> result: java.lang.Object
}
@@ -0,0 +1,11 @@
// WITH_SIGNATURES
class A<T>(val result: T) {
inner class B {
inner class C {
fun f() {
fun g(t: T) {}
}
}
}
}
@@ -0,0 +1,42 @@
@kotlin.Metadata
final class<Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function1<TT;Lkotlin/Unit;>;> A$B$C$f$1 {
// source: 'genericInnerClass.kt'
public final <(TT;)V> method invoke(p0: java.lang.Object): void
static <null> method <clinit>(): void
<null> method <init>(): void
public synthetic bridge <null> method invoke(p0: java.lang.Object): java.lang.Object
enclosing method A$B$C.f()V
public final static field <null> INSTANCE: A$B$C$f$1
inner (anonymous) class A$B$C$f$1
public final inner class A$B
public final inner class A$B$C
}
@kotlin.Metadata
public final class<null> A$B$C {
// source: 'genericInnerClass.kt'
public <()V> method <init>(p0: A$B): void
public final <null> method f(): void
synthetic final field <null> this$0: A$B
inner (anonymous) class A$B$C$f$1
public final inner class A$B
public final inner class A$B$C
}
@kotlin.Metadata
public final class<null> A$B {
// source: 'genericInnerClass.kt'
public <()V> method <init>(p0: A): void
synthetic final field <null> this$0: A
public final inner class A$B
public final inner class A$B$C
}
@kotlin.Metadata
public final class<<T:Ljava/lang/Object;>Ljava/lang/Object;> A {
// source: 'genericInnerClass.kt'
public final <()TT;> method getResult(): java.lang.Object
public <(TT;)V> method <init>(p0: java.lang.Object): void
private final field <TT;> result: java.lang.Object
public final inner class A$B
}
@@ -0,0 +1,28 @@
@kotlin.Metadata
public final class<null> A$B$C {
// source: 'genericInnerClass.kt'
public <()V> method <init>(p0: A$B): void
private final static <<T:Ljava/lang/Object;>(TT;)V> method f$g(p0: java.lang.Object): void
public final <null> method f(): void
synthetic final field <LA<TT;>.B;> this$0: A$B
public final inner class A$B
public final inner class A$B$C
}
@kotlin.Metadata
public final class<null> A$B {
// source: 'genericInnerClass.kt'
public <()V> method <init>(p0: A): void
synthetic final field <LA<TT;>;> this$0: A
public final inner class A$B
public final inner class A$B$C
}
@kotlin.Metadata
public final class<<T:Ljava/lang/Object;>Ljava/lang/Object;> A {
// source: 'genericInnerClass.kt'
public final <()TT;> method getResult(): java.lang.Object
public <(TT;)V> method <init>(p0: java.lang.Object): void
private final field <TT;> result: java.lang.Object
public final inner class A$B
}
@@ -0,0 +1,11 @@
// WITH_SIGNATURES
class A<T>(val result: T) {
fun b() {
class C<S> {
fun f() {
fun g(t: T): S? = null
}
}
}
}
@@ -0,0 +1,31 @@
@kotlin.Metadata
final class<Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function1<TT;TS;>;> A$b$C$f$1 {
// source: 'genericLocalClass.kt'
public final @org.jetbrains.annotations.Nullable <(TT;)TS;> method invoke(p0: java.lang.Object): java.lang.Object
static <null> method <clinit>(): void
<null> method <init>(): void
enclosing method A$b$C.f()V
public final static field <null> INSTANCE: A$b$C$f$1
inner (anonymous) class A$b$C$f$1
inner (local) class A$b$C C
}
@kotlin.Metadata
public final class<<S:Ljava/lang/Object;>Ljava/lang/Object;> A$b$C {
// source: 'genericLocalClass.kt'
public <null> method <init>(): void
public final <null> method f(): void
enclosing method A.b()V
inner (anonymous) class A$b$C$f$1
inner (local) class A$b$C C
}
@kotlin.Metadata
public final class<<T:Ljava/lang/Object;>Ljava/lang/Object;> A {
// source: 'genericLocalClass.kt'
public final <()TT;> method getResult(): java.lang.Object
public <(TT;)V> method <init>(p0: java.lang.Object): void
public final <null> method b(): void
private final field <TT;> result: java.lang.Object
inner (local) class A$b$C C
}
@@ -0,0 +1,19 @@
@kotlin.Metadata
public final class<<S:Ljava/lang/Object;>Ljava/lang/Object;> A$b$C {
// source: 'genericLocalClass.kt'
private final static <<T:Ljava/lang/Object;S:Ljava/lang/Object;>(TT;)TS;> method f$g(p0: java.lang.Object): java.lang.Object
public <null> method <init>(): void
public final <null> method f(): void
enclosing method A.b()V
inner (local) class A$b$C C
}
@kotlin.Metadata
public final class<<T:Ljava/lang/Object;>Ljava/lang/Object;> A {
// source: 'genericLocalClass.kt'
public final <()TT;> method getResult(): java.lang.Object
public <(TT;)V> method <init>(p0: java.lang.Object): void
public final <null> method b(): void
private final field <TT;> result: java.lang.Object
inner (local) class A$b$C C
}