summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2014-02-19 20:37:46 +0100
committerEugene Burmako <xeno.by@gmail.com>2014-02-20 16:22:12 +0100
commit09fe97aec626b875f68e057828c44a9b6f4344dc (patch)
tree2098554fc29f0cf80f35d3fbd685d8bcb03e2358
parent3973f29cec9f06724941b68577908f546341c45e (diff)
downloadscala-09fe97aec626b875f68e057828c44a9b6f4344dc.tar.gz
scala-09fe97aec626b875f68e057828c44a9b6f4344dc.tar.bz2
scala-09fe97aec626b875f68e057828c44a9b6f4344dc.zip
SI-8316 SI-8318 SI-8248 reintroduces resetAllAttrs
Unfortunately, due to the aforementioned bugs we have to delay our triumph over resetAllAttrs. Therefore, I'm rolling back the internal changes to scalac introduced in https://github.com/scala/scala/pull/3485. Our public reflection API interface in Scala 2.11 is still going to contain only resetLocalAttrs, but both the reifier and the label typechecker are too heavily addicted to resetAllAttrs to do away with it right now.
-rw-r--r--src/compiler/scala/reflect/reify/Reifier.scala10
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala16
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rw-r--r--test/files/run/macro-reify-chained1/Impls_Macros_1.scala (renamed from test/files/run/macro-reify-nested-b/Impls_Macros_1.scala)3
-rw-r--r--test/files/run/macro-reify-chained1/Test_2.scala9
-rw-r--r--test/files/run/macro-reify-chained2/Impls_Macros_1.scala47
-rw-r--r--test/files/run/macro-reify-chained2/Test_2.scala9
-rw-r--r--test/files/run/macro-reify-nested-a.flags1
-rw-r--r--test/files/run/macro-reify-nested-a1/Impls_Macros_1.scala (renamed from test/files/run/macro-reify-nested-a/Impls_Macros_1.scala)3
-rw-r--r--test/files/run/macro-reify-nested-a1/Test_2.scala (renamed from test/files/run/macro-reify-nested-a/Test_2.scala)5
-rw-r--r--test/files/run/macro-reify-nested-a2/Impls_Macros_1.scala47
-rw-r--r--test/files/run/macro-reify-nested-a2/Test_2.scala9
-rw-r--r--test/files/run/macro-reify-nested-b.flags1
-rw-r--r--test/files/run/macro-reify-nested-b1/Impls_Macros_1.scala47
-rw-r--r--test/files/run/macro-reify-nested-b1/Test_2.scala (renamed from test/files/run/macro-reify-nested-b/Test_2.scala)5
-rw-r--r--test/files/run/macro-reify-nested-b2/Impls_Macros_1.scala47
-rw-r--r--test/files/run/macro-reify-nested-b2/Test_2.scala9
17 files changed, 261 insertions, 9 deletions
diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala
index 6b0a0ee8d7..b1cc797389 100644
--- a/src/compiler/scala/reflect/reify/Reifier.scala
+++ b/src/compiler/scala/reflect/reify/Reifier.scala
@@ -110,10 +110,18 @@ abstract class Reifier extends States
// todo. this is a common problem with non-trivial macros in our current macro system
// needs to be solved some day
// upd. a new hope: https://groups.google.com/forum/#!topic/scala-internals/TtCTPlj_qcQ
- val untyped = resetAttrs(result, leaveAlone = {
+ var importantSymbols = Set[Symbol](
+ NothingClass, AnyClass, SingletonClass, PredefModule, ScalaRunTimeModule, TypeCreatorClass, TreeCreatorClass, MirrorClass,
+ ApiUniverseClass, JavaUniverseClass, ReflectRuntimePackage, runDefinitions.ReflectRuntimeCurrentMirror)
+ importantSymbols ++= importantSymbols map (_.companionSymbol)
+ importantSymbols ++= importantSymbols map (_.moduleClass)
+ importantSymbols ++= importantSymbols map (_.linkedClassOfClass)
+ def isImportantSymbol(sym: Symbol): Boolean = sym != null && sym != NoSymbol && importantSymbols(sym)
+ val untyped = brutallyResetAttrs(result, leaveAlone = {
case ValDef(_, u, _, _) if u == nme.UNIVERSE_SHORT => true
case ValDef(_, m, _, _) if m == nme.MIRROR_SHORT => true
case tree if symtab.syms contains tree.symbol => true
+ case tree if isImportantSymbol(tree.symbol) => true
case _ => false
})
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index d33ea5bb5c..9ca06427e8 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -194,8 +194,18 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
//
// def resetAllAttrs(x: Tree, leaveAlone: Tree => Boolean = null): Tree = new ResetAttrs(localOnly = false, leaveAlone).transform(x)
+ // upd. Unfortunately this didn't work out quite as we expected. The last two users of resetAllAttrs:
+ // reification and typedLabelDef broke in very weird ways when we replaced resetAllAttrs with resetLocalAttrs
+ // (see SI-8316 change from resetAllAttrs to resetLocalAttrs in reifiers broke Slick and
+ // SI-8318 NPE in mixin in scala-continuations for more information).
+ // Given that we're supposed to release 2.11.0-RC1 in less than a week, I'm temporarily reinstating resetAllAttrs
+ // until we have time to better understand what's going on. In order to dissuade people from using it,
+ // it now comes with a new, ridiculous name.
/** @see ResetAttrs */
- def resetAttrs(x: Tree, leaveAlone: Tree => Boolean = null): Tree = new ResetAttrs(leaveAlone).transform(x)
+ def brutallyResetAttrs(x: Tree, leaveAlone: Tree => Boolean = null): Tree = new ResetAttrs(brutally = true, leaveAlone).transform(x)
+
+ /** @see ResetAttrs */
+ def resetAttrs(x: Tree): Tree = new ResetAttrs(brutally = false, leaveAlone = null).transform(x)
/** A transformer which resets symbol and tpe fields of all nodes in a given tree,
* with special treatment of:
@@ -206,7 +216,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
*
* (bq:) This transformer has mutable state and should be discarded after use
*/
- private class ResetAttrs(leaveAlone: Tree => Boolean = null) {
+ private class ResetAttrs(brutally: Boolean, leaveAlone: Tree => Boolean) {
// this used to be based on -Ydebug, but the need for logging in this code is so situational
// that I've reverted to a hard-coded constant here.
val debug = false
@@ -299,7 +309,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
// if we move these trees into lexical contexts different from their original locations.
if (dupl.hasSymbol) {
val sym = dupl.symbol
- val vetoScope = !(locals contains sym)
+ val vetoScope = !brutally && !(locals contains sym)
val vetoThis = dupl.isInstanceOf[This] && sym.isPackageClass
if (!(vetoScope || vetoThis)) dupl.symbol = NoSymbol
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 8721450dc9..fa96d98bcc 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2288,7 +2288,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val sym2 = namer.enterInScope(
context.owner.newLabel(ldef.name, ldef.pos) setInfo MethodType(List(), restpe))
val LabelDef(_, _, rhs1) = resetAttrs(ldef)
- val rhs2 = typed(rhs1, restpe)
+ val rhs2 = typed(brutallyResetAttrs(rhs1), restpe)
ldef.params foreach (param => param setType param.symbol.tpe)
deriveLabelDef(ldef)(_ => rhs2) setSymbol sym2 setType restpe
}
diff --git a/test/files/run/macro-reify-nested-b/Impls_Macros_1.scala b/test/files/run/macro-reify-chained1/Impls_Macros_1.scala
index 3bea04cead..7f877b2729 100644
--- a/test/files/run/macro-reify-nested-b/Impls_Macros_1.scala
+++ b/test/files/run/macro-reify-chained1/Impls_Macros_1.scala
@@ -1,6 +1,7 @@
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{universe => ru}
import scala.reflect.macros.blackbox.Context
+import scala.language.experimental.macros
case class Utils[C <: Context]( c:C ) {
import c.universe._
@@ -34,7 +35,7 @@ object QueryableMacros{
c.universe.reify{ Queryable.factory[S]( foo.splice )}
}
def map[T:c.WeakTypeTag, S:c.WeakTypeTag]
- (c: scala.reflect.macros.blackbox.Context)
+ (c: Context)
(projection: c.Expr[T => S]): c.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection )
}
class Queryable[T]{
diff --git a/test/files/run/macro-reify-chained1/Test_2.scala b/test/files/run/macro-reify-chained1/Test_2.scala
new file mode 100644
index 0000000000..2adb07b035
--- /dev/null
+++ b/test/files/run/macro-reify-chained1/Test_2.scala
@@ -0,0 +1,9 @@
+object Test extends App{
+ val q : Queryable[Any] = new Queryable[Any]
+ q.map(x => x).map(x => x)
+
+ locally {
+ val q : Queryable[Any] = new Queryable[Any]
+ q.map(x => x).map(x => x)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-chained2/Impls_Macros_1.scala b/test/files/run/macro-reify-chained2/Impls_Macros_1.scala
new file mode 100644
index 0000000000..965b191044
--- /dev/null
+++ b/test/files/run/macro-reify-chained2/Impls_Macros_1.scala
@@ -0,0 +1,47 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{universe => ru}
+import scala.reflect.macros.whitebox.Context
+import scala.language.experimental.macros
+
+case class Utils[C <: Context]( c:C ) {
+ import c.universe._
+ import c.{Tree=>_}
+ object removeDoubleReify extends c.universe.Transformer {
+ def apply( tree:Tree ) = transform(tree)
+ override def transform(tree: Tree): Tree = {
+ super.transform {
+ tree match {
+ case Apply(TypeApply(Select(_this, termname), _), reification::Nil )
+ if termname.toString == "factory" => c.unreifyTree(reification)
+ case Apply(Select(_this, termname), reification::Nil )
+ if termname.toString == "factory" => c.unreifyTree(reification)
+ case _ => tree
+ }
+ }
+ }
+ }
+}
+object QueryableMacros{
+ def _helper[C <: Context,S:c.WeakTypeTag]( c:C )( name:String, projection:c.Expr[_] ) = {
+ import c.universe._
+ import internal._
+ val element_type = implicitly[c.WeakTypeTag[S]].tpe
+ val foo = c.Expr[ru.Expr[Queryable[S]]](
+ c.reifyTree( gen.mkRuntimeUniverseRef, EmptyTree, c.typecheck(
+ Utils[c.type](c).removeDoubleReify(
+ Apply(Select(c.prefix.tree, TermName( name )), List( projection.tree ))
+ ).asInstanceOf[Tree]
+ )))
+ c.universe.reify{ Queryable.factory[S]( foo.splice )}
+ }
+ def map[T:c.WeakTypeTag, S:c.WeakTypeTag]
+ (c: Context)
+ (projection: c.Expr[T => S]): c.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection )
+}
+class Queryable[T]{
+ def _map[S]( projection: T => S ) : Queryable[S] = ???
+ def map[S]( projection: T => S ) : Queryable[S] = macro QueryableMacros.map[T,S]
+}
+object Queryable{
+ def factory[S]( projection:ru.Expr[Queryable[S]] ) : Queryable[S] = null
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-chained2/Test_2.scala b/test/files/run/macro-reify-chained2/Test_2.scala
new file mode 100644
index 0000000000..2adb07b035
--- /dev/null
+++ b/test/files/run/macro-reify-chained2/Test_2.scala
@@ -0,0 +1,9 @@
+object Test extends App{
+ val q : Queryable[Any] = new Queryable[Any]
+ q.map(x => x).map(x => x)
+
+ locally {
+ val q : Queryable[Any] = new Queryable[Any]
+ q.map(x => x).map(x => x)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-a.flags b/test/files/run/macro-reify-nested-a.flags
deleted file mode 100644
index cd66464f2f..0000000000
--- a/test/files/run/macro-reify-nested-a.flags
+++ /dev/null
@@ -1 +0,0 @@
--language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-a/Impls_Macros_1.scala b/test/files/run/macro-reify-nested-a1/Impls_Macros_1.scala
index 3bea04cead..7f877b2729 100644
--- a/test/files/run/macro-reify-nested-a/Impls_Macros_1.scala
+++ b/test/files/run/macro-reify-nested-a1/Impls_Macros_1.scala
@@ -1,6 +1,7 @@
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{universe => ru}
import scala.reflect.macros.blackbox.Context
+import scala.language.experimental.macros
case class Utils[C <: Context]( c:C ) {
import c.universe._
@@ -34,7 +35,7 @@ object QueryableMacros{
c.universe.reify{ Queryable.factory[S]( foo.splice )}
}
def map[T:c.WeakTypeTag, S:c.WeakTypeTag]
- (c: scala.reflect.macros.blackbox.Context)
+ (c: Context)
(projection: c.Expr[T => S]): c.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection )
}
class Queryable[T]{
diff --git a/test/files/run/macro-reify-nested-a/Test_2.scala b/test/files/run/macro-reify-nested-a1/Test_2.scala
index fa0eb378af..b99c4c55e4 100644
--- a/test/files/run/macro-reify-nested-a/Test_2.scala
+++ b/test/files/run/macro-reify-nested-a1/Test_2.scala
@@ -1,4 +1,9 @@
object Test extends App{
val q : Queryable[Any] = new Queryable[Any]
q.map(e1 => q.map(e2=>e1))
+
+ locally {
+ val q : Queryable[Any] = new Queryable[Any]
+ q.map(e1 => q.map(e2=>e1))
+ }
} \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-a2/Impls_Macros_1.scala b/test/files/run/macro-reify-nested-a2/Impls_Macros_1.scala
new file mode 100644
index 0000000000..965b191044
--- /dev/null
+++ b/test/files/run/macro-reify-nested-a2/Impls_Macros_1.scala
@@ -0,0 +1,47 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{universe => ru}
+import scala.reflect.macros.whitebox.Context
+import scala.language.experimental.macros
+
+case class Utils[C <: Context]( c:C ) {
+ import c.universe._
+ import c.{Tree=>_}
+ object removeDoubleReify extends c.universe.Transformer {
+ def apply( tree:Tree ) = transform(tree)
+ override def transform(tree: Tree): Tree = {
+ super.transform {
+ tree match {
+ case Apply(TypeApply(Select(_this, termname), _), reification::Nil )
+ if termname.toString == "factory" => c.unreifyTree(reification)
+ case Apply(Select(_this, termname), reification::Nil )
+ if termname.toString == "factory" => c.unreifyTree(reification)
+ case _ => tree
+ }
+ }
+ }
+ }
+}
+object QueryableMacros{
+ def _helper[C <: Context,S:c.WeakTypeTag]( c:C )( name:String, projection:c.Expr[_] ) = {
+ import c.universe._
+ import internal._
+ val element_type = implicitly[c.WeakTypeTag[S]].tpe
+ val foo = c.Expr[ru.Expr[Queryable[S]]](
+ c.reifyTree( gen.mkRuntimeUniverseRef, EmptyTree, c.typecheck(
+ Utils[c.type](c).removeDoubleReify(
+ Apply(Select(c.prefix.tree, TermName( name )), List( projection.tree ))
+ ).asInstanceOf[Tree]
+ )))
+ c.universe.reify{ Queryable.factory[S]( foo.splice )}
+ }
+ def map[T:c.WeakTypeTag, S:c.WeakTypeTag]
+ (c: Context)
+ (projection: c.Expr[T => S]): c.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection )
+}
+class Queryable[T]{
+ def _map[S]( projection: T => S ) : Queryable[S] = ???
+ def map[S]( projection: T => S ) : Queryable[S] = macro QueryableMacros.map[T,S]
+}
+object Queryable{
+ def factory[S]( projection:ru.Expr[Queryable[S]] ) : Queryable[S] = null
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-a2/Test_2.scala b/test/files/run/macro-reify-nested-a2/Test_2.scala
new file mode 100644
index 0000000000..b99c4c55e4
--- /dev/null
+++ b/test/files/run/macro-reify-nested-a2/Test_2.scala
@@ -0,0 +1,9 @@
+object Test extends App{
+ val q : Queryable[Any] = new Queryable[Any]
+ q.map(e1 => q.map(e2=>e1))
+
+ locally {
+ val q : Queryable[Any] = new Queryable[Any]
+ q.map(e1 => q.map(e2=>e1))
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-b.flags b/test/files/run/macro-reify-nested-b.flags
deleted file mode 100644
index cd66464f2f..0000000000
--- a/test/files/run/macro-reify-nested-b.flags
+++ /dev/null
@@ -1 +0,0 @@
--language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-b1/Impls_Macros_1.scala b/test/files/run/macro-reify-nested-b1/Impls_Macros_1.scala
new file mode 100644
index 0000000000..7f877b2729
--- /dev/null
+++ b/test/files/run/macro-reify-nested-b1/Impls_Macros_1.scala
@@ -0,0 +1,47 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{universe => ru}
+import scala.reflect.macros.blackbox.Context
+import scala.language.experimental.macros
+
+case class Utils[C <: Context]( c:C ) {
+ import c.universe._
+ import c.{Tree=>_}
+ object removeDoubleReify extends c.universe.Transformer {
+ def apply( tree:Tree ) = transform(tree)
+ override def transform(tree: Tree): Tree = {
+ super.transform {
+ tree match {
+ case Apply(TypeApply(Select(_this, termname), _), reification::Nil )
+ if termname.toString == "factory" => c.unreifyTree(reification)
+ case Apply(Select(_this, termname), reification::Nil )
+ if termname.toString == "factory" => c.unreifyTree(reification)
+ case _ => tree
+ }
+ }
+ }
+ }
+}
+object QueryableMacros{
+ def _helper[C <: Context,S:c.WeakTypeTag]( c:C )( name:String, projection:c.Expr[_] ) = {
+ import c.universe._
+ import internal._
+ val element_type = implicitly[c.WeakTypeTag[S]].tpe
+ val foo = c.Expr[ru.Expr[Queryable[S]]](
+ c.reifyTree( gen.mkRuntimeUniverseRef, EmptyTree, c.typecheck(
+ Utils[c.type](c).removeDoubleReify(
+ Apply(Select(c.prefix.tree, TermName( name )), List( projection.tree ))
+ ).asInstanceOf[Tree]
+ )))
+ c.universe.reify{ Queryable.factory[S]( foo.splice )}
+ }
+ def map[T:c.WeakTypeTag, S:c.WeakTypeTag]
+ (c: Context)
+ (projection: c.Expr[T => S]): c.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection )
+}
+class Queryable[T]{
+ def _map[S]( projection: T => S ) : Queryable[S] = ???
+ def map[S]( projection: T => S ) : Queryable[S] = macro QueryableMacros.map[T,S]
+}
+object Queryable{
+ def factory[S]( projection:ru.Expr[Queryable[S]] ) : Queryable[S] = null
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-b/Test_2.scala b/test/files/run/macro-reify-nested-b1/Test_2.scala
index fa13f57ffb..b199036349 100644
--- a/test/files/run/macro-reify-nested-b/Test_2.scala
+++ b/test/files/run/macro-reify-nested-b1/Test_2.scala
@@ -1,4 +1,9 @@
object Test extends App{
val q : Queryable[Any] = new Queryable[Any]
q.map(e1 => q.map(e2=>e1).map(e2=>e1))
+
+ locally {
+ val q : Queryable[Any] = new Queryable[Any]
+ q.map(e1 => q.map(e2=>e1).map(e2=>e1))
+ }
} \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-b2/Impls_Macros_1.scala b/test/files/run/macro-reify-nested-b2/Impls_Macros_1.scala
new file mode 100644
index 0000000000..965b191044
--- /dev/null
+++ b/test/files/run/macro-reify-nested-b2/Impls_Macros_1.scala
@@ -0,0 +1,47 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{universe => ru}
+import scala.reflect.macros.whitebox.Context
+import scala.language.experimental.macros
+
+case class Utils[C <: Context]( c:C ) {
+ import c.universe._
+ import c.{Tree=>_}
+ object removeDoubleReify extends c.universe.Transformer {
+ def apply( tree:Tree ) = transform(tree)
+ override def transform(tree: Tree): Tree = {
+ super.transform {
+ tree match {
+ case Apply(TypeApply(Select(_this, termname), _), reification::Nil )
+ if termname.toString == "factory" => c.unreifyTree(reification)
+ case Apply(Select(_this, termname), reification::Nil )
+ if termname.toString == "factory" => c.unreifyTree(reification)
+ case _ => tree
+ }
+ }
+ }
+ }
+}
+object QueryableMacros{
+ def _helper[C <: Context,S:c.WeakTypeTag]( c:C )( name:String, projection:c.Expr[_] ) = {
+ import c.universe._
+ import internal._
+ val element_type = implicitly[c.WeakTypeTag[S]].tpe
+ val foo = c.Expr[ru.Expr[Queryable[S]]](
+ c.reifyTree( gen.mkRuntimeUniverseRef, EmptyTree, c.typecheck(
+ Utils[c.type](c).removeDoubleReify(
+ Apply(Select(c.prefix.tree, TermName( name )), List( projection.tree ))
+ ).asInstanceOf[Tree]
+ )))
+ c.universe.reify{ Queryable.factory[S]( foo.splice )}
+ }
+ def map[T:c.WeakTypeTag, S:c.WeakTypeTag]
+ (c: Context)
+ (projection: c.Expr[T => S]): c.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection )
+}
+class Queryable[T]{
+ def _map[S]( projection: T => S ) : Queryable[S] = ???
+ def map[S]( projection: T => S ) : Queryable[S] = macro QueryableMacros.map[T,S]
+}
+object Queryable{
+ def factory[S]( projection:ru.Expr[Queryable[S]] ) : Queryable[S] = null
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-b2/Test_2.scala b/test/files/run/macro-reify-nested-b2/Test_2.scala
new file mode 100644
index 0000000000..b199036349
--- /dev/null
+++ b/test/files/run/macro-reify-nested-b2/Test_2.scala
@@ -0,0 +1,9 @@
+object Test extends App{
+ val q : Queryable[Any] = new Queryable[Any]
+ q.map(e1 => q.map(e2=>e1).map(e2=>e1))
+
+ locally {
+ val q : Queryable[Any] = new Queryable[Any]
+ q.map(e1 => q.map(e2=>e1).map(e2=>e1))
+ }
+} \ No newline at end of file