summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-01-28 14:10:48 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-02-02 02:17:35 +0100
commit3af838c55674c0d03e8849d8c756d6ad56c537db (patch)
tree33fe0405a7b52bfd5d08cd809ff6b403d94e3c40
parent02963d724c512251ce66502226408091686989ee (diff)
downloadscala-3af838c55674c0d03e8849d8c756d6ad56c537db.tar.gz
scala-3af838c55674c0d03e8849d8c756d6ad56c537db.tar.bz2
scala-3af838c55674c0d03e8849d8c756d6ad56c537db.zip
SI-7033 Be symful when creating factory methods.
Implicit class factory methods were synthesizing the reference to the class as `Ident(classDef.name)`, which was unhygienic in case of `implicit class X[X]`. To use symbols without causing a cycle, I switched from `REF(symbol)` to `Ident(symbol)`. The former calls into: at scala.reflect.internal.TreeGen.mkAttributedSelect(TreeGen.scala:184) at scala.reflect.internal.TreeGen.mkAttributedRef(TreeGen.scala:124) at scala.reflect.internal.TreeGen.mkAttributedRef(TreeGen.scala:130) at scala.tools.nsc.ast.TreeDSL$CODE$.REF(TreeDSL.scala:307) which forces the info of enclosing module and forms a cycle.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala11
-rw-r--r--test/files/pos/t7033.scala15
3 files changed, 22 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index acc4f7ff67..b1cf93a879 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -389,7 +389,7 @@ trait MethodSynthesis {
result
}
def derivedTree: DefDef =
- factoryMeth(mods & flagsMask | flagsExtra, name, tree, symbolic = false)
+ factoryMeth(mods & flagsMask | flagsExtra, name, tree)
def flagsExtra: Long = METHOD | IMPLICIT | SYNTHETIC
def flagsMask: Long = AccessFlags
def name: TermName = tree.name.toTermName
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index 5782d7bbca..3e4e0f49d7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -79,8 +79,9 @@ trait Unapplies extends ast.TreeDSL
private def toIdent(x: DefTree) = Ident(x.name) setPos x.pos.focus
- private def classType(cdef: ClassDef, tparams: List[TypeDef], symbolic: Boolean = true): Tree = {
- val tycon = if (symbolic) REF(cdef.symbol) else Ident(cdef.name)
+ private def classType(cdef: ClassDef, tparams: List[TypeDef]): Tree = {
+ // SI-7033 Unattributed to avoid forcing `cdef.symbol.info`.
+ val tycon = Ident(cdef.symbol)
if (tparams.isEmpty) tycon else AppliedTypeTree(tycon, tparams map toIdent)
}
@@ -133,10 +134,10 @@ trait Unapplies extends ast.TreeDSL
/** The apply method corresponding to a case class
*/
- def factoryMeth(mods: Modifiers, name: TermName, cdef: ClassDef, symbolic: Boolean): DefDef = {
+ def factoryMeth(mods: Modifiers, name: TermName, cdef: ClassDef): DefDef = {
val tparams = cdef.tparams map copyUntypedInvariant
val cparamss = constrParamss(cdef)
- def classtpe = classType(cdef, tparams, symbolic)
+ def classtpe = classType(cdef, tparams)
atPos(cdef.pos.focus)(
DefDef(mods, name, tparams, cparamss, classtpe,
New(classtpe, mmap(cparamss)(gen.paramToArg)))
@@ -145,7 +146,7 @@ trait Unapplies extends ast.TreeDSL
/** The apply method corresponding to a case class
*/
- def caseModuleApplyMeth(cdef: ClassDef): DefDef = factoryMeth(caseMods, nme.apply, cdef, symbolic = true)
+ def caseModuleApplyMeth(cdef: ClassDef): DefDef = factoryMeth(caseMods, nme.apply, cdef)
/** The unapply method corresponding to a case class
*/
diff --git a/test/files/pos/t7033.scala b/test/files/pos/t7033.scala
new file mode 100644
index 0000000000..a4d256673b
--- /dev/null
+++ b/test/files/pos/t7033.scala
@@ -0,0 +1,15 @@
+import language.higherKinds
+object Wrap {
+ implicit class X[X](val a: X)
+
+ X[Int](0)
+}
+
+class Wrap {
+ implicit class Y[Y](val a: Y)
+ Y[Int](0)
+ implicit class Z[Z[_]](val a: Z[Wrap.this.Z[Z]])
+ Z[List](List(new Z[List](null)))
+}
+
+case class X[X](val a: X)