Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CodePrinter fails to print the expr in Typed if the tpt does not have an original #8447

Closed
scabug opened this issue Mar 26, 2014 · 9 comments
Milestone

Comments

@scabug
Copy link

scabug commented Mar 26, 2014

class C {
  def test {
    reflect.runtime.universe.typeOf[_67.u.TermName forSome { val _67: AnyRef{val u: reflect.runtime.universe.type} }]
  }
}

running that tree through showCode

class C {
  def test: scala.Unit = {
    scala.reflect.runtime.`package`.universe.typeOf[(_67.u.TermName forSome {
      val _67: AnyRef {
        val u: reflect.runtime.universe.type
      }
    })](());
    ()
  }
}

Applying this patch:

diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 35eab94..5cfeb9b 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -174,7 +174,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
       print(" // " + unit.source)
       if (unit.body == null) println(": tree is null")
       else {
-        val source = util.stringFromWriter(w => newTreePrinter(w) print unit.body)
+        def printer(w: PrintWriter) = if (sys.props("scala.print.code") != null) newCodePrinter(w, unit.body, printRootPkg = false) else newTreePrinter(w)
+        val source = util.stringFromWriter(w => printer(w) print unit.body)
 
         // treePrinter show unit.body
         if (lastPrintedSource == source)
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index fcc377b..809b46d 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -949,13 +949,15 @@ trait Printers extends api.Printers { self: SymbolTable =>
           printFunction(f)(printValueParams(vparams, inParentheses = printParentheses))
 
         case Typed(expr, tp) =>
-          def printTp = print("(", tp, ")")
+          def printExpr = print("(", expr, ")")
 
           tp match {
-            case EmptyTree | build.SyntacticEmptyTypeTree() => printTp
+            case EmptyTree | build.SyntacticEmptyTypeTree() =>
+              // TODO not sure that we can omit TypeTrees without an original, what about macro synthezised trees?
+              printExpr
             // case for untypechecked trees
-            case Annotated(annot, arg) if (expr ne null) && (arg ne null) && expr.equalsStructure(arg) => printTp // remove double arg - 5: 5: @unchecked
-            case tt: TypeTree if tt.original.isInstanceOf[Annotated] => printTp
+            case Annotated(annot, arg) if (expr ne null) && (arg ne null) && expr.equalsStructure(arg) => printExpr // remove double arg - 5: 5: @unchecked
+            case tt: TypeTree if tt.original.isInstanceOf[Annotated] => printExpr
             case Function(List(), EmptyTree) => print("(", expr, " _)") //func _
             // parentheses required when (a match {}) : Type
             case _ => print("((", expr, "): ", tp, ")")

Gives the desired output:

qbin/scalac -Xprint:patmat -Dscala.print.code sandbox/test.scala
[[syntax trees at end of                    patmat]] // test.scala
class C {
  def test: scala.Unit = {
    scala.reflect.runtime.`package`.universe.typeOf[(_67.u.TermName forSome {
      val _67: AnyRef {
        val u: reflect.runtime.universe.type
      }
    })](({
      val $u: scala.reflect.runtime.`package`.universe.type = scala.reflect.runtime.`package`.universe;
      val $m: $u.Mirror = scala.reflect.runtime.`package`.universe.runtimeMirror(classOf[C].getClassLoader());
      $u.TypeTag.apply($m, {
        final class $typecreator1 extends TypeCreator {
          def apply[U <: Universe with Singleton]($m$untyped: Mirror[U]): (U)#Type = {
            val $u: U = $m$untyped.universe;
            val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
            val symdef$_67$type1 = $u.internal.reificationSupport.newNestedSymbol($u.internal.reificationSupport.selectTerm($m.staticClass("C"), "test"), $u.TypeName.apply("_67.type"), $u.NoPosition, $u.internal.reificationSupport.FlagsRepr.apply(34359738384L), false);
            val free$u1 = $u.internal.reificationSupport.newFreeTerm("u", u, $u.internal.reificationSupport.FlagsRepr.apply(17592324456528L), "defined by <refinement> in test.scala:4:82");
            val `symdef$<refinement>1` = $u.internal.reificationSupport.newNestedSymbol($m.staticPackage("scala").asModule.moduleClass, $u.TypeName.apply("<refinement>"), $u.NoPosition, $u.internal.reificationSupport.FlagsRepr.apply(0L), true);
            val `symdef$<refinement>2` = $u.internal.reificationSupport.newNestedSymbol($m.staticClass("C"), $u.TypeName.apply("<refinement>"), $u.NoPosition, $u.internal.reificationSupport.FlagsRepr.apply(0L), true);
            $u.internal.reificationSupport.setInfo(symdef$_67$type1, $u.internal.reificationSupport.TypeBounds($m.staticClass("scala.Nothing").asType.toTypeConstructor, $u.internal.reificationSupport.RefinedType(scala.collection.immutable.List.apply($u.internal.reificationSupport.RefinedType(scala.collection.immutable.List.apply($u.internal.reificationSupport.TypeRef($u.internal.reificationSupport.ThisType($m.staticPackage("scala").asModule.moduleClass), $u.internal.reificationSupport.selectType($m.staticPackage("scala").asModule.moduleClass, "AnyRef"), scala.collection.immutable.Nil)), $u.internal.reificationSupport.newScopeWith(free$u1), `symdef$<refinement>2`), $m.staticClass("scala.Singleton").asType.toTypeConstructor), $u.internal.reificationSupport.newScopeWith(), `symdef$<refinement>1`)));
            $u.internal.reificationSupport.setInfo(free$u1, $u.internal.reificationSupport.NullaryMethodType($u.internal.reificationSupport.SingleType($u.internal.reificationSupport.SingleType($u.internal.reificationSupport.SingleType($u.internal.reificationSupport.SingleType($u.internal.reificationSupport.ThisType($m.staticPackage("scala").asModule.moduleClass), $m.staticPackage("scala.reflect")), $m.staticPackage("scala.reflect.runtime")), $m.staticModule("scala.reflect.runtime.package")), $u.internal.reificationSupport.selectTerm($m.staticModule("scala.reflect.runtime.package").asModule.moduleClass, "universe"))));
            $u.internal.reificationSupport.setInfo(`symdef$<refinement>1`, $u.internal.reificationSupport.RefinedType(scala.collection.immutable.List.apply($u.internal.reificationSupport.RefinedType(scala.collection.immutable.List.apply($u.internal.reificationSupport.TypeRef($u.internal.reificationSupport.ThisType($m.staticPackage("scala").asModule.moduleClass), $u.internal.reificationSupport.selectType($m.staticPackage("scala").asModule.moduleClass, "AnyRef"), scala.collection.immutable.Nil)), $u.internal.reificationSupport.newScopeWith(free$u1), `symdef$<refinement>2`), $m.staticClass("scala.Singleton").asType.toTypeConstructor), $u.internal.reificationSupport.newScopeWith(), `symdef$<refinement>1`));
            $u.internal.reificationSupport.setInfo(`symdef$<refinement>2`, $u.internal.reificationSupport.RefinedType(scala.collection.immutable.List.apply($u.internal.reificationSupport.TypeRef($u.internal.reificationSupport.ThisType($m.staticPackage("scala").asModule.moduleClass), $u.internal.reificationSupport.selectType($m.staticPackage("scala").asModule.moduleClass, "AnyRef"), scala.collection.immutable.Nil)), $u.internal.reificationSupport.newScopeWith(free$u1), `symdef$<refinement>2`));
            $u.internal.reificationSupport.ExistentialType(scala.collection.immutable.List.apply(symdef$_67$type1), $u.internal.reificationSupport.TypeRef($u.internal.reificationSupport.SingleType($u.internal.reificationSupport.TypeRef($u.NoPrefix, symdef$_67$type1, scala.collection.immutable.Nil), free$u1), $u.internal.reificationSupport.selectType($m.staticClass("scala.reflect.api.Names"), "TermName"), scala.collection.immutable.Nil))
          }
        };
        new $typecreator1()
      })
    }));
    ()
  }
}

PS: bonus marks on this ticket for making CodePrinter available under -Xprint. It is important that we keep to old style printing avialable, however, so we can diff the output of this from Scala 2.10 and 2.11. So we'll need to be able to control this from the command line.

@scabug
Copy link
Author

scabug commented Mar 26, 2014

Imported From: https://issues.scala-lang.org/browse/SI-8447?orig=1
Reporter: @retronym
Assignee: @VladimirNik

@scabug
Copy link
Author

scabug commented Mar 26, 2014

@retronym said:
Also problematic is the fact that trees like Ident(symbolOf[reflect.api.TypeCreator]) are printed without qualification.

@scabug
Copy link
Author

scabug commented Apr 24, 2014

@paulp said:
This makes showCode super unuseful. I naively believed it was printing something similar to the tree it was being passed, which was missing almost all its types for some reason, which I see now is this. Channeling user-level information into ASTs means your inputs are Types and your trees are TypeTrees.

Is there some facility for translating a Type into the corresponding Tree?

@scabug
Copy link
Author

scabug commented Apr 24, 2014

@paulp said:
Actually maybe I'm not even complaining about the same thing. I'll add an example.

@scabug
Copy link
Author

scabug commented Apr 24, 2014

@paulp said:
Printing the tree we see "param: Int", via showCode it's just "param".

scala> def cdef[A: TypeTag](name: TypeName) = q"class $name(param: ${typeOf[A]})"
cdef: [A](name: reflect.runtime.universe.TypeName)(implicit evidence$1: reflect.runtime.universe.TypeTag[A])reflect.runtime.universe.ClassDef

scala> showCode(cdef[Int]("Bippy"))
res0: String = class Bippy(param)

scala> cdef[Int]("Bippy").toString
res1: String =
class Bippy extends scala.AnyRef {
  <paramaccessor> private[this] val param: Int = _;
  def <init>(param: Int) = {
    super.<init>();
    ()
  }
}

@scabug
Copy link
Author

scabug commented Apr 26, 2014

@xeno-by said:
Looks like indeed an issue in showCode. It seems like it's using originals to print TypeTrees. If there were a good way to go from a Type to a Tree, that would be workaroundable, but I'm not aware of such a facility.

@scabug
Copy link
Author

scabug commented Apr 26, 2014

@paulp said:
Yeah, I wrote it myself.

@scabug
Copy link
Author

scabug commented May 4, 2014

@VladimirNik said:
Fixes in scala/scala#3710 should improve TypeTrees printing.

@retronym, can I add print.code flag to this pull request?

@scabug
Copy link
Author

scabug commented May 5, 2014

@retronym said:
I would keep print.code for a separate PR / issue.

@scabug scabug closed this as completed Jul 3, 2014
@scabug scabug added this to the 2.11.2 milestone Apr 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant