Skip to content

Commit a48de98

Browse files
committed
Fix catching of specialized annotations
Detecting annotations on `Specializable` groups or `AnyRef` was flawed
1 parent 993c739 commit a48de98

File tree

1 file changed

+46
-12
lines changed

1 file changed

+46
-12
lines changed

src/dotty/tools/dotc/transform/PreSpecializer.scala

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,52 @@
11
package dotty.tools.dotc.transform
22

3-
import dotty.tools.dotc.ast.Trees.{Select, Ident, SeqLiteral, Typed}
3+
import dotty.tools.dotc.ast.Trees.{Ident, SeqLiteral, Typed}
44
import dotty.tools.dotc.ast.tpd
55
import dotty.tools.dotc.core.Annotations.Annotation
66
import dotty.tools.dotc.core.Contexts.Context
7-
import dotty.tools.dotc.core.StdNames._
8-
import dotty.tools.dotc.core.{Flags, Definitions}
9-
import dotty.tools.dotc.core.Symbols.Symbol
10-
import dotty.tools.dotc.core.Types.{TermRef, Type}
11-
import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, MiniPhaseTransform}
127
import dotty.tools.dotc.core.Decorators._
8+
import dotty.tools.dotc.core.Names.Name
9+
import dotty.tools.dotc.core.StdNames._
10+
import dotty.tools.dotc.core.Symbols.{NoSymbol, Symbol}
11+
import dotty.tools.dotc.core.Types.Type
12+
import dotty.tools.dotc.core.{Definitions, Flags}
13+
import dotty.tools.dotc.transform.TreeTransforms.{TreeTransform, MiniPhaseTransform, TransformerInfo}
1314

1415
/**
15-
* This phase retrieves all `@specialized` anotations before they are thrown away,
16+
* This phase retrieves all `@specialized` anotations,
1617
* and stores them for the `TypeSpecializer` phase.
1718
*/
1819
class PreSpecializer extends MiniPhaseTransform {
1920

2021
override def phaseName: String = "prespecialize"
2122

23+
private var anyRefModule: Symbol = NoSymbol
24+
private var specializableMapping: Map[Symbol, List[Type]] = _
25+
private var specializableModule: Symbol = NoSymbol
26+
27+
28+
override def prepareForUnit(tree: tpd.Tree)(implicit ctx: Context): TreeTransform = {
29+
specializableModule = ctx.requiredModule("scala.Specializable")
30+
anyRefModule = ctx.requiredModule("scala.package") // Using nme.PACKAGE generated errors on my machine - should be further explored
31+
def specializableField(nm: String) = specializableModule.info.member(nm.toTermName).symbol
32+
33+
specializableMapping = Map(
34+
specializableField("Primitives") -> List(defn.IntType, defn.LongType, defn.FloatType, defn.ShortType,
35+
defn.DoubleType, defn.BooleanType, defn.UnitType, defn.CharType, defn.ByteType),
36+
specializableField("Everything") -> List(defn.IntType, defn.LongType, defn.FloatType, defn.ShortType,
37+
defn.DoubleType, defn.BooleanType, defn.UnitType, defn.CharType, defn.ByteType, defn.AnyRefType),
38+
specializableField("Bits32AndUp") -> List(defn.IntType, defn.LongType, defn.FloatType, defn.DoubleType),
39+
specializableField("Integral") -> List(defn.ByteType, defn.ShortType, defn.IntType, defn.LongType, defn.CharType),
40+
specializableField("AllNumeric") -> List(defn.ByteType, defn.ShortType, defn.IntType, defn.LongType,
41+
defn.CharType, defn.FloatType, defn.DoubleType),
42+
specializableField("BestOfBreed") -> List(defn.IntType, defn.DoubleType, defn.BooleanType, defn.UnitType,
43+
defn.AnyRefType)
44+
)
45+
this
46+
}
47+
2248
private final def primitiveCompanionToPrimitive(companion: Type)(implicit ctx: Context) = {
23-
if (companion.termSymbol eq ctx.requiredModule("scala.package").info.member("AnyRef".toTermName).symbol) { // Handles `@specialized(AnyRef)` cases
49+
if (companion.termSymbol eq anyRefModule.info.member(nme.AnyRef.toTermName).symbol) {
2450
defn.AnyRefType
2551
}
2652
else {
@@ -30,6 +56,13 @@ class PreSpecializer extends MiniPhaseTransform {
3056
}
3157
}
3258

59+
private def specializableToPrimitive(specializable: Type, name: Name)(implicit ctx: Context): List[Type] = {
60+
if (specializable.termSymbol eq specializableModule.info.member(name).symbol) {
61+
specializableMapping(specializable.termSymbol)
62+
}
63+
else Nil
64+
}
65+
3366
def defn(implicit ctx: Context): Definitions = ctx.definitions
3467

3568
private def primitiveTypes(implicit ctx: Context) =
@@ -60,12 +93,13 @@ class PreSpecializer extends MiniPhaseTransform {
6093
val args = annot.arguments
6194
if (args.isEmpty) primitiveTypes
6295
else args.head match {
63-
case a@Typed(SeqLiteral(types), _) => // Matches the expected `@specialized(...)` annotations
96+
case a @ Typed(SeqLiteral(types), _) =>
6497
types.map(t => primitiveCompanionToPrimitive(t.tpe))
6598

66-
case a@Select(Ident(_), _) => primitiveTypes // Matches `Select(Ident(Specializable), Primitives)`
67-
// which is used in several instances in the compiler
68-
case _ => ctx.error("surprising match on specialized annotation"); Nil
99+
case a @ Ident(groupName) if a.tpe.isInstanceOf[Type] => // Matches `@specialized` annotations on Specializable Groups
100+
specializableToPrimitive(a.tpe.asInstanceOf[Type], groupName)
101+
102+
case _ => ctx.error("unexpected match on specialized annotation"); Nil
69103
}
70104
case nil => Nil
71105
}

0 commit comments

Comments
 (0)