[macros] untypecheck seems to produce invalid code

69 views
Skip to first unread message

Stefan Ollinger

unread,
Jun 15, 2015, 9:59:37 AM6/15/15
to scala-l...@googlegroups.com
Hey,

See attached example. Is that a known bug or am I doing something wrong?

Regards,
Stefan

------

import scala.reflect.runtime.universe._
import scala.reflect.macros.blackbox.Context
import scala.language.experimental.macros
 
abstract class A {
val is: Int
}
 
def fooImpl(c: Context)(expr: c.Expr[Any]) = {
import c.universe._
 
println(expr)
// Expr[Nothing]({
// final class $anon extends $line22.$read.$iw.$iw.$iw.$iw.$iw.$iw.A {
// def <init>(): <$anon: A> = {
// $anon.super.<init>();
// ()
// };
// private[this] val is: Int = 100;
// override <stable> <accessor> def is: Int = $anon.this.is
// };
// new $anon()
// })
 
val untypedExpr = c.Expr[Any](c.untypecheck(expr.tree.duplicate))
 
println(untypedExpr) // this is invalid: override private[this] val is = 100;
// Expr[Any]({
// final class $anon extends $line22.$read.$iw.$iw.$iw.$iw.$iw.$iw.A {
// def <init>() = {
// super.<init>();
// ()
// };
// override private[this] val is = 100;
// override <stable> <accessor> def is: Int = $anon.this.is
// };
// new $anon()
// })
 
untypedExpr
}
 
def foo(expr: => Any): Any = macro fooImpl
 
// 1. this does not work
foo {
new A {
override val is = 100
}
}
 
// <console>:18: error: value is overrides nothing
// override val is = 100
 
// 2. this works
val tree = reify {
new A {
override val is = 100
}
}
 
// tree: reflect.runtime.universe.Expr[A] =
// Expr[A]({
// final class $anon extends $read.A {
// def <init>() = {
// super.<init>();
// ()
// };
// override val is = 100
// };
// new $anon()
// })

Stefan Ollinger

unread,
Jun 15, 2015, 6:52:08 PM6/15/15
to scala-l...@googlegroups.com
Here is another issue:

import scala.reflect.runtime.universe._
import scala.reflect.macros.blackbox.Context
import scala.language.experimental.macros

def fooImpl(c: Context)(expr: c.Expr[Any]) = {
  import c.universe._

  val untypedExpr = c.Expr[Any](c.untypecheck(expr.tree.duplicate))

  println(expr)
  // Expr[Nothing]((({
  //   @SerialVersionUID(0) final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[Any,Any] with Serializable {
  //     def <init>(): <$anon: Any => Any> = {
  //       $anonfun.super.<init>();
  //       ()
  //     };
  //     final override def applyOrElse[A1, B1 >: Any](x1: A1, default: A1 => B1): B1 = ((x1.asInstanceOf[Any]: Any): Any @unchecked) match {
  //       case scala.util.control.NonFatal.unapply(<unapply-selector>) <unapply> ((e @ _)) => ()
  //       case (defaultCase$ @ _) => default.apply(x1)
  //     };
  //     final def isDefinedAt(x1: Any): Boolean = ((x1.asInstanceOf[Any]: Any): Any @unchecked) match {
  //       case scala.util.control.NonFatal.unapply(<unapply-selector>) <unapply> ((e @ _)) => true
  //       case (defaultCase$ @ _) => false
  //     }
  //   };
  //   new $anonfun()
  // }: PartialFunction[Any,Any]): PartialFunction[Any,Any]))
  
  println(untypedExpr)
  // Expr[Any]((({
  //   final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[Any,Any] with Serializable {
  //     def <init>() = {
  //       super.<init>();
  //       ()
  //     };
  //     final override def applyOrElse[A1, B1 >: Any](x1: A1, default: scala.this.Function1[A1, B1]) = ((x1.asInstanceOf[Any]: Any): (x1.asInstanceOf[Any]: Any): @scala.unchecked) match {
  //       case scala.util.control.NonFatal.unapply(<unapply-selector>) <unapply> ((e @ _)) => ()
  //       case (defaultCase$ @ _) => default.apply(x1)
  //     };
  //     final def isDefinedAt(x1: Any): Boolean = ((x1.asInstanceOf[Any]: Any): (x1.asInstanceOf[Any]: Any): @scala.unchecked) match {
  //       case scala.util.control.NonFatal.unapply(<unapply-selector>) <unapply> ((e @ _)) => true
  //       case (defaultCase$ @ _) => false
  //     }
  //   };
  //   new $anonfun()
  // }: PartialFunction[Any,Any]): scala.PartialFunction[scala.Any, scala.Any]))

  untypedExpr
}

def foo(expr: => Any): Any = macro fooImpl

foo { ({ case scala.util.control.NonFatal(e) => }):PartialFunction[Any, Any] }

// ReplGlobal.abort: unexpected UnApply scala.util.control.NonFatal.unapply(<unapply-selector>) <unapply> ((e @ _))
// 
// error: unexpected UnApply scala.util.control.NonFatal.unapply(<unapply-selector>) <unapply> ((e @ _))
// scala.reflect.internal.FatalError: unexpected UnApply scala.util.control.NonFatal.unapply(<unapply-selector>) <unapply> ((e @ _))
//   at scala.reflect.internal.Reporting$class.abort(Reporting.scala:59)
//   at scala.tools.nsc.interpreter.IMain$$anon$1.scala$tools$nsc$interpreter$ReplGlobal$$super$abort(IMain.scala:237)
//   at scala.tools.nsc.interpreter.ReplGlobal$class.abort(ReplGlobal.scala:20)
//   at scala.tools.nsc.interpreter.IMain$$anon$1.abort(IMain.scala:237)
//   at scala.tools.nsc.typechecker.Typers$Typer.typedInAnyMode$1(Typers.scala:5247)
//   at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5259)
//   at scala.tools.nsc.typechecker.Typers$Typer.runTyper$1(Typers.scala:5295)
//   at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedInternal(Typers.scala:5322)
//   at scala.tools.nsc.typechecker.Typers$Typer.body$2(Typers.scala:5269)
//   at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5273)
//   at scala.tools.nsc.interpreter.ReplGlobal$$anon$1$$anon$2.typed(ReplGlobal.scala:36)
//   at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$113$$anonfun$apply$55.apply(Typers.scala:5408)
//   at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$113.apply(Typers.scala:5408)
//   at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$113.apply(Typers.scala:5408)
//   at scala.tools.nsc.typechecker.TypeDiagnostics$class.typingInPattern(TypeDiagnostics.scala:62)
//   at scala.tools.nsc.interpreter.ReplGlobal$$anon$1.typingInPattern(ReplGlobal.scala:23)
//   at scala.tools.nsc.typechecker.Typers$Typer.typedPattern(Typers.scala:5408)
//   at scala.tools.nsc.typechecker.Typers$Typer.typedCase(Typers.scala:2359)
//   at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedCases$1.apply(Typers.scala:2399)
//   at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedCases$1.apply(Typers.scala:2398)
//   at scala.collection.immutable.List.loop$1(List.scala:172)
//   at scala.collection.immutable.List.mapConserve(List.scala:188)
//   at scala.tools.nsc.typechecker.Typers$Typer.typedCases(Typers.scala:2398)
//   ...
// 
// That entry seems to have slain the compiler.  Shall I replay
// your session? I can re-run each line except the last one.
Reply all
Reply to author
Forward
0 new messages