Skip to content

Conversation

@tanishiking
Copy link
Member

@tanishiking tanishiking commented Dec 22, 2025

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:

//> using jvm 21
package ox
import java.util.concurrent.StructuredTaskScope
trait Ox {
  def scope: StructuredTaskScope[Any]
}

and test.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.


I'm wondering how do I test on CI.

  • Is it okay to put a classfile on tests/neg/i20491/?
  • Can we test it only for specific JVM version?

@tanishiking tanishiking force-pushed the i20491 branch 2 times, most recently from 6de1eaa to 8972b20 Compare December 23, 2025 09:43
Fixes scala#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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Usage of Scala library compiled with newer version of JDK leads to compiler crash

1 participant