Skip to content

finding unreachable case clause on huge enum blows up compile time even it does not have guard clause #12873

Open
@KisaragiEffective

Description

@KisaragiEffective

Reproduction steps

  1. checkout https://github.com/KisaragiEffective/scala-match-on-huge-enum or https://github.com/KisaragiEffective/match-on-huge-enum-sealed-trait
  2. just compile

Problems

sbt:match-on-huge-enum> compile
[info] compiling 1 Scala source and 1 Java source to /private/tmp/scala-match-on-huge-enum/target/scala-2.13/classes ...
[warn] /private/tmp/scala-match-on-huge-enum/src/main/scala/Hello.scala:5:5: Cannot check match for unreachability.
[warn] The analysis required more space than allowed.
[warn] Please try with scalac -Ypatmat-exhaust-depth 40 or -Ypatmat-exhaust-depth off.
[warn]     h match {
[warn]     ^
[warn] 1 deprecation (since 2.13.0); re-run with -deprecation for details
[warn] two warnings found
[success] Total time: 163 s (02:43), completed Sep 17, 2023 10:14:55 PM

There are two issues.

  1. Each occurrence of the match expression adds a few minutes (originally reported as "3 or 4 minutes") to compilation time, which is non-negligible.
  2. The current (2.13.12) compiler implementation takes too long time to find unreachable case (exhaustiveness performance issue is split: patmat does not consider that it is exhaustive even if it has wildcard arm #12874).

Notes

This is a performance problem: there is a case in real world.

One of them is in "Bukkit", a minecraft server, is providing API for plugging into Minecraft. It provides a class called Material, which corresponds in-game item or block per one-by-one. As of today, there are 1866 entries.

Upon profiling we saw that scala.tools.nsc.transform.patmat.PatternMatching$OptimizeMatchTranslator.exhaustive occupies ~85% of the CPU time (unreachableCase also does ~15%, that's another story).

A work-around is to simply avoid match on those enums (ours is avoided by GiganticMinecraft/SeichiAssist@1ad23ea, but preferred to use match).

The above also applies to Scala 2's "pseudo" enum (sealed trait + object). Some how its shorter (on my machine, its about half) than Java's one (but still slow).

If the match has only wildcard arm (or annotate scrutinee with @unchecked, thank you @dwijnand) , it will not blow up.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions