From d7d63e93f35c692b26e95db1b02d758723dde18d Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sun, 10 Nov 2013 13:40:26 +0100 Subject: Tidy up the Uncurry component of delambdafy - Use tree factories that accept symbols and encapsulate ValDef creation - Use `gen.mkForwarder` to handle the conditional addition of `: _*` for varargs functions. We don't need to predicate this on `etaExpandKeepsStar`; the only place that need to do that is EtaExpansion. --- src/reflect/scala/reflect/internal/Trees.scala | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/reflect') diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index af0af8afe8..b0abc0be7b 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -1804,6 +1804,12 @@ trait Trees extends api.Trees { case t => sys.error("Not a LabelDef: " + t + "/" + t.getClass) } + def deriveFunction(func: Tree)(applyToRhs: Tree => Tree): Function = func match { + case Function(params0, rhs0) => + treeCopy.Function(func, params0, applyToRhs(rhs0)) + case t => + sys.error("Not a Function: " + t + "/" + t.getClass) + } // -------------- Classtags -------------------------------------------------------- -- cgit v1.2.3 From cb37548ef85d471951867b9f8a97cb9b9820fc66 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Nov 2013 09:41:07 +0100 Subject: Symbol substutition must consider ClassInfoType#parents An upcoming change to uncurry, in which I plan to make substitution of `lambda params -> apply method params` requires that I first to fix a problem in symbol substition. This situation can arise when the body of this definition: def owner1(a: A) = { class C extends M[a.B] } is transplanted into a new owner that has a different symbol for `a`. I speculated that value classes might also be prone to the fact that symbol substitution neglected `ClassInfoType#parents`. We can test change with Value Classes: Partial Functions that are dependent on value class param type used to fail with a spurious overriding error, now they work correctly. --- .../scala/reflect/internal/tpe/TypeMaps.scala | 6 ++++++ .../run/value-class-partial-func-depmet.scala | 24 ++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 test/files/run/value-class-partial-func-depmet.scala (limited to 'src/reflect') diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala index 9a54ad8217..f5aa048e6a 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala @@ -717,6 +717,12 @@ private[internal] trait TypeMaps { else appliedType(tcon.typeConstructor, args) case SingleType(NoPrefix, sym) => substFor(sym) + case ClassInfoType(parents, decls, sym) => + val parents1 = parents mapConserve this + // We don't touch decls here; they will be touched when an enclosing TreeSubstitutor + // transforms the tree that defines them. + if (parents1 eq parents) tp + else ClassInfoType(parents1, decls, sym) case _ => tp } diff --git a/test/files/run/value-class-partial-func-depmet.scala b/test/files/run/value-class-partial-func-depmet.scala new file mode 100644 index 0000000000..12ff64ed36 --- /dev/null +++ b/test/files/run/value-class-partial-func-depmet.scala @@ -0,0 +1,24 @@ +class C +class A { class C } + +object Test { + def main(args: Array[String]) { + val a = new A + + new VC("").foo(a) + } +} + +class VC(val a: Any) extends AnyVal { + def foo(a: A) = { + val pf: PartialFunction[a.C, Any] = { case x => x } + (pf: PartialFunction[Null, Any]).isDefinedAt(null) + } +} + +// 2.11.0-M6 +// test/files/run/value-class-partial-func-depmet.scala:14: error: overriding method applyOrElse in trait PartialFunction of type [A1 <: a.C, B1 >: Any](x: A1, default: A1 => B1)B1; +// method applyOrElse has incompatible type +// val pf: PartialFunction[a.C, Any] = { case x => x } +// ^ +// one error found -- cgit v1.2.3 From 5d5596bb07c0b5985fe9a6ba5433a3d463918b28 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 20 Nov 2013 10:26:32 +0100 Subject: Special treatment for local symbols in TypeTreeMemberType Avoids calling `thisType` on the owner if it is a term symbol, which doesn't make much sense. This method is used internally in tree factory methods that create, e.g, a `DefDef` based on the info of a `Symbol`. --- src/reflect/scala/reflect/internal/Trees.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/reflect') diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index b0abc0be7b..d191fbd38f 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -590,7 +590,7 @@ trait Trees extends api.Trees { def TypeTree(tp: Type): TypeTree = TypeTree() setType tp private def TypeTreeMemberType(sym: Symbol): TypeTree = { // Needed for pos/t4970*.scala. See SI-7853 - val resType = (sym.owner.thisType memberType sym).finalResultType + val resType = (if (sym.isLocal) sym.tpe else (sym.owner.thisType memberType sym)).finalResultType atPos(sym.pos.focus)(TypeTree(resType)) } -- cgit v1.2.3