Scott Christopher
11/05/2020, 12:49 AMjava.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
com/example/Foo.bar(Lkotlin/jvm/functions/Function3;)Lcom/example/Other$ThingConsumer; @13: invokespecial
Reason:
Type 'kotlin/jvm/functions/Function3' (current frame, stack[3]) is not assignable to 'kotlin/jvm/internal/Ref$ObjectRef'
when attempting to use:
runBlocking { consumer(connection, event) }
where consumer: suspend (Connection, Event) -> Unit
is passed into the function calling runBlocking
.
We can hack around it by replacing it with something like GlobalScope.async { consumer(connection, event) }.asCompletableFuture().get()
but it's less than ideal 😬
This is using Kotlin 1.4.10 and kotlinx.coroutines 1.4.0.
Any thoughts?ephemient
11/05/2020, 1:04 AMScott Christopher
11/05/2020, 1:07 AMScott Christopher
11/05/2020, 8:05 AMrunBlocking
call exists inside of a SAM. If the runBlocking
is moved outside the SAM, but still kept within the same surrounding function it doesn't crash...Scott Christopher
11/05/2020, 9:01 AMpackage foo
import kotlinx.coroutines.runBlocking
import java.util.function.Consumer
class Example {
fun <A> fn(consumer: suspend (A) -> Unit):
Consumer<A> =
Consumer { a: A ->
runBlocking { consumer(a) }
}
}
fun main() {
val constructors = Example::class.java.constructors
println("hi $constructors")
}
Resulting in:
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
foo/Example.fn(Lkotlin/jvm/functions/Function2;)Ljava/util/function/Consumer; @11: invokespecial
Reason:
Type 'kotlin/jvm/functions/Function2' (current frame, stack[2]) is not assignable to 'kotlin/jvm/internal/Ref$ObjectRef'
Current Frame:
bci: @11
flags: { }
locals: { 'foo/Example', 'kotlin/jvm/functions/Function2' }
stack: { uninitialized 6, uninitialized 6, 'kotlin/jvm/functions/Function2' }
Bytecode:
0x0000000: 2b12 0ab8 0010 bb00 1259 2bb7 0016 c000
0x0000010: 18b0
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
at java.lang.Class.getConstructors(Class.java:1651)
at foo.ExampleKt.main(Example.kt:15)
at foo.ExampleKt.main(Example.kt)
Vampire
11/05/2020, 9:03 AMVerifyError
should imho never happen, I'd recommend opening an issue for thatephemient
11/05/2020, 9:04 AMScott Christopher
11/05/2020, 9:05 AMephemient
11/05/2020, 9:06 AMScott Christopher
11/05/2020, 9:08 AMVampire
11/05/2020, 9:10 AMScott Christopher
11/05/2020, 9:12 AM@Lkotlin/Metadata;(mv={1, 4, 0} ...
in the generated bytecode - does that suggest it's compiled with 1.4.0?ephemient
11/05/2020, 9:13 AMScott Christopher
11/05/2020, 9:13 AMephemient
11/05/2020, 9:14 AM0x0000000: 2b12 0ab8 0010 bb00 1259 2bb7 0016 c000
0x0000010: 18b0
disassembling by hand, that is
aload_1
ldc 10
invokestatic #16
new #18
dup
aload_1
invokespecial #22
checkcast #24
areturn
Scott Christopher
11/05/2020, 9:15 AMephemient
11/05/2020, 9:16 AMScott Christopher
11/05/2020, 9:19 AM// access flags 0x11
// signature <A:Ljava/lang/Object;>(Lkotlin/jvm/functions/Function2<-TA;-Lkotlin/coroutines/Continuation<-Lkotlin/Unit;>;+Ljava/lang/Object;>;)Ljava/util/function/Consumer<TA;>;
// declaration: java.util.function.Consumer<A> fn<A>(kotlin.jvm.functions.Function2<? super A, ? super kotlin.coroutines.Continuation<? super kotlin.Unit>, ? extends java.lang.Object>)
public final fn(Lkotlin/jvm/functions/Function2;)Ljava/util/function/Consumer;
@Lorg/jetbrains/annotations/NotNull;() // invisible
// annotable parameter count: 1 (visible)
// annotable parameter count: 1 (invisible)
@Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
L0
ALOAD 1
LDC "consumer"
INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkNotNullParameter (Ljava/lang/Object;Ljava/lang/String;)V
L1
LINENUMBER 9 L1
NEW foo/Example$fn$1
DUP
ALOAD 1
INVOKESPECIAL foo/Example$fn$1.<init> (Lkotlin/jvm/functions/Function2;)V
CHECKCAST java/util/function/Consumer
L2
LINENUMBER 11 L2
ARETURN
L3
LOCALVARIABLE this Lfoo/Example; L0 L3 0
LOCALVARIABLE consumer Lkotlin/jvm/functions/Function2; L0 L3 1
MAXSTACK = 3
MAXLOCALS = 2
ephemient
11/05/2020, 9:24 AMkotlin/jvm/internal/Ref$ObjectRef
is involved at allephemient
11/05/2020, 9:26 AMScott Christopher
11/05/2020, 9:26 AMClass:getConstructors()
Scott Christopher
11/05/2020, 9:26 AMScott Christopher
11/05/2020, 9:29 AMpublic final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
Intrinsics.checkNotNullParameter(completion, "completion");
Function2 var3 = new <anonymous constructor>(completion);
var3.p$ = (CoroutineScope)value;
return var3;
}
Scott Christopher
11/05/2020, 9:30 AMFunction2
when it's expecting a Continuation
ephemient
11/05/2020, 9:30 AMephemient
11/05/2020, 9:31 AMScott Christopher
11/05/2020, 9:32 AMfn
in that example above. Here's the whole class:
public final class Example {
@NotNull
public final Consumer fn(@NotNull final Function2 consumer) {
Intrinsics.checkNotNullParameter(consumer, "consumer");
return (Consumer)(new Consumer() {
public final void accept(final Object a) {
BuildersKt.runBlocking$default((CoroutineContext)null, (Function2)(new Function2((Continuation)null) {
private CoroutineScope p$;
Object L$0;
int label;
@Nullable
public final Object invokeSuspend(@NotNull Object $result) {
Object var3 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
CoroutineScope $this$runBlocking;
switch(this.label) {
case 0:
ResultKt.throwOnFailure($result);
$this$runBlocking = this.p$;
Function2 var10000 = consumer;
Object var10001 = a;
this.L$0 = $this$runBlocking;
this.label = 1;
if (var10000.invoke(var10001, this) == var3) {
return var3;
}
break;
case 1:
$this$runBlocking = (CoroutineScope)this.L$0;
ResultKt.throwOnFailure($result);
break;
default:
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
return Unit.INSTANCE;
}
@NotNull
public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
Intrinsics.checkNotNullParameter(completion, "completion");
Function2 var3 = new <anonymous constructor>(completion);
var3.p$ = (CoroutineScope)value;
return var3;
}
public final Object invoke(Object var1, Object var2) {
return ((<undefinedtype>)this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
}
}), 1, (Object)null);
}
});
}
}
ephemient
11/05/2020, 9:35 AMephemient
11/05/2020, 9:52 AMgradle
from the command line, does it still error? (your failing .kt from above + minimal build script)ephemient
11/05/2020, 9:53 AMScott Christopher
11/05/2020, 9:54 AMScott Christopher
11/05/2020, 9:55 AMkotlinc
that is bundled with the IntelliJ plugin, and that also worked fine...Scott Christopher
11/05/2020, 9:56 AMephemient
11/05/2020, 10:05 AMephemient
11/05/2020, 10:06 AMephemient
11/05/2020, 10:07 AMScott Christopher
11/05/2020, 10:07 AMScott Christopher
11/05/2020, 10:08 AMScott Christopher
11/05/2020, 10:09 AMephemient
11/05/2020, 10:30 AMsbt run
here works tooephemient
11/05/2020, 10:30 AMScott Christopher
11/05/2020, 10:31 AMScott Christopher
11/05/2020, 10:31 AMScott Christopher
11/05/2020, 10:31 AMephemient
11/05/2020, 10:32 AMScott Christopher
11/05/2020, 10:36 AMkotlinVersion
key (or changing the version explicitly to 1.3.50Scott Christopher
11/05/2020, 10:36 AMephemient
11/05/2020, 10:44 AMephemient
11/05/2020, 10:44 AMVampire
11/05/2020, 10:45 AMScott Christopher
11/05/2020, 10:46 AMephemient
11/05/2020, 9:26 PM