diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-01-29 09:15:36 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-01-31 16:50:13 +0100 |
commit | d0afd7ece04e1974093c8c37b0ff6654742ab57b (patch) | |
tree | db2f4f0e30eae93cf1c9721ffb351634020829e4 | |
parent | a5b0fc49e517d1c63d22f9909ac9bed0552ed466 (diff) | |
download | scala-d0afd7ece04e1974093c8c37b0ff6654742ab57b.tar.gz scala-d0afd7ece04e1974093c8c37b0ff6654742ab57b.tar.bz2 scala-d0afd7ece04e1974093c8c37b0ff6654742ab57b.zip |
SI-7700 @unspecialized, Part Deux: Now Working.
This annotation was introduced to allow us to mark methods within
a specialized trait as immune from specialization. In particular,
this is desirable for `Function1.{andThen, compose}`.
However, it seems we need to check for this in two places in the
specialization code base. The feature is now backed with a test.
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala | 28 | ||||
-rw-r--r-- | test/files/run/t7700.check | 2 | ||||
-rw-r--r-- | test/files/run/t7700.scala | 17 |
3 files changed, 38 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index c505d9dc5f..9e86e052c0 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -306,6 +306,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { /** Return the specialized name of 'sym' in the given environment. It * guarantees the same result regardless of the map order by sorting * type variables alphabetically. + * + * !!! Is this safe in the face of the following? + * scala> trait T { def foo[A] = 0}; object O extends T { override def foo[B] = 0 } */ private def specializedName(sym: Symbol, env: TypeEnv): TermName = { val tvars = ( @@ -391,13 +394,16 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { * enclosing member with the annotation. */ private def needsSpecialization(env: TypeEnv, sym: Symbol): Boolean = ( - !sym.ownerChain.exists(_ hasAnnotation UnspecializedClass) && ( + !hasUnspecializableAnnotation(sym) && ( specializedTypeVars(sym).intersect(env.keySet).diff(wasSpecializedForTypeVars(sym)).nonEmpty || sym.isClassConstructor && (sym.enclClass.typeParams exists (_.isSpecialized)) || isNormalizedMember(sym) && info(sym).typeBoundsIn(env) ) ) + private def hasUnspecializableAnnotation(sym: Symbol): Boolean = + sym.ownerChain.exists(_ hasAnnotation UnspecializedClass) + def isNormalizedMember(m: Symbol) = m.isSpecialized && (info get m exists { case NormalizedMember(_) => true case _ => false @@ -907,16 +913,20 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } if (sym.isMethod) { - val stvars = specializedTypeVars(sym) - if (stvars.nonEmpty) - debuglog("specialized %s on %s".format(sym.fullLocationString, stvars.map(_.name).mkString(", "))) + if (hasUnspecializableAnnotation(sym)) { + List() + } else { + val stvars = specializedTypeVars(sym) + if (stvars.nonEmpty) + debuglog("specialized %s on %s".format(sym.fullLocationString, stvars.map(_.name).mkString(", "))) - val tps1 = if (sym.isConstructor) tps filter (sym.info.paramTypes contains _) else tps - val tps2 = tps1 filter stvars - if (!sym.isDeferred) - addConcreteSpecMethod(sym) + val tps1 = if (sym.isConstructor) tps filter (sym.info.paramTypes contains _) else tps + val tps2 = tps1 filter stvars + if (!sym.isDeferred) + addConcreteSpecMethod(sym) - specializeOn(tps2) + specializeOn(tps2) + } } else Nil } diff --git a/test/files/run/t7700.check b/test/files/run/t7700.check new file mode 100644 index 0000000000..ca8e686984 --- /dev/null +++ b/test/files/run/t7700.check @@ -0,0 +1,2 @@ +public abstract java.lang.Object C.bar(java.lang.Object) +public abstract java.lang.Object C.foo(java.lang.Object) diff --git a/test/files/run/t7700.scala b/test/files/run/t7700.scala new file mode 100644 index 0000000000..76d16b808c --- /dev/null +++ b/test/files/run/t7700.scala @@ -0,0 +1,17 @@ +import scala.annotation._ + +trait C[@specialized U] { + @unspecialized + def foo(u: U): U + @unspecialized + def bar[A](u: U) = u +} + +object Test extends App { + val declared = classOf[C[_]].getDeclaredMethods.sortBy(_.getName) + println(declared.mkString("\n")) + object CInt extends C[Int] { def foo(i: Int) = i } + object CAny extends C[Any] { def foo(a: Any) = a } + assert(CInt.foo(1) == 1) + assert(CAny.foo("") == "") +} |