Skip to content

compiletime.testing.typeCheckErrors can result in UTF8 string too large in JVM codegen #24597

@WojciechMazur

Description

@WojciechMazur

Based on the OpenCB failure in plokhotnyuk/jsoniter-scala - build logs

If the execution of macro results in StackOverflow or other exception with long stack trace, it might be too long when reaching the JVM backend - at this point the codegen would fail with exception

We should either trim the output of such macro, or detect it and fail early. Otherwise it's hard to discover exact place where failing macro was used.

Compiler version

3.8
3.3 LTS
All Scala versions

Minimized code

def Test = scala.compiletime.testing.typeCheckErrors("stackOverflowMacro")
import scala.quoted.*

transparent inline def stackOverflowMacro: Int = ${ StackOverflowMacro.impl }

object StackOverflowMacro:
    def impl(using Quotes): Expr[Int] =  '{ ${impl} + ${impl} }
    

Output

> scala compile test.scala test.macro.scala -S 3.8.0-RC2 --server=false
java.lang.IllegalArgumentException: UTF8 string too large
        at scala.tools.asm.ByteVector.putUTF8(ByteVector.java:255)
        at scala.tools.asm.SymbolTable.addConstantUtf8(SymbolTable.java:800)
        at scala.tools.asm.SymbolTable.addConstantUtf8Reference(SymbolTable.java:1053)
        at scala.tools.asm.SymbolTable.addConstantString(SymbolTable.java:630)
        at scala.tools.asm.SymbolTable.addConstant(SymbolTable.java:500)
        at scala.tools.asm.MethodWriter.visitLdcInsn(MethodWriter.java:1281)
        at scala.tools.asm.tree.LdcInsnNode.accept(LdcInsnNode.java:75)
        at scala.tools.asm.tree.InsnList.accept(InsnList.java:144)
        at scala.tools.asm.tree.MethodNode.accept(MethodNode.java:751)
        at scala.tools.asm.tree.MethodNode.accept(MethodNode.java:649)
        at scala.tools.asm.tree.ClassNode.accept(ClassNode.java:468)
        at dotty.tools.backend.jvm.PostProcessor.serializeClass(PostProcessor.scala:101)
        at dotty.tools.backend.jvm.PostProcessor.sendToDisk(PostProcessor.scala:37)
        at dotty.tools.backend.jvm.GeneratedClassHandler$WritingClassHandler.postProcessUnit$$anonfun$1$$anonfun$1$$anonfun$1(GeneratedClassHandler.scala:94)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
        at scala.collection.immutable.List.foreach(List.scala:327)
        at dotty.tools.backend.jvm.GeneratedClassHandler$WritingClassHandler.postProcessUnit$$anonfun$1$$anonfun$1(GeneratedClassHandler.scala:94)
        at dotty.tools.backend.jvm.GeneratedClassHandler$WritingClassHandler.postProcessUnit$$anonfun$1$$anonfun$adapted$1(GeneratedClassHandler.scala:96)
        at dotty.tools.backend.jvm.PostProcessorFrontendAccess$Impl.withThreadLocalReporter(PostProcessorFrontendAccess.scala:140)
        at dotty.tools.backend.jvm.GeneratedClassHandler$WritingClassHandler.postProcessUnit$$anonfun$1(GeneratedClassHandler.scala:96)
        at dotty.tools.backend.jvm.GeneratedClassHandler$WritingClassHandler.postProcessUnit$$anonfun$adapted$1(GeneratedClassHandler.scala:96)
        at scala.concurrent.Future$.apply$$anonfun$1(Future.scala:692)
        at scala.concurrent.impl.Promise$Transformation.run(Promise.scala:503)
        at dotty.tools.backend.jvm.GeneratedClassHandler$.SyncWritingClassHandler$superArg$1$$anonfun$1(GeneratedClassHandler.scala:146)
        at scala.concurrent.impl.ExecutionContextImpl.execute(ExecutionContextImpl.scala:22)
        at scala.concurrent.impl.Promise$Transformation.submitWithValue(Promise.scala:465)
        at scala.concurrent.impl.Promise$DefaultPromise.submitWithValue(Promise.scala:374)
        at scala.concurrent.impl.Promise$DefaultPromise.dispatchOrAddCallbacks(Promise.scala:325)
        at scala.concurrent.impl.Promise$DefaultPromise.map(Promise.scala:185)
        at scala.concurrent.Future$.apply(Future.scala:692)
        at dotty.tools.backend.jvm.GeneratedClassHandler$WritingClassHandler.postProcessUnit(GeneratedClassHandler.scala:96)
        at dotty.tools.backend.jvm.GeneratedClassHandler$WritingClassHandler.process(GeneratedClassHandler.scala:82)
        at dotty.tools.backend.jvm.CodeGen.genUnit(CodeGen.scala:122)
        at dotty.tools.backend.jvm.GenBCode.run(GenBCode.scala:90)
        at dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:386)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
        at scala.collection.immutable.List.foreach(List.scala:327)
        at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:379)
        at dotty.tools.backend.jvm.GenBCode.runOn(GenBCode.scala:98)
        at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:380)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
        at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1327)
        at dotty.tools.dotc.Run.runPhases$1(Run.scala:373)
        at dotty.tools.dotc.Run.compileUnits$$anonfun$1$$anonfun$2(Run.scala:420)
        at dotty.tools.dotc.Run.compileUnits$$anonfun$1$$anonfun$adapted$1(Run.scala:420)
        at scala.Function0.apply$mcV$sp(Function0.scala:45)
        at dotty.tools.dotc.Run.showProgress(Run.scala:482)
        at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:420)
        at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:432)
        at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:69)
        at dotty.tools.dotc.Run.compileUnits(Run.scala:432)
        at dotty.tools.dotc.Run.compileUnits(Run.scala:325)
        at dotty.tools.dotc.Run.compileSuspendedUnits(Run.scala:446)
        at dotty.tools.dotc.Driver.finish(Driver.scala:64)
        at dotty.tools.dotc.Driver.doCompile(Driver.scala:39)
        at dotty.tools.dotc.Driver.process(Driver.scala:213)
        at dotty.tools.dotc.Driver.process(Driver.scala:181)
        at dotty.tools.dotc.Driver.process(Driver.scala:193)
        at dotty.tools.dotc.Driver.main(Driver.scala:223)
        at dotty.tools.dotc.Main.main(Main.scala)
Error while emitting test$package$
UTF8 string too large
1 error found

Expectation

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions