From 97286d761a5eaf18cc7018aa162866232a87ed91 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Fri, 10 Jan 2014 20:28:19 +0100 Subject: moves analyzer.ImportType into scala.reflect.internal This cute little type is necessary for importers to work correctly. I wonder how we could overlook its existence for almost 2 years. --- src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala | 2 +- src/compiler/scala/tools/nsc/ast/TreeGen.scala | 2 +- src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 5 ++--- src/interactive/scala/tools/nsc/interactive/Global.scala | 6 +++--- src/reflect/scala/reflect/internal/Importers.scala | 2 ++ src/reflect/scala/reflect/internal/Types.scala | 4 ++++ src/reflect/scala/reflect/runtime/JavaUniverseForce.scala | 1 + 7 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala index c68b248240..eb7409836c 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala @@ -632,7 +632,7 @@ abstract class TreeBrowsers { Document.group("(" :/: symsToDocument(tparams) :/: "), ") :/: toDocument(result) :: ")")) - case global.analyzer.ImportType(expr) => + case ImportType(expr) => "ImportType(" + expr.toString + ")" diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 4ac6672727..a87a04472a 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -37,7 +37,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { NoSymbol newImport NoPosition setFlag SYNTHETIC - setInfo analyzer.ImportType(qual) + setInfo ImportType(qual) ) val importTree = ( Import(qual, selector) diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 53bc9a2772..598b12b00d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -1353,9 +1353,8 @@ trait Contexts { self: Analyzer => override def toString = tree.toString } - case class ImportType(expr: Tree) extends Type { - override def safeToString = "ImportType("+expr+")" - } + type ImportType = global.ImportType + val ImportType = global.ImportType } object ContextMode { diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala index b55a573029..0e897d6492 100644 --- a/src/interactive/scala/tools/nsc/interactive/Global.scala +++ b/src/interactive/scala/tools/nsc/interactive/Global.scala @@ -956,7 +956,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") singleType(qual.tpe, tree.symbol) case Import(expr, selectors) => tree.symbol.info match { - case analyzer.ImportType(expr) => expr match { + case ImportType(expr) => expr match { case s@Select(qual, name) if treeInfo.admitsTypeSelection(expr) => singleType(qual.tpe, s.symbol) case i : Ident => i.tpe case _ => tree.tpe @@ -1021,7 +1021,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") def addScopeMember(sym: Symbol, pre: Type, viaImport: Tree) = locals.add(sym, pre, implicitlyAdded = false) { (s, st) => // imported val and var are always marked as inaccessible, but they could be accessed through their getters. SI-7995 - if (s.hasGetter) + if (s.hasGetter) new ScopeMember(s, st, context.isAccessible(s.getter, pre, superAccess = false), viaImport) else new ScopeMember(s, st, context.isAccessible(s, pre, superAccess = false), viaImport) @@ -1111,7 +1111,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") val pre = stabilizedType(tree) val ownerTpe = tree.tpe match { - case analyzer.ImportType(expr) => expr.tpe + case ImportType(expr) => expr.tpe case null => pre case MethodType(List(), rtpe) => rtpe case _ => tree.tpe diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala index 91ba552012..26d55e21c4 100644 --- a/src/reflect/scala/reflect/internal/Importers.scala +++ b/src/reflect/scala/reflect/internal/Importers.scala @@ -260,6 +260,8 @@ trait Importers extends api.Importers { to: SymbolTable => newExistentialType(tparams map importSymbol, importType(result)) case from.OverloadedType(pre, alts) => OverloadedType(importType(pre), alts map importSymbol) + case from.ImportType(qual) => + ImportType(importTree(qual)) case from.AntiPolyType(pre, targs) => AntiPolyType(importType(pre), targs map importType) case their: from.TypeVar => diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 99e6ae633f..45daa2ae04 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -2747,6 +2747,10 @@ trait Types case _ => OverloadedType(pre, alternatives) } + case class ImportType(expr: Tree) extends Type { + override def safeToString = "ImportType("+expr+")" + } + /** A class remembering a type instantiation for some a set of overloaded * polymorphic symbols. * Not used after phase `typer`. diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index c87995275f..9dfa5bcf2e 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -169,6 +169,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => this.PolyType this.ExistentialType this.OverloadedType + this.ImportType this.AntiPolyType this.HasTypeMember this.ArrayTypeRef -- cgit v1.2.3 From 752f1eb63e931e04fd2818f32b6ca7e68e4298d2 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Fri, 10 Jan 2014 01:36:06 +0100 Subject: deprecates resetAllAttrs and resetLocalAttrs in favor of the new API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now have c.untypecheck, which is supposed to be a counterpart of c.typecheck in the sense that it goes back from typed trees to untyped ones: http://stackoverflow.com/questions/20936509/scala-macros-what-is-the-difference-between-typed-aka-typechecked-an-untyped. Let’s hope that c.untypecheck will soon be able to solve our problems with partially/incorrectly attributed trees emitted by macros: https://groups.google.com/forum/#!topic/scala-internals/TtCTPlj_qcQ. --- .../scala/reflect/macros/contexts/Typers.scala | 2 ++ src/compiler/scala/tools/reflect/ToolBox.scala | 15 ++++++++----- .../scala/tools/reflect/ToolBoxFactory.scala | 2 ++ src/reflect/scala/reflect/macros/Typers.scala | 26 +++++++++++++++++----- test/files/run/idempotency-case-classes.scala | 2 +- test/files/run/idempotency-extractors.scala | 2 +- test/files/run/idempotency-labels.scala | 2 +- test/files/run/idempotency-lazy-vals.scala | 2 +- test/files/run/idempotency-this.scala | 2 +- test/files/run/resetattrs-this.scala | 2 +- test/files/run/t6187.check | 2 +- test/files/run/t6187.scala | 2 +- 12 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/compiler/scala/reflect/macros/contexts/Typers.scala b/src/compiler/scala/reflect/macros/contexts/Typers.scala index 85204d0f1b..cd3db74016 100644 --- a/src/compiler/scala/reflect/macros/contexts/Typers.scala +++ b/src/compiler/scala/reflect/macros/contexts/Typers.scala @@ -49,4 +49,6 @@ trait Typers { def resetAllAttrs(tree: Tree): Tree = universe.resetAllAttrs(universe.duplicateAndKeepPositions(tree)) def resetLocalAttrs(tree: Tree): Tree = universe.resetLocalAttrs(universe.duplicateAndKeepPositions(tree)) + + def untypecheck(tree: Tree): Tree = universe.resetLocalAttrs(universe.duplicateAndKeepPositions(tree)) } diff --git a/src/compiler/scala/tools/reflect/ToolBox.scala b/src/compiler/scala/tools/reflect/ToolBox.scala index 236b868842..4c1bc794bc 100644 --- a/src/compiler/scala/tools/reflect/ToolBox.scala +++ b/src/compiler/scala/tools/reflect/ToolBox.scala @@ -72,19 +72,22 @@ trait ToolBox[U <: scala.reflect.api.Universe] { def inferImplicitView(tree: u.Tree, from: u.Type, to: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: u.Position = u.NoPosition): u.Tree /** Recursively resets symbols and types in a given tree. - * - * Note that this does not revert the tree to its pre-typer shape. - * For more info, read up https://issues.scala-lang.org/browse/SI-5464. + * WARNING: Don't use this API, go for [[untypecheck]] instead. */ + @deprecated("Use `tb.untypecheck` instead", "2.11.0") def resetAllAttrs(tree: u.Tree): u.Tree /** Recursively resets locally defined symbols and types in a given tree. - * - * Note that this does not revert the tree to its pre-typer shape. - * For more info, read up https://issues.scala-lang.org/browse/SI-5464. + * WARNING: Don't use this API, go for [[untypecheck]] instead. */ + @deprecated("Use `tb.untypecheck` instead", "2.11.0") def resetLocalAttrs(tree: u.Tree): u.Tree + /** + * @see [[scala.reflect.macros.Typers.untypecheck]] + */ + def untypecheck(tree: u.Tree): u.Tree + /** .. */ def parse(code: String): u.Tree diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index af13b7d0ba..4a8c91bd1b 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -401,6 +401,8 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => uttree } + def untypecheck(tree: u.Tree): u.Tree = resetLocalAttrs(tree) + def parse(code: String): u.Tree = withCompilerApi { compilerApi => import compilerApi._ if (compiler.settings.verbose) println("parsing "+code) diff --git a/src/reflect/scala/reflect/macros/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala index 5a25801335..f215e8769d 100644 --- a/src/reflect/scala/reflect/macros/Typers.scala +++ b/src/reflect/scala/reflect/macros/Typers.scala @@ -69,18 +69,32 @@ trait Typers { def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree /** Recursively resets symbols and types in a given tree. - * - * Note that this does not revert the tree to its pre-typer shape. - * For more info, read up https://issues.scala-lang.org/browse/SI-5464. + * WARNING: Don't use this API, go for [[untypecheck]] instead. */ + @deprecated("Use `c.untypecheck` instead", "2.11.0") def resetAllAttrs(tree: Tree): Tree /** Recursively resets locally defined symbols and types in a given tree. - * - * Note that this does not revert the tree to its pre-typer shape. - * For more info, read up https://issues.scala-lang.org/browse/SI-5464. + * WARNING: Don't use this API, go for [[untypecheck]] instead. */ + @deprecated("Use `c.untypecheck` instead", "2.11.0") def resetLocalAttrs(tree: Tree): Tree + + /** In the current implementation of Scala's reflection API, untyped trees (also known as parser trees or unattributed trees) + * are observationally different from typed trees (also known as typer trees, typechecked trees or attributed trees), + * + * Usually, if some compiler API takes a tree, then both untyped and typed trees will do. However in some cases, + * only untyped or only typed trees are appropriate. For example, [[eval]] only accepts untyped trees and one can only splice + * typed trees inside typed trees. Therefore in the current reflection API, there is a need in functions + * that go back and forth between untyped and typed trees. For this we have [[typecheck]] and `untypecheck`. + * + * Note that `untypecheck` is currently afflicted by https://issues.scala-lang.org/browse/SI-5464, + * which makes it sometimes corrupt trees so that they don't make sense anymore. Unfortunately, there's no workaround for that. + * We plan to fix this issue soon, but for now please keep it in mind. + * + * @see [[http://stackoverflow.com/questions/20936509/scala-macros-what-is-the-difference-between-typed-aka-typechecked-an-untyped]] + */ + def untypecheck(tree: Tree): Tree } /** Indicates an error during one of the methods in [[scala.reflect.macros.Typers]]. diff --git a/test/files/run/idempotency-case-classes.scala b/test/files/run/idempotency-case-classes.scala index 81e119582b..4ad132174d 100644 --- a/test/files/run/idempotency-case-classes.scala +++ b/test/files/run/idempotency-case-classes.scala @@ -12,7 +12,7 @@ object Test extends App { val tb = cm.mkToolBox() val tcasee = tb.typecheck(casee.tree) println(tcasee) - val rtcasee = tb.resetAllAttrs(tcasee) + val rtcasee = tb.untypecheck(tcasee) try { println(tb.eval(rtcasee)) } catch { diff --git a/test/files/run/idempotency-extractors.scala b/test/files/run/idempotency-extractors.scala index b66b043be1..8c0a0b1106 100644 --- a/test/files/run/idempotency-extractors.scala +++ b/test/files/run/idempotency-extractors.scala @@ -12,7 +12,7 @@ object Test extends App { val tb = cm.mkToolBox() val textractor = tb.typecheck(extractor.tree) println(textractor) - val rtextractor = tb.resetAllAttrs(textractor) + val rtextractor = tb.untypecheck(textractor) try { println(tb.eval(rtextractor)) } catch { diff --git a/test/files/run/idempotency-labels.scala b/test/files/run/idempotency-labels.scala index f1a185d3d0..084c93d3c6 100644 --- a/test/files/run/idempotency-labels.scala +++ b/test/files/run/idempotency-labels.scala @@ -13,7 +13,7 @@ object Test extends App { val tb = cm.mkToolBox() val tlabel = tb.typecheck(label.tree) println(tlabel) - val rtlabel = tb.resetAllAttrs(tlabel) + val rtlabel = tb.untypecheck(tlabel) try { println(tb.eval(rtlabel)) } catch { diff --git a/test/files/run/idempotency-lazy-vals.scala b/test/files/run/idempotency-lazy-vals.scala index e763f2f3f4..9d677caeca 100644 --- a/test/files/run/idempotency-lazy-vals.scala +++ b/test/files/run/idempotency-lazy-vals.scala @@ -17,7 +17,7 @@ object Test extends App { val tb = cm.mkToolBox() val tlazee = tb.typecheck(lazee.tree) println(tlazee) - val rtlazee = tb.resetAllAttrs(tlazee) + val rtlazee = tb.untypecheck(tlazee) try { println(tb.eval(rtlazee)) } catch { diff --git a/test/files/run/idempotency-this.scala b/test/files/run/idempotency-this.scala index 2db1efd2d1..26917ab743 100644 --- a/test/files/run/idempotency-this.scala +++ b/test/files/run/idempotency-this.scala @@ -12,7 +12,7 @@ object Test extends App { val tthiss = tb.typecheck(thiss.tree) println(tthiss) println(showRaw(tthiss)) - val rtthiss = tb.resetAllAttrs(tthiss) + val rtthiss = tb.untypecheck(tthiss) try { println(tb.eval(rtthiss)) } catch { diff --git a/test/files/run/resetattrs-this.scala b/test/files/run/resetattrs-this.scala index 6150a4e265..ff45d61dfe 100644 --- a/test/files/run/resetattrs-this.scala +++ b/test/files/run/resetattrs-this.scala @@ -6,6 +6,6 @@ object Test extends App { val tb = cm.mkToolBox() val tree = Select(This(cm.staticPackage("scala").moduleClass), TermName("Predef")) val ttree = tb.typecheck(tree) - val rttree = tb.resetAllAttrs(ttree) + val rttree = tb.untypecheck(ttree) println(tb.eval(rttree) == Predef) } diff --git a/test/files/run/t6187.check b/test/files/run/t6187.check index c833b45443..c7447b62a0 100644 --- a/test/files/run/t6187.check +++ b/test/files/run/t6187.check @@ -7,7 +7,7 @@ import reflect.macros.BlackboxContext scala> def macroImpl[T: c.WeakTypeTag](c: BlackboxContext)(t: c.Expr[T]): c.Expr[List[T]] = { val r = c.universe.reify { List(t.splice) } - c.Expr[List[T]]( c.resetLocalAttrs(r.tree) ) + c.Expr[List[T]]( c.untypecheck(r.tree) ) } macroImpl: [T](c: scala.reflect.macros.BlackboxContext)(t: c.Expr[T])(implicit evidence$1: c.WeakTypeTag[T])c.Expr[List[T]] diff --git a/test/files/run/t6187.scala b/test/files/run/t6187.scala index fc6fa6e9a7..18f8f7ea2b 100644 --- a/test/files/run/t6187.scala +++ b/test/files/run/t6187.scala @@ -5,7 +5,7 @@ object Test extends ReplTest { import language.experimental.macros, reflect.macros.BlackboxContext def macroImpl[T: c.WeakTypeTag](c: BlackboxContext)(t: c.Expr[T]): c.Expr[List[T]] = { val r = c.universe.reify { List(t.splice) } - c.Expr[List[T]]( c.resetLocalAttrs(r.tree) ) + c.Expr[List[T]]( c.untypecheck(r.tree) ) } def demo[T](t: T): List[T] = macro macroImpl[T] def m[T](t: T): List[List[T]] = -- cgit v1.2.3