Skip to content

SIP-62 better for dropForMap phase bug #24673

@xuwei-k

Description

@xuwei-k

Compiler version

  • 3.8.1-RC1-bin-20251205-cd32c6f-NIGHTLY
  • 3.8.0-RC3

Minimized code

//> using scala 3.8.0-RC3

@main def main = {
  val result = for {
    a <- Option(2)
    _ = if (true) {
      sys.error("err")
    }
  } yield a

  println(result)
}

Output

Some(2)

Expectation

  • runtime error. same as Scala 3.7.x
  • or compile error or warning

Scala 3.7.4

Exception in thread "main" java.lang.RuntimeException: err
	at scala.sys.package$.error(package.scala:27)
	at A$package$.$anonfun$1(A.scala:7)
	at A$package$.$anonfun$adapted$1(A.scala:5)
	at scala.Option.map(Option.scala:242)
	at A$package$.main(A.scala:5)
	at main.main(A.scala:3)

-Xprint:all result

I think dropForMap phase delete following code.

https://github.com/scala/scala3/blob/b531c2f97f5a0e8d6b48d0d69b9081addebe90db/compiler/src/dotty/tools/dotc/transform/localopt/DropForMap.scala

    _ = if (true) {
      sys.error("err")
    }
[info] [[syntax trees at end of                 posttyper]] // /Users/kenji/scala-3-8-for-expr-if/A.scala
[info] package <empty> {
[info]   final lazy module val A$package: A$package = new A$package()
[info]   @SourceFile("A.scala") final module class A$package() extends Object() {
[info]     this: A$package.type =>
[info]     private def writeReplace(): AnyRef =
[info]       new scala.runtime.ModuleSerializationProxy(classOf[A$package.type])
[info]     @main def main: Unit =
[info]       {
[info]         val result: Option[Int] =
[info]           Option.apply[Int](2).map[Int]((a: Int) =>
[info]             {
[info]               val $1$: Unit =
[info]                 (if true then
[info]                   {
[info]                     sys.package.error("err")
[info]                   }
[info]                  else ()):Unit @unchecked match 
[info]                   {
[info]                     case $1$ @ _ => $1$:Unit
[info]                   }
[info]               a
[info]             }
[info]           )
[info]         println(result)
[info]       }
[info]   }
[info]   @SourceFile("A.scala") final class main() extends Object() {
[info]     <static> def main(args: Array[String]): Unit =
[info]       try main catch 
[info]         {
[info]           case error @ _:scala.util.CommandLineParser.ParseError =>
[info]             scala.util.CommandLineParser.showError(error)
[info]         }
[info]   }
[info] }
[info] [[syntax trees at end of                unrollDefs]] // /Users/kenji/scala-3-8-for-expr-if/A.scala: unchanged since posttyper
[info] [[syntax trees at end of                   pickler]] // /Users/kenji/scala-3-8-for-expr-if/A.scala: unchanged since posttyper
[info] [[syntax trees at end of                   sbt-api]] // /Users/kenji/scala-3-8-for-expr-if/A.scala: unchanged since posttyper
[info] [[syntax trees at end of                  inlining]] // /Users/kenji/scala-3-8-for-expr-if/A.scala: unchanged since posttyper
[info] [[syntax trees at end of              postInlining]] // /Users/kenji/scala-3-8-for-expr-if/A.scala: unchanged since posttyper
[info] [[syntax trees at end of                   staging]] // /Users/kenji/scala-3-8-for-expr-if/A.scala: unchanged since posttyper
[info] [[syntax trees at end of                  splicing]] // /Users/kenji/scala-3-8-for-expr-if/A.scala: unchanged since posttyper
[info] [[syntax trees at end of              pickleQuotes]] // /Users/kenji/scala-3-8-for-expr-if/A.scala: unchanged since posttyper
[info] [[syntax trees at end of MegaPhase{crossVersionChecks, firstTransform, checkReentrant, elimPackagePrefixes, cookComments, checkLoopingImplicits, betaReduce, inlineVals, expandSAMs, elimRepeated, refchecks, dropForMap}]] // /Users/kenji/scala-3-8-for-expr-if/A.scala
[info] package <empty> {
[info]   final lazy module val A$package: A$package = new A$package()
[info]   @SourceFile("A.scala") final module class A$package() extends Object() {
[info]     private def writeReplace(): AnyRef =
[info]       new scala.runtime.ModuleSerializationProxy(classOf[A$package.type])
[info]     @main def main: Unit =
[info]       {
[info]         val result: Option[Int] = Option.apply[Int](2)
[info]         println(result)
[info]       }
[info]   }
[info]   @SourceFile("A.scala") final class main() extends Object() {
[info]     <static> def main(args: Array[String]): Unit =
[info]       try main catch 
[info]         {
[info]           case error @ _:scala.util.CommandLineParser.ParseError =>
[info]             scala.util.CommandLineParser.showError(error)
[info]         }
[info]   }
[info] }
<         val result: Option[Int] =
<           Option.apply[Int](2).map[Int]((a: Int) =>
<             {
<               val $1$: Unit =
<                 (if true then
<                   {
<                     sys.package.error("err")
<                   }
<                  else ()):Unit @unchecked match 
<                   {
<                     case $1$ @ _ => $1$:Unit
<                   }
<               a
<             }
<           )
---
>         val result: Option[Int] = Option.apply[Int](2)

Metadata

Metadata

Assignees

Labels

area:desugarDesugaring happens after parsing but before typing, see desugar.scalaarea:experimental.betterForsIssues related to the betterFors language extensionitype:bug

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions