Skip to content

Pattern matching with alternatives is compiled to "throw null" with Scala.js #9268

Closed
@devkat

Description

@devkat

Minimized code

https://github.com/scala-js/scala-js/blob/master/test-suite/shared/src/test/scala/org/scalajs/testsuite/javalib/util/FormatterTest.scala#L626

  @Test def leftAlignWithoutWidthThrows(): Unit = {
    for (conversion <- "bBhHsHcCdoxXeEgGf%") {
      val fmt = "ab%-" + conversion + "cd"
      val arg = conversion match {
        case 'e' | 'E' | 'g' | 'G' | 'f' => 5.5
        case _ => 5
      }
      val e =
        expectFormatterThrows(classOf[MissingFormatWidthException], fmt, arg)
      assertEquals(fmt, "%-" + conversion, e.getFormatSpecifier)
    }
  }

Output

Scala.js IR:

  @hints(1) private def leftAlignWithoutWidthThrows$$anonfun$1;C;V(conversion: char) {
    val fmt: java.lang.String = (("ab%-" +[string] conversion) +[string] "cd");
    val arg: double = matchResult1[double]: {
      val x1: char = conversion;
      throw null
    };
    val e: java.util.MissingFormatWidthException = this.expectFormatterThrows;Ljava.lang.Class;Ljava.lang.String;Lscala.collection.immutable.Seq;Ljava.lang.Throwable(classOf[java.util.MissingFormatWidthException], fmt, mod:scala.runtime.ScalaRunTime$.genericWrapArray;Ljava.lang.Object;Lscala.collection.immutable.ArraySeq(java.lang.Object[](arg))).asInstanceOf[java.util.MissingFormatWidthException];
    mod:org.junit.Assert$.assertEquals;Ljava.lang.String;Ljava.lang.Object;Ljava.lang.Object;V(fmt, ("%-" +[string] conversion), e.getFormatSpecifier;Ljava.lang.String())
  }

JavaScript:

  leftAlignWithoutWidthThrows__V() {
    const len = $uI("bBhHsHcCdoxXeEgGf%".length);
    let i = 0;
    while ((i < len)) {
      const index = i;
      $uI("bBhHsHcCdoxXeEgGf%".charCodeAt(index));
      throw null
    }
  };

Expectation

This (equivalent?) match expression:

      val arg = conversion match {
        case _: ('e' | 'E' | 'g' | 'G' | 'f') => 5.5
        case _ => 5
      }

is compiled to the following IR:

    val arg: double = matchResult1[double]: {
      val x1: char = conversion;
      if ((((int)'e') ==[int] ((int)x1)) || (((int)'E') ==[int] ((int)x1)) || (((int)'g') ==[int] ((int)x1)) || (((int)'G') ==[int] ((int)x1)) || (((int)'f') ==[int] ((int)x1))) {
        return@matchResult1 5.5d
      };
      return@matchResult1 5.0d
    };

and the following JavaScript code:

const arg = ((((((arg1 === 101) || (arg1 === 69)) || (arg1 === 103)) || (arg1 === 71)) || (arg1 === 102)) ? 5.5 : 5.0);

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions