dotty-linker / dotty

Modified version of dotty suporting language specific and library-specific optimizations
Other
37 stars 5 forks source link

Example of failed compilation in simplify branch #3

Open jvican opened 8 years ago

jvican commented 8 years ago

Compiling:

package test

object HoistUpNestedIfElses {

  def main(args: Array[String]): Unit = {
    sealed trait Animal
    case class Cat(name: String) extends Animal
    case class Cow(typeOfMilk: String) extends Animal

    sealed trait Food
    case object Meat extends Food
    case object Grass extends Food

    def getFoodFor(a: Animal) = a match {
      case c: Cat => Meat
      case cw: Cow => Grass
    }

    getFoodFor(Cat("Garfield"))
    getFoodFor(Cow("UHV"))
  }

}

fails with:

checking test/test/HoistUpNestedIfElses.scala after phase frontend
checking test/test/HoistUpNestedIfElses.scala after phase posttyper
checking test/test/HoistUpNestedIfElses.scala after phase pickler
checking test/test/HoistUpNestedIfElses.scala after phase summaries
checking test/test/HoistUpNestedIfElses.scala after phase TreeTransform:{firstTransform, checkReentrant}
checking test/test/HoistUpNestedIfElses.scala after phase TreeTransform:{prespecialize, refchecks, elimRepeated, normalizeFlags, extmethods, expandSAMs, tailrec, liftTry, classOf}
checking test/test/HoistUpNestedIfElses.scala after phase TreeTransform:{patternMatcher, explicitOuter, explicitSelf, crossCast, splitter}
method equals after inlineLabelsCalledOnce became this.eq(x$0.asInstanceOf[Object]).||({
  case val selector11: Any = x$0
  {
    {
      if selector11.isInstanceOf[Cat] then {
        val x$0: Cat = selector11.asInstanceOf[Cat(x$0)]
        {
          this.name.==(x$0.name)
        }
      } else {
        if selector11.isInstanceOf[Any] then {
          false
        } else throw new MatchError(selector11)
      }
    }
  }
})
method equals after devalify became this.eq(x$0.asInstanceOf[Object]).||({
  {
    {
      if x$0.isInstanceOf[Cat] then {
        val x$0: Cat = x$0.asInstanceOf[Cat(x$0)]
        {
          this.name.==(x$0.name)
        }
      } else {
        if x$0.isInstanceOf[Any] then {
          false
        } else throw new MatchError(x$0)
      }
    }
  }
})
method equals after dropNoEffects became this.eq(x$0.asInstanceOf[Object]).||(
  if x$0.isInstanceOf[Cat] then {
    val x$0: Cat = x$0.asInstanceOf[Cat(x$0)]
    this.name.==(x$0.name)
  } else if x$0.isInstanceOf[Any] then false else throw new MatchError(x$0)
)
method equals after inlineLabelsCalledOnce became this.eq(x$0.asInstanceOf[Object]).||({
  case val selector12: Any = x$0
  {
    {
      if selector12.isInstanceOf[Cow] then {
        val x$0: Cow = selector12.asInstanceOf[Cow(x$0)]
        {
          this.typeOfMilk.==(x$0.typeOfMilk)
        }
      } else {
        if selector12.isInstanceOf[Any] then {
          false
        } else throw new MatchError(selector12)
      }
    }
  }
})
method equals after devalify became this.eq(x$0.asInstanceOf[Object]).||({
  {
    {
      if x$0.isInstanceOf[Cow] then {
        val x$0: Cow = x$0.asInstanceOf[Cow(x$0)]
        {
          this.typeOfMilk.==(x$0.typeOfMilk)
        }
      } else {
        if x$0.isInstanceOf[Any] then {
          false
        } else throw new MatchError(x$0)
      }
    }
  }
})
method equals after dropNoEffects became this.eq(x$0.asInstanceOf[Object]).||(
  if x$0.isInstanceOf[Cow] then {
    val x$0: Cow = x$0.asInstanceOf[Cow(x$0)]
    this.typeOfMilk.==(x$0.typeOfMilk)
  } else if x$0.isInstanceOf[Any] then false else throw new MatchError(x$0)
)
method equals after inlineLabelsCalledOnce became this.eq(x$0.asInstanceOf[Object]).||({
  case val selector13: Any = x$0
  {
    {
      if selector13.isInstanceOf[Meat$] then {
        val x$0: Meat$ = selector13.asInstanceOf[Meat$(x$0)]
        {
          true
        }
      } else {
        if selector13.isInstanceOf[Any] then {
          false
        } else throw new MatchError(selector13)
      }
    }
  }
})
method equals after devalify became this.eq(x$0.asInstanceOf[Object]).||({
  {
    {
      if x$0.isInstanceOf[Meat$] then {
        x$0.asInstanceOf[Meat$(x$0)]
        {
          true
        }
      } else {
        if x$0.isInstanceOf[Any] then {
          false
        } else throw new MatchError(x$0)
      }
    }
  }
})
method equals after dropNoEffects became this.eq(x$0.asInstanceOf[Object]).||(
  if x$0.isInstanceOf[Meat$] then {
    x$0.asInstanceOf[Meat$(x$0)]
    true
  } else if x$0.isInstanceOf[Any] then false else throw new MatchError(x$0)
)
method equals after inlineLabelsCalledOnce became this.eq(x$0.asInstanceOf[Object]).||({
  case val selector14: Any = x$0
  {
    {
      if selector14.isInstanceOf[Grass$] then {
        val x$0: Grass$ = selector14.asInstanceOf[Grass$(x$0)]
        {
          true
        }
      } else {
        if selector14.isInstanceOf[Any] then {
          false
        } else throw new MatchError(selector14)
      }
    }
  }
})
method equals after devalify became this.eq(x$0.asInstanceOf[Object]).||({
  {
    {
      if x$0.isInstanceOf[Grass$] then {
        x$0.asInstanceOf[Grass$(x$0)]
        {
          true
        }
      } else {
        if x$0.isInstanceOf[Any] then {
          false
        } else throw new MatchError(x$0)
      }
    }
  }
})
method equals after dropNoEffects became this.eq(x$0.asInstanceOf[Object]).||(
  if x$0.isInstanceOf[Grass$] then {
    x$0.asInstanceOf[Grass$(x$0)]
    true
  } else if x$0.isInstanceOf[Any] then false else throw new MatchError(x$0)
)
method getFoodFor after inlineLabelsCalledOnce became {
  case val selector15: Animal = a
  {
    {
      if selector15.isInstanceOf[Cat] then {
        val c: Cat = selector15.asInstanceOf[Cat(c)]
        {
          {
            Meat
          }
        }
      } else {
        if selector15.isInstanceOf[Cow] then {
          val cw: Cow = selector15.asInstanceOf[Cow(cw)]
          {
            {
              Grass
            }
          }
        } else throw new MatchError(selector15)
      }
    }
  }
}
method getFoodFor after devalify became {
  {
    {
      if a.isInstanceOf[Cat] then {
        a.asInstanceOf[Cat(c)]
        {
          {
            Meat
          }
        }
      } else {
        if a.isInstanceOf[Cow] then {
          a.asInstanceOf[Cow(cw)]
          {
            {
              Grass
            }
          }
        } else throw new MatchError(a)
      }
    }
  }
}
method getFoodFor after dropNoEffects became if a.isInstanceOf[Cat] then {
  a.asInstanceOf[Cat(c)]
  Meat
} else 
  if a.isInstanceOf[Cow] then {
    a.asInstanceOf[Cow(cw)]
    Grass
  } else throw new MatchError(a)
exception while transforming def main(args: Array[String]): Unit = {
  <trait> sealed interface trait Animal() extends Object {}
  final lazy module val Animal: Animal$ = new Animal$()
  final module class Animal$() extends Object() { this: Animal.type =>}
  case class Cat(name: String) extends Object() with Animal with Product1[String
    ]
   { 
    val name: String
    def copy(name: String): Cat = new Cat(name)
    def copy$default$1: String @uncheckedVariance = 
      this.name: String @uncheckedVariance
    def isDefined: Boolean = true
    def _1: String = this.name
    override def hashCode(): Int = {
      var acc: Int = -889275714
      acc = 
        scala.runtime.Statics$#mix(acc, 
          scala.runtime.Statics$#anyHash(this.name)
        )
      scala.runtime.Statics$#finalizeHash(acc, 1)
    }
    override def equals(x$0: Any): Boolean = 
      this.eq(x$0.asInstanceOf[Object]).||({
        case val selector11: Any = x$0
        {
          def case11(): Boolean = {
            def case21(): Boolean = {
              def matchFail11(): Boolean = throw new MatchError(selector11)
              if selector11.isInstanceOf[Any] then {
                false
              } else matchFail11()
            }
            if selector11.isInstanceOf[Cat] then {
              val x$0: Cat = selector11.asInstanceOf[Cat(x$0)]
              {
                this.name.==(x$0.name)
              }
            } else case21()
          }
          case11()
        }
      })
    override def toString(): String = scala.runtime.ScalaRunTime._toString(this)
    override def canEqual(that: Any): Boolean = that.isInstanceOf[Cat]
    override def productPrefix: String = "Cat"
  }
  final lazy module val Cat: Cat$ = new Cat$()
  final module class Cat$() extends Object() with (String => Cat) { 
    this: Cat.type =>

    def apply(name: String): Cat = new Cat(name)
    def unapply(x$1: Cat): Cat = x$1
  }
  case class Cow(typeOfMilk: String) extends Object() with Animal with Product1[
    String
  ] { 
    val typeOfMilk: String
    def copy(typeOfMilk: String): Cow = new Cow(typeOfMilk)
    def copy$default$1: String @uncheckedVariance = 
      this.typeOfMilk: String @uncheckedVariance
    def isDefined: Boolean = true
    def _1: String = this.typeOfMilk
    override def hashCode(): Int = {
      var acc: Int = -889275714
      acc = 
        scala.runtime.Statics$#mix(acc, 
          scala.runtime.Statics$#anyHash(this.typeOfMilk)
        )
      scala.runtime.Statics$#finalizeHash(acc, 1)
    }
    override def equals(x$0: Any): Boolean = 
      this.eq(x$0.asInstanceOf[Object]).||({
        case val selector12: Any = x$0
        {
          def case31(): Boolean = {
            def case41(): Boolean = {
              def matchFail21(): Boolean = throw new MatchError(selector12)
              if selector12.isInstanceOf[Any] then {
                false
              } else matchFail21()
            }
            if selector12.isInstanceOf[Cow] then {
              val x$0: Cow = selector12.asInstanceOf[Cow(x$0)]
              {
                this.typeOfMilk.==(x$0.typeOfMilk)
              }
            } else case41()
          }
          case31()
        }
      })
    override def toString(): String = scala.runtime.ScalaRunTime._toString(this)
    override def canEqual(that: Any): Boolean = that.isInstanceOf[Cow]
    override def productPrefix: String = "Cow"
  }
  final lazy module val Cow: Cow$ = new Cow$()
  final module class Cow$() extends Object() with (String => Cow) { 
    this: Cow.type =>

    def apply(typeOfMilk: String): Cow = new Cow(typeOfMilk)
    def unapply(x$1: Cow): Cow = x$1
  }
  <trait> sealed interface trait Food() extends Object {}
  final lazy module val Food: Food$ = new Food$()
  final module class Food$() extends Object() { this: Food.type =>}
  final lazy module case val Meat: Meat$ = new Meat$()
  final module case class Meat$() extends Object() with Food with Product0 { 
    this: Meat.type =>

    override def hashCode(): Int = {
      var acc: Int = -889275714
      scala.runtime.Statics$#finalizeHash(acc, 0)
    }
    override def equals(x$0: Any): Boolean = 
      this.eq(x$0.asInstanceOf[Object]).||({
        case val selector13: Any = x$0
        {
          def case51(): Boolean = {
            def case61(): Boolean = {
              def matchFail31(): Boolean = throw new MatchError(selector13)
              if selector13.isInstanceOf[Any] then {
                false
              } else matchFail31()
            }
            if selector13.isInstanceOf[Meat$] then {
              val x$0: Meat$ = selector13.asInstanceOf[Meat$(x$0)]
              {
                true
              }
            } else case61()
          }
          case51()
        }
      })
    override def toString(): String = scala.runtime.ScalaRunTime._toString(this)
    override def canEqual(that: Any): Boolean = that.isInstanceOf[Meat$]
    override def productPrefix: String = "Meat$"
  }
  final lazy module case val Grass: Grass$ = new Grass$()
  final module case class Grass$() extends Object() with Food with Product0 { 
    this: Grass.type =>

    override def hashCode(): Int = {
      var acc: Int = -889275714
      scala.runtime.Statics$#finalizeHash(acc, 0)
    }
    override def equals(x$0: Any): Boolean = 
      this.eq(x$0.asInstanceOf[Object]).||({
        case val selector14: Any = x$0
        {
          def case71(): Boolean = {
            def case81(): Boolean = {
              def matchFail41(): Boolean = throw new MatchError(selector14)
              if selector14.isInstanceOf[Any] then {
                false
              } else matchFail41()
            }
            if selector14.isInstanceOf[Grass$] then {
              val x$0: Grass$ = selector14.asInstanceOf[Grass$(x$0)]
              {
                true
              }
            } else case81()
          }
          case71()
        }
      })
    override def toString(): String = scala.runtime.ScalaRunTime._toString(this)
    override def canEqual(that: Any): Boolean = that.isInstanceOf[Grass$]
    override def productPrefix: String = "Grass$"
  }
  def getFoodFor(a: Animal): Food & Product0 = {
    case val selector15: Animal = a
    {
      def case91(): Meat$ | Grass$ = {
        def case101(): Meat$ | Grass$ = {
          def matchFail51(): Meat$ | Grass$ = throw new MatchError(selector15)
          if selector15.isInstanceOf[Cow] then {
            val cw: Cow = selector15.asInstanceOf[Cow(cw)]
            {
              {
                Grass
              }
            }
          } else matchFail51()
        }
        if selector15.isInstanceOf[Cat] then {
          val c: Cat = selector15.asInstanceOf[Cat(c)]
          {
            {
              Meat
            }
          }
        } else case101()
      }
      case91()
    }
  }
  getFoodFor(Cat.apply("Garfield"))
  {
    getFoodFor(Cow.apply("UHV"))
    ()
  }
} of class class dotty.tools.dotc.ast.Trees$DefDef # 1607
exception while transforming () extends Object() { this: test.HoistUpNestedIfElses.type => 
  def main(args: Array[String]): Unit = {
    <trait> sealed interface trait Animal() extends Object {}
    final lazy module val Animal: Animal$ = new Animal$()
    final module class Animal$() extends Object() { this: Animal.type =>}
    case class Cat(name: String) extends Object() with Animal with Product1[
      String
    ] { 
      val name: String
      def copy(name: String): Cat = new Cat(name)
      def copy$default$1: String @uncheckedVariance = 
        this.name: String @uncheckedVariance
      def isDefined: Boolean = true
      def _1: String = this.name
      override def hashCode(): Int = {
        var acc: Int = -889275714
        acc = 
          scala.runtime.Statics$#mix(acc, 
            scala.runtime.Statics$#anyHash(this.name)
          )
        scala.runtime.Statics$#finalizeHash(acc, 1)
      }
      override def equals(x$0: Any): Boolean = 
        this.eq(x$0.asInstanceOf[Object]).||({
          case val selector11: Any = x$0
          {
            def case11(): Boolean = {
              def case21(): Boolean = {
                def matchFail11(): Boolean = throw new MatchError(selector11)
                if selector11.isInstanceOf[Any] then {
                  false
                } else matchFail11()
              }
              if selector11.isInstanceOf[Cat] then {
                val x$0: Cat = selector11.asInstanceOf[Cat(x$0)]
                {
                  this.name.==(x$0.name)
                }
              } else case21()
            }
            case11()
          }
        })
      override def toString(): String = 
        scala.runtime.ScalaRunTime._toString(this)
      override def canEqual(that: Any): Boolean = that.isInstanceOf[Cat]
      override def productPrefix: String = "Cat"
    }
    final lazy module val Cat: Cat$ = new Cat$()
    final module class Cat$() extends Object() with (String => Cat) { 
      this: Cat.type =>

      def apply(name: String): Cat = new Cat(name)
      def unapply(x$1: Cat): Cat = x$1
    }
    case class Cow(typeOfMilk: String) extends Object() with Animal with 
      Product1
    [String] { 
      val typeOfMilk: String
      def copy(typeOfMilk: String): Cow = new Cow(typeOfMilk)
      def copy$default$1: String @uncheckedVariance = 
        this.typeOfMilk: String @uncheckedVariance
      def isDefined: Boolean = true
      def _1: String = this.typeOfMilk
      override def hashCode(): Int = {
        var acc: Int = -889275714
        acc = 
          scala.runtime.Statics$#mix(acc, 
            scala.runtime.Statics$#anyHash(this.typeOfMilk)
          )
        scala.runtime.Statics$#finalizeHash(acc, 1)
      }
      override def equals(x$0: Any): Boolean = 
        this.eq(x$0.asInstanceOf[Object]).||({
          case val selector12: Any = x$0
          {
            def case31(): Boolean = {
              def case41(): Boolean = {
                def matchFail21(): Boolean = throw new MatchError(selector12)
                if selector12.isInstanceOf[Any] then {
                  false
                } else matchFail21()
              }
              if selector12.isInstanceOf[Cow] then {
                val x$0: Cow = selector12.asInstanceOf[Cow(x$0)]
                {
                  this.typeOfMilk.==(x$0.typeOfMilk)
                }
              } else case41()
            }
            case31()
          }
        })
      override def toString(): String = 
        scala.runtime.ScalaRunTime._toString(this)
      override def canEqual(that: Any): Boolean = that.isInstanceOf[Cow]
      override def productPrefix: String = "Cow"
    }
    final lazy module val Cow: Cow$ = new Cow$()
    final module class Cow$() extends Object() with (String => Cow) { 
      this: Cow.type =>

      def apply(typeOfMilk: String): Cow = new Cow(typeOfMilk)
      def unapply(x$1: Cow): Cow = x$1
    }
    <trait> sealed interface trait Food() extends Object {}
    final lazy module val Food: Food$ = new Food$()
    final module class Food$() extends Object() { this: Food.type =>}
    final lazy module case val Meat: Meat$ = new Meat$()
    final module case class Meat$() extends Object() with Food with Product0 { 
      this: Meat.type =>

      override def hashCode(): Int = {
        var acc: Int = -889275714
        scala.runtime.Statics$#finalizeHash(acc, 0)
      }
      override def equals(x$0: Any): Boolean = 
        this.eq(x$0.asInstanceOf[Object]).||({
          case val selector13: Any = x$0
          {
            def case51(): Boolean = {
              def case61(): Boolean = {
                def matchFail31(): Boolean = throw new MatchError(selector13)
                if selector13.isInstanceOf[Any] then {
                  false
                } else matchFail31()
              }
              if selector13.isInstanceOf[Meat$] then {
                val x$0: Meat$ = selector13.asInstanceOf[Meat$(x$0)]
                {
                  true
                }
              } else case61()
            }
            case51()
          }
        })
      override def toString(): String = 
        scala.runtime.ScalaRunTime._toString(this)
      override def canEqual(that: Any): Boolean = that.isInstanceOf[Meat$]
      override def productPrefix: String = "Meat$"
    }
    final lazy module case val Grass: Grass$ = new Grass$()
    final module case class Grass$() extends Object() with Food with Product0 { 
      this: Grass.type =>

      override def hashCode(): Int = {
        var acc: Int = -889275714
        scala.runtime.Statics$#finalizeHash(acc, 0)
      }
      override def equals(x$0: Any): Boolean = 
        this.eq(x$0.asInstanceOf[Object]).||({
          case val selector14: Any = x$0
          {
            def case71(): Boolean = {
              def case81(): Boolean = {
                def matchFail41(): Boolean = throw new MatchError(selector14)
                if selector14.isInstanceOf[Any] then {
                  false
                } else matchFail41()
              }
              if selector14.isInstanceOf[Grass$] then {
                val x$0: Grass$ = selector14.asInstanceOf[Grass$(x$0)]
                {
                  true
                }
              } else case81()
            }
            case71()
          }
        })
      override def toString(): String = 
        scala.runtime.ScalaRunTime._toString(this)
      override def canEqual(that: Any): Boolean = that.isInstanceOf[Grass$]
      override def productPrefix: String = "Grass$"
    }
    def getFoodFor(a: Animal): Food & Product0 = {
      case val selector15: Animal = a
      {
        def case91(): Meat$ | Grass$ = {
          def case101(): Meat$ | Grass$ = {
            def matchFail51(): Meat$ | Grass$ = throw new MatchError(selector15)
            if selector15.isInstanceOf[Cow] then {
              val cw: Cow = selector15.asInstanceOf[Cow(cw)]
              {
                {
                  Grass
                }
              }
            } else matchFail51()
          }
          if selector15.isInstanceOf[Cat] then {
            val c: Cat = selector15.asInstanceOf[Cat(c)]
            {
              {
                Meat
              }
            }
          } else case101()
        }
        case91()
      }
    }
    getFoodFor(Cat.apply("Garfield"))
    {
      getFoodFor(Cow.apply("UHV"))
      ()
    }
  }
} of class class dotty.tools.dotc.ast.Trees$Template # 1608
exception while transforming final module class HoistUpNestedIfElses$() extends Object() { 
  this: test.HoistUpNestedIfElses.type =>

  def main(args: Array[String]): Unit = {
    <trait> sealed interface trait Animal() extends Object {}
    final lazy module val Animal: Animal$ = new Animal$()
    final module class Animal$() extends Object() { this: Animal.type =>}
    case class Cat(name: String) extends Object() with Animal with Product1[
      String
    ] { 
      val name: String
      def copy(name: String): Cat = new Cat(name)
      def copy$default$1: String @uncheckedVariance = 
        this.name: String @uncheckedVariance
      def isDefined: Boolean = true
      def _1: String = this.name
      override def hashCode(): Int = {
        var acc: Int = -889275714
        acc = 
          scala.runtime.Statics$#mix(acc, 
            scala.runtime.Statics$#anyHash(this.name)
          )
        scala.runtime.Statics$#finalizeHash(acc, 1)
      }
      override def equals(x$0: Any): Boolean = 
        this.eq(x$0.asInstanceOf[Object]).||({
          case val selector11: Any = x$0
          {
            def case11(): Boolean = {
              def case21(): Boolean = {
                def matchFail11(): Boolean = throw new MatchError(selector11)
                if selector11.isInstanceOf[Any] then {
                  false
                } else matchFail11()
              }
              if selector11.isInstanceOf[Cat] then {
                val x$0: Cat = selector11.asInstanceOf[Cat(x$0)]
                {
                  this.name.==(x$0.name)
                }
              } else case21()
            }
            case11()
          }
        })
      override def toString(): String = 
        scala.runtime.ScalaRunTime._toString(this)
      override def canEqual(that: Any): Boolean = that.isInstanceOf[Cat]
      override def productPrefix: String = "Cat"
    }
    final lazy module val Cat: Cat$ = new Cat$()
    final module class Cat$() extends Object() with (String => Cat) { 
      this: Cat.type =>

      def apply(name: String): Cat = new Cat(name)
      def unapply(x$1: Cat): Cat = x$1
    }
    case class Cow(typeOfMilk: String) extends Object() with Animal with 
      Product1
    [String] { 
      val typeOfMilk: String
      def copy(typeOfMilk: String): Cow = new Cow(typeOfMilk)
      def copy$default$1: String @uncheckedVariance = 
        this.typeOfMilk: String @uncheckedVariance
      def isDefined: Boolean = true
      def _1: String = this.typeOfMilk
      override def hashCode(): Int = {
        var acc: Int = -889275714
        acc = 
          scala.runtime.Statics$#mix(acc, 
            scala.runtime.Statics$#anyHash(this.typeOfMilk)
          )
        scala.runtime.Statics$#finalizeHash(acc, 1)
      }
      override def equals(x$0: Any): Boolean = 
        this.eq(x$0.asInstanceOf[Object]).||({
          case val selector12: Any = x$0
          {
            def case31(): Boolean = {
              def case41(): Boolean = {
                def matchFail21(): Boolean = throw new MatchError(selector12)
                if selector12.isInstanceOf[Any] then {
                  false
                } else matchFail21()
              }
              if selector12.isInstanceOf[Cow] then {
                val x$0: Cow = selector12.asInstanceOf[Cow(x$0)]
                {
                  this.typeOfMilk.==(x$0.typeOfMilk)
                }
              } else case41()
            }
            case31()
          }
        })
      override def toString(): String = 
        scala.runtime.ScalaRunTime._toString(this)
      override def canEqual(that: Any): Boolean = that.isInstanceOf[Cow]
      override def productPrefix: String = "Cow"
    }
    final lazy module val Cow: Cow$ = new Cow$()
    final module class Cow$() extends Object() with (String => Cow) { 
      this: Cow.type =>

      def apply(typeOfMilk: String): Cow = new Cow(typeOfMilk)
      def unapply(x$1: Cow): Cow = x$1
    }
    <trait> sealed interface trait Food() extends Object {}
    final lazy module val Food: Food$ = new Food$()
    final module class Food$() extends Object() { this: Food.type =>}
    final lazy module case val Meat: Meat$ = new Meat$()
    final module case class Meat$() extends Object() with Food with Product0 { 
      this: Meat.type =>

      override def hashCode(): Int = {
        var acc: Int = -889275714
        scala.runtime.Statics$#finalizeHash(acc, 0)
      }
      override def equals(x$0: Any): Boolean = 
        this.eq(x$0.asInstanceOf[Object]).||({
          case val selector13: Any = x$0
          {
            def case51(): Boolean = {
              def case61(): Boolean = {
                def matchFail31(): Boolean = throw new MatchError(selector13)
                if selector13.isInstanceOf[Any] then {
                  false
                } else matchFail31()
              }
              if selector13.isInstanceOf[Meat$] then {
                val x$0: Meat$ = selector13.asInstanceOf[Meat$(x$0)]
                {
                  true
                }
              } else case61()
            }
            case51()
          }
        })
      override def toString(): String = 
        scala.runtime.ScalaRunTime._toString(this)
      override def canEqual(that: Any): Boolean = that.isInstanceOf[Meat$]
      override def productPrefix: String = "Meat$"
    }
    final lazy module case val Grass: Grass$ = new Grass$()
    final module case class Grass$() extends Object() with Food with Product0 { 
      this: Grass.type =>

      override def hashCode(): Int = {
        var acc: Int = -889275714
        scala.runtime.Statics$#finalizeHash(acc, 0)
      }
      override def equals(x$0: Any): Boolean = 
        this.eq(x$0.asInstanceOf[Object]).||({
          case val selector14: Any = x$0
          {
            def case71(): Boolean = {
              def case81(): Boolean = {
                def matchFail41(): Boolean = throw new MatchError(selector14)
                if selector14.isInstanceOf[Any] then {
                  false
                } else matchFail41()
              }
              if selector14.isInstanceOf[Grass$] then {
                val x$0: Grass$ = selector14.asInstanceOf[Grass$(x$0)]
                {
                  true
                }
              } else case81()
            }
            case71()
          }
        })
      override def toString(): String = 
        scala.runtime.ScalaRunTime._toString(this)
      override def canEqual(that: Any): Boolean = that.isInstanceOf[Grass$]
      override def productPrefix: String = "Grass$"
    }
    def getFoodFor(a: Animal): Food & Product0 = {
      case val selector15: Animal = a
      {
        def case91(): Meat$ | Grass$ = {
          def case101(): Meat$ | Grass$ = {
            def matchFail51(): Meat$ | Grass$ = throw new MatchError(selector15)
            if selector15.isInstanceOf[Cow] then {
              val cw: Cow = selector15.asInstanceOf[Cow(cw)]
              {
                {
                  Grass
                }
              }
            } else matchFail51()
          }
          if selector15.isInstanceOf[Cat] then {
            val c: Cat = selector15.asInstanceOf[Cat(c)]
            {
              {
                Meat
              }
            }
          } else case101()
        }
        case91()
      }
    }
    getFoodFor(Cat.apply("Garfield"))
    {
      getFoodFor(Cow.apply("UHV"))
      ()
    }
  }
} of class class dotty.tools.dotc.ast.Trees$TypeDef # 1609
exception while transforming package test {
  final lazy module val HoistUpNestedIfElses: test.HoistUpNestedIfElses$ = 
    new test.HoistUpNestedIfElses$()
  final module class HoistUpNestedIfElses$() extends Object() { 
    this: test.HoistUpNestedIfElses.type =>

    def main(args: Array[String]): Unit = {
      <trait> sealed interface trait Animal() extends Object {}
      final lazy module val Animal: Animal$ = new Animal$()
      final module class Animal$() extends Object() { this: Animal.type =>}
      case class Cat(name: String) extends Object() with Animal with Product1[
        String
      ] { 
        val name: String
        def copy(name: String): Cat = new Cat(name)
        def copy$default$1: String @uncheckedVariance = 
          this.name: String @uncheckedVariance
        def isDefined: Boolean = true
        def _1: String = this.name
        override def hashCode(): Int = {
          var acc: Int = -889275714
          acc = 
            scala.runtime.Statics$#mix(acc, 
              scala.runtime.Statics$#anyHash(this.name)
            )
          scala.runtime.Statics$#finalizeHash(acc, 1)
        }
        override def equals(x$0: Any): Boolean = 
          this.eq(x$0.asInstanceOf[Object]).||({
            case val selector11: Any = x$0
            {
              def case11(): Boolean = {
                def case21(): Boolean = {
                  def matchFail11(): Boolean = throw new MatchError(selector11)
                  if selector11.isInstanceOf[Any] then {
                    false
                  } else matchFail11()
                }
                if selector11.isInstanceOf[Cat] then {
                  val x$0: Cat = selector11.asInstanceOf[Cat(x$0)]
                  {
                    this.name.==(x$0.name)
                  }
                } else case21()
              }
              case11()
            }
          })
        override def toString(): String = 
          scala.runtime.ScalaRunTime._toString(this)
        override def canEqual(that: Any): Boolean = that.isInstanceOf[Cat]
        override def productPrefix: String = "Cat"
      }
      final lazy module val Cat: Cat$ = new Cat$()
      final module class Cat$() extends Object() with (String => Cat) { 
        this: Cat.type =>

        def apply(name: String): Cat = new Cat(name)
        def unapply(x$1: Cat): Cat = x$1
      }
      case class Cow(typeOfMilk: String) extends Object() with Animal with 
        Product1
      [String] { 
        val typeOfMilk: String
        def copy(typeOfMilk: String): Cow = new Cow(typeOfMilk)
        def copy$default$1: String @uncheckedVariance = 
          this.typeOfMilk: String @uncheckedVariance
        def isDefined: Boolean = true
        def _1: String = this.typeOfMilk
        override def hashCode(): Int = {
          var acc: Int = -889275714
          acc = 
            scala.runtime.Statics$#mix(acc, 
              scala.runtime.Statics$#anyHash(this.typeOfMilk)
            )
          scala.runtime.Statics$#finalizeHash(acc, 1)
        }
        override def equals(x$0: Any): Boolean = 
          this.eq(x$0.asInstanceOf[Object]).||({
            case val selector12: Any = x$0
            {
              def case31(): Boolean = {
                def case41(): Boolean = {
                  def matchFail21(): Boolean = throw new MatchError(selector12)
                  if selector12.isInstanceOf[Any] then {
                    false
                  } else matchFail21()
                }
                if selector12.isInstanceOf[Cow] then {
                  val x$0: Cow = selector12.asInstanceOf[Cow(x$0)]
                  {
                    this.typeOfMilk.==(x$0.typeOfMilk)
                  }
                } else case41()
              }
              case31()
            }
          })
        override def toString(): String = 
          scala.runtime.ScalaRunTime._toString(this)
        override def canEqual(that: Any): Boolean = that.isInstanceOf[Cow]
        override def productPrefix: String = "Cow"
      }
      final lazy module val Cow: Cow$ = new Cow$()
      final module class Cow$() extends Object() with (String => Cow) { 
        this: Cow.type =>

        def apply(typeOfMilk: String): Cow = new Cow(typeOfMilk)
        def unapply(x$1: Cow): Cow = x$1
      }
      <trait> sealed interface trait Food() extends Object {}
      final lazy module val Food: Food$ = new Food$()
      final module class Food$() extends Object() { this: Food.type =>}
      final lazy module case val Meat: Meat$ = new Meat$()
      final module case class Meat$() extends Object() with Food with Product0 {

      this: Meat.type => 
        override def hashCode(): Int = {
          var acc: Int = -889275714
          scala.runtime.Statics$#finalizeHash(acc, 0)
        }
        override def equals(x$0: Any): Boolean = 
          this.eq(x$0.asInstanceOf[Object]).||({
            case val selector13: Any = x$0
            {
              def case51(): Boolean = {
                def case61(): Boolean = {
                  def matchFail31(): Boolean = throw new MatchError(selector13)
                  if selector13.isInstanceOf[Any] then {
                    false
                  } else matchFail31()
                }
                if selector13.isInstanceOf[Meat$] then {
                  val x$0: Meat$ = selector13.asInstanceOf[Meat$(x$0)]
                  {
                    true
                  }
                } else case61()
              }
              case51()
            }
          })
        override def toString(): String = 
          scala.runtime.ScalaRunTime._toString(this)
        override def canEqual(that: Any): Boolean = that.isInstanceOf[Meat$]
        override def productPrefix: String = "Meat$"
      }
      final lazy module case val Grass: Grass$ = new Grass$()
      final module case class Grass$() extends Object() with Food with Product0 
        {
       this: Grass.type => 
        override def hashCode(): Int = {
          var acc: Int = -889275714
          scala.runtime.Statics$#finalizeHash(acc, 0)
        }
        override def equals(x$0: Any): Boolean = 
          this.eq(x$0.asInstanceOf[Object]).||({
            case val selector14: Any = x$0
            {
              def case71(): Boolean = {
                def case81(): Boolean = {
                  def matchFail41(): Boolean = throw new MatchError(selector14)
                  if selector14.isInstanceOf[Any] then {
                    false
                  } else matchFail41()
                }
                if selector14.isInstanceOf[Grass$] then {
                  val x$0: Grass$ = selector14.asInstanceOf[Grass$(x$0)]
                  {
                    true
                  }
                } else case81()
              }
              case71()
            }
          })
        override def toString(): String = 
          scala.runtime.ScalaRunTime._toString(this)
        override def canEqual(that: Any): Boolean = that.isInstanceOf[Grass$]
        override def productPrefix: String = "Grass$"
      }
      def getFoodFor(a: Animal): Food & Product0 = {
        case val selector15: Animal = a
        {
          def case91(): Meat$ | Grass$ = {
            def case101(): Meat$ | Grass$ = {
              def matchFail51(): Meat$ | Grass$ = 
                throw new MatchError(selector15)
              if selector15.isInstanceOf[Cow] then {
                val cw: Cow = selector15.asInstanceOf[Cow(cw)]
                {
                  {
                    Grass
                  }
                }
              } else matchFail51()
            }
            if selector15.isInstanceOf[Cat] then {
              val c: Cat = selector15.asInstanceOf[Cat(c)]
              {
                {
                  Meat
                }
              }
            } else case101()
          }
          case91()
        }
      }
      getFoodFor(Cat.apply("Garfield"))
      {
        getFoodFor(Cow.apply("UHV"))
        ()
      }
    }
  }
} of class class dotty.tools.dotc.ast.Trees$PackageDef # 1610
exception occurred while compiling test/test/HoistUpNestedIfElses.scala
Exception in thread "main" java.lang.AssertionError: assertion failed: asTerm called on not-a-Term val <none>
    at scala.Predef$.assert(Predef.scala:165)
    at dotty.tools.dotc.core.Symbols$Symbol.asTerm(Symbols.scala:409)
    at dotty.tools.dotc.ast.tpd$.New(tpd.scala:386)
    at dotty.tools.dotc.transform.linker.Simplify$$anonfun$5$$anonfun$6$$anonfun$apply$6.apply(Simplify.scala:113)
    at dotty.tools.dotc.transform.linker.Simplify$$anonfun$5$$anonfun$6$$anonfun$apply$6.apply(Simplify.scala:110)
    at dotty.tools.dotc.transform.linker.Simplify$$anon$1.transform(Simplify.scala:93)
    at dotty.tools.dotc.ast.Trees$Instance$TreeMap$$anonfun$transform$2.apply(Trees.scala:1182)
    at dotty.tools.dotc.ast.Trees$Instance$TreeMap$$anonfun$transform$2.apply(Trees.scala:1182)
    at scala.collection.immutable.List.loop$1(List.scala:173)
    at scala.collection.immutable.List.mapConserve(List.scala:189)
    at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1182)
    at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1101)
    at dotty.tools.dotc.transform.linker.Simplify$$anon$1.transform(Simplify.scala:93)
    at dotty.tools.dotc.ast.Trees$Instance$TreeMap$$anonfun$transform$2.apply(Trees.scala:1182)
    at dotty.tools.dotc.ast.Trees$Instance$TreeMap$$anonfun$transform$2.apply(Trees.scala:1182)
    at scala.collection.immutable.List.loop$1(List.scala:173)
    at scala.collection.immutable.List.mapConserve(List.scala:189)
    at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1182)
    at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transformStats(Trees.scala:1180)
    at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1117)
    at dotty.tools.dotc.transform.linker.Simplify$$anon$1.transform(Simplify.scala:93)
    at dotty.tools.dotc.transform.linker.Simplify.transformDefDef(Simplify.scala:94)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.goDefDef(TreeTransform.scala:834)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.transformNamed(TreeTransform.scala:1005)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer$$anonfun$transform$2.apply(TreeTransform.scala:1212)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer$$anonfun$transform$2.apply(TreeTransform.scala:1205)
    at dotty.tools.dotc.reporting.Reporting$class.traceIndented(Reporter.scala:154)
    at dotty.tools.dotc.core.Contexts$Context.traceIndented(Contexts.scala:53)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.transform(TreeTransform.scala:1204)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.dotty$tools$dotc$transform$TreeTransforms$TreeTransformer$$transformStat$1(TreeTransform.scala:1238)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer$$anonfun$38.apply(TreeTransform.scala:1242)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer$$anonfun$38.apply(TreeTransform.scala:1242)
    at dotty.tools.dotc.core.Decorators$ListDecorator$.loop$1(Decorators.scala:51)
    at dotty.tools.dotc.core.Decorators$ListDecorator$.mapconserve$extension(Decorators.scala:67)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.transformStats(TreeTransform.scala:1242)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.transformUnnamed(TreeTransform.scala:1183)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer$$anonfun$transform$2.apply(TreeTransform.scala:1213)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer$$anonfun$transform$2.apply(TreeTransform.scala:1205)
    at dotty.tools.dotc.reporting.Reporting$class.traceIndented(Reporter.scala:154)
    at dotty.tools.dotc.core.Contexts$Context.traceIndented(Contexts.scala:53)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.transform(TreeTransform.scala:1204)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.transformNamed(TreeTransform.scala:1011)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer$$anonfun$transform$2.apply(TreeTransform.scala:1212)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer$$anonfun$transform$2.apply(TreeTransform.scala:1205)
    at dotty.tools.dotc.reporting.Reporting$class.traceIndented(Reporter.scala:154)
    at dotty.tools.dotc.core.Contexts$Context.traceIndented(Contexts.scala:53)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.transform(TreeTransform.scala:1204)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.dotty$tools$dotc$transform$TreeTransforms$TreeTransformer$$transformStat$1(TreeTransform.scala:1238)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer$$anonfun$38.apply(TreeTransform.scala:1242)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer$$anonfun$38.apply(TreeTransform.scala:1242)
    at dotty.tools.dotc.core.Decorators$ListDecorator$.loop$1(Decorators.scala:51)
    at dotty.tools.dotc.core.Decorators$ListDecorator$.mapconserve$extension(Decorators.scala:67)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.transformStats(TreeTransform.scala:1242)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.transformUnnamed(TreeTransform.scala:1192)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer$$anonfun$transform$2.apply(TreeTransform.scala:1213)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer$$anonfun$transform$2.apply(TreeTransform.scala:1205)
    at dotty.tools.dotc.reporting.Reporting$class.traceIndented(Reporter.scala:154)
    at dotty.tools.dotc.core.Contexts$Context.traceIndented(Contexts.scala:53)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.transform(TreeTransform.scala:1204)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.macroTransform(TreeTransform.scala:563)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.run(TreeTransform.scala:480)
    at dotty.tools.dotc.core.Phases$Phase$$anonfun$runOn$1.apply(Phases.scala:279)
    at dotty.tools.dotc.core.Phases$Phase$$anonfun$runOn$1.apply(Phases.scala:277)
    at scala.collection.immutable.List.map(List.scala:273)
    at dotty.tools.dotc.core.Phases$Phase$class.runOn(Phases.scala:277)
    at dotty.tools.dotc.transform.TreeTransforms$TreeTransformer.runOn(TreeTransform.scala:474)
    at dotty.tools.dotc.Run$$anonfun$compileUnits$1$$anonfun$apply$mcV$sp$1.apply(Run.scala:67)
    at dotty.tools.dotc.Run$$anonfun$compileUnits$1$$anonfun$apply$mcV$sp$1.apply(Run.scala:64)
    at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
    at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
    at dotty.tools.dotc.Run$$anonfun$compileUnits$1.apply$mcV$sp(Run.scala:64)
    at dotty.tools.dotc.Run$$anonfun$compileUnits$1.apply(Run.scala:59)
    at dotty.tools.dotc.Run$$anonfun$compileUnits$1.apply(Run.scala:59)
    at dotty.tools.dotc.util.Stats$.monitorHeartBeat(Stats.scala:69)
    at dotty.tools.dotc.Run.compileUnits(Run.scala:59)
    at dotty.tools.dotc.Run.compileSources(Run.scala:56)
    at dotty.tools.dotc.Run.compile(Run.scala:40)
    at dotty.tools.dotc.Driver.doCompile(Driver.scala:21)
    at dotty.tools.dotc.Driver.process(Driver.scala:47)
    at dotty.tools.dotc.Driver.process(Driver.scala:57)
    at dotty.tools.dotc.Driver.main(Driver.scala:65)
    at dotty.tools.dotc.Main.main(Main.scala)

in the simplify branch while scalac compiles it just fine. It looks like it's a problem with the optimizations performed in the simplify phase.

DarkDimius commented 8 years ago

Fixed in unstuch branch to get you unstuck. Will work on a proper fix after student presentations.