Skip to content

Commit 7f90796

Browse files
committed
Handle TypeError during Erasure phase
Fixes #20491 Wrap the `transform` method in Erasure with a try-catch to handle `TypeError` (including `MissingType`). These errors can occur during TypeErasure when accessing types from dependencies compiled with newer JDK versions that use APIs unavailable in the current runtime. For example, when a library compiled with JDK 21 (using `java.util.concurrent.StructuredTaskScope`) is used in a project running on JDK 17, the compiler currently crashes with an unhandled `MissingType` exception during the Erasure phase instead of reporting an error. `MissingType` is thrown from `TypeErasure.sigName` or `checkedSuperType`, which are called from `TypeErasure.eraseXXX`. These errors are usually caught by `Typer.handleTypeError` or `TreePickler.pickleType`, but those handlers do not cover exceptions thrown during the Erasure. (It seems that during typer, the compiler trusts the information from the classfile or tasty without verifying that all referenced types actually exist on the classpath). This commit encloses `Erasure.transform` with a try-catch to intercept the `TypeError` and call `report.error`. We can test the change manually: ``` . |-- cp | `-- ox | `-- Ox.class `-- test.scala ``` `Ox.class` is compiled from: ```scala //> using jvm 21 package ox import java.util.concurrent.StructuredTaskScope trait Ox { def scope: StructuredTaskScope[Any] } ``` and `test.scala`: ```scala //> using jvm 17 given ox.Ox = ??? ``` `$ scala-cli compile test.scala -S 3.8.1-RC1-bin-SNAPSHOT --extra-jars ./cp` now it should compile fails, instead of crash.
1 parent 4d4f543 commit 7f90796

File tree

1 file changed

+6
-2
lines changed

1 file changed

+6
-2
lines changed

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import core.Decorators.*
2020
import core.Constants.*
2121
import core.Definitions.*
2222
import core.Annotations.BodyAnnotation
23+
import core.TypeError
2324
import typer.NoChecking
2425
import inlines.Inlines
2526
import typer.ProtoTypes.*
@@ -49,7 +50,7 @@ class Erasure extends Phase with DenotTransformer {
4950
override def changesMembers: Boolean = true // the phase adds bridges
5051
override def changesParents: Boolean = true // the phase drops Any
5152

52-
def transform(ref: SingleDenotation)(using Context): SingleDenotation = ref match {
53+
def transform(ref: SingleDenotation)(using Context): SingleDenotation = try ref match {
5354
case ref: SymDenotation =>
5455
def isCompacted(symd: SymDenotation) =
5556
symd.isAnonymousFunction && {
@@ -130,7 +131,10 @@ class Erasure extends Phase with DenotTransformer {
130131
ref.symbol, transformInfo(ref.symbol, ref.symbol.info), currentStablePeriod, ref.prefix)
131132
case _ =>
132133
ref.derivedSingleDenotation(ref.symbol, transformInfo(ref.symbol, ref.symbol.info))
133-
}
134+
} catch case ex: TypeError =>
135+
// Handle missing types from dependencies (e.g., JDK version mismatch)
136+
report.error(ex.toMessage, ref.symbol.srcPos)
137+
ref // Keep old denotation on error
134138

135139
private val eraser = new Erasure.Typer(this)
136140

0 commit comments

Comments
 (0)