Skip to content

Commit

Permalink
Fix: #2187 Match with guards does not compile (#2188)
Browse files Browse the repository at this point in the history
* Generate match default case before any other case to register it in MethodEnv.

* Add test case

* Scalafmt fix

* Fix comments

* Fix failing tests - limit generating match default case to only LabelDefs
  • Loading branch information
WojciechMazur committed Mar 3, 2021
1 parent 5df3293 commit 0ded408
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,35 @@ trait NirGenExpr[G <: nsc.Global with Singleton] { self: NirGenPhase[G] =>
}

def genIfsChain(): Val = {
/* Default label needs to be generated before any others and then added to
* current MethodEnv. It's label might be referenced in any of them in
* case of match with guards, eg.:
*
* "Hello, World!" match {
* case "Hello" if cond1 => "foo"
* case "World" if cond2 => "bar"
* case _ if cond3 => "bar-baz"
* case _ => "baz-bar"
* }
*
* might be translated to something like:
*
* val x1 = "Hello, World!"
* if(x1 == "Hello"){ if(cond1) "foo" else default4() }
* else if (x1 == "World"){ if(cond2) "bar" else default4() }
* else default4()
*
* def default4() = if(cond3) "bar-baz" else "baz-bar
*
* We need to make sure to only generate LabelDef at this stage.
* Generating other ASTs and mutating state might lead to unexpected
* runtime errors.
*/
val optDefaultLabel = defaultp match {
case label: LabelDef => Some(genLabelDef(label))
case _ => None
}

def loop(cases: List[Case]): Val = {
cases match {
case (_, caze, body, p) :: elsep =>
Expand All @@ -279,7 +308,7 @@ trait NirGenExpr[G <: nsc.Global with Singleton] { self: NirGenPhase[G] =>
thenp = ContTree(() => genExpr(body)),
elsep = ContTree(() => loop(elsep)))

case Nil => genExpr(defaultp)
case Nil => optDefaultLabel.getOrElse(genExpr(defaultp))
}
}
loop(caseps.toList)
Expand Down
18 changes: 18 additions & 0 deletions unit-tests/src/test/scala/scala/scalanative/IssuesTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,24 @@ class IssuesTest {
.foreach(assertEquals("hello", _))
}

@Test def test_Issue2187(): Unit = {
val args = List.empty[String]
// In issue 2187 match with guards would not compile
val res = "Hello, World!" match {
case "Hello" if args.isEmpty => "foo"
case "Hello" if args.nonEmpty => "foo2"
// With next line it compiled because it was not referencing default case
// case "Hello" => "foo3"
case "World" if args.nonEmpty => "bar"
case "World" if args.length > 3 => "bar2"
case "World" if args.isEmpty => "bar3"
case "World" => "bar4"
case _ if args != null => "bar-baz"
case _ => "baz-bar"
}
assertNotNull(res)
}

}

package issue1090 {
Expand Down

0 comments on commit 0ded408

Please sign in to comment.