Compiler version
3.3.1
Minimized code
Full context here in lila-ws
repository: https://github.com/lichess-org/lila-ws/pull/525/commits/7f47bc39a8b36a0f076b24dd75da17150502040e
This code below crash the runtime:
private def shutdown(channel: Channel, code: Int, reason: String): Unit =
channel.writeAndFlush(CloseWebSocketFrame(code, reason)).addListener(_ => channel.close())
The fix is annotating the lambda with type:
private def shutdown(channel: Channel, code: Int, reason: String): Unit =
val close: GenericFutureListener[ChannelFuture] = _ => channel.close()
channel.writeAndFlush(CloseWebSocketFrame(code, reason)).addListener(close)
Stacktrace:
WARN i.n.c.DefaultChannelPipeline [KQueueEventLoopGroup-6-3] An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exc
eption.
java.lang.BootstrapMethodError: bootstrap method initialization exception
at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:188)
at java.base/java.lang.invoke.CallSite.makeSite(CallSite.java:316)
at java.base/java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:274)
at java.base/java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:264)
at lila.ws.netty.FrameHandler.shutdown(FrameHandler.scala:62)
at lila.ws.netty.FrameHandler.channelRead0(FrameHandler.scala:27)
at lila.ws.netty.FrameHandler.channelRead0(FrameHandler.scala:17)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
at io.netty.handler.codec.http.websocketx.Utf8FrameValidator.channelRead(Utf8FrameValidator.java:89)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:102)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.kqueue.AbstractKQueueStreamChannel$KQueueStreamUnsafe.readReady(AbstractKQueueStreamChannel.java:544)
at io.netty.channel.kqueue.AbstractKQueueChannel$AbstractKQueueUnsafe.readReady(AbstractKQueueChannel.java:387)
at io.netty.channel.kqueue.KQueueEventLoop.processReady(KQueueEventLoop.java:218)
at io.netty.channel.kqueue.KQueueEventLoop.run(KQueueEventLoop.java:296)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.invoke.LambdaConversionException: Type mismatch for dynamic parameter 0: class scala.runtime.Nothing$ is not a subtype of interface io.netty.util.concurrent.Future
at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.checkDescriptor(AbstractValidatingLambdaMetafactory.java:327)
at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:313)
at java.base/java.lang.invoke.LambdaMetafactory.altMetafactory(LambdaMetafactory.java:535)
at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:147)
... 40 common frames omitted
Expectation
Either compile error or We shouldn't need to annotate the type.
This issue was picked for the Scala Issue Spree of tomorrow, April 9th. @hamzaremmal, @Sporarum, @jan-pieter will be working on it. If you have any insight into the issue or guidance on how to fix it, please leave it here.
It looks very similar to #20114
java.lang.BootstrapMethodError: bootstrap method initialization exception at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:188) at
Seems like the compiler insert a Nothing type, because Nothing is a sub type of Future, the listener needs a ? extends Future<?> as input, so scala compiler inser a Nothing?
For the lambda we need insert a Future<?> instead.
I still remember when using scala 2.12.x with completionStage, I have to use stage.[Unit]handle(...) for the compiler to work properly.