Skip to content

Commit 24a0777

Browse files
committed
SI-8871 Fix specialization under REPL / FSC
The transformation of applications to specialized methods relies on the owner of said method having had the specialization info transform run which stashes a bunch of related data into per-run caches such as `SpecializeTypes#{typeEnv}`. Recently, we found that per-run caches didn't quite live up to there name, and in fact weren't being cleaned up before a new run. This was remedied in 00e11ff. However, no good deed goes unpunished, and this led to a regression in specialization in the REPL and FSC. This commit makes two changes: - change the specialization info tranformer to no longer directly enter specialized methods into the `info` of whatever the current phase happens to be. This stops them showing up `enteringTyper` of the following run. - change `adaptInfos` to simply discard all but the oldest entry in the type history when bringing a symbol from one run into the next. This generalizes the approach taken to fix SI-7801. The specialization info transformer will now execute in each run, and repopulate `typeEnv` and friends. I see that we have a seemingly related bandaid for this sort of problem since 08505bd. In a followup, I'll try to revert that.
1 parent 8d25e84 commit 24a0777

File tree

6 files changed

+23
-13
lines changed

6 files changed

+23
-13
lines changed

src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -861,11 +861,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
861861
debuglog("%s expands to %s in %s".format(sym, specMember.name.decode, pp(env)))
862862
info(specMember) = NormalizedMember(sym)
863863
newOverload(sym, specMember, env)
864-
// if this is a class, we insert the normalized member in scope,
865-
// if this is a method, there's no attached scope for it (EmptyScope)
866-
val decls = owner.info.decls
867-
if (decls != EmptyScope)
868-
decls.enter(specMember)
869864
specMember
870865
}
871866
}

src/reflect/scala/reflect/internal/Symbols.scala

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
173173
with HasFlags
174174
with Annotatable[Symbol]
175175
with Attachable {
176-
177176
// makes sure that all symbols that runtime reflection deals with are synchronized
178177
private def isSynchronized = this.isInstanceOf[scala.reflect.runtime.SynchronizedSymbols#SynchronizedSymbol]
179178
private def isAprioriThreadsafe = isThreadsafe(AllOps)
@@ -1592,13 +1591,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
15921591
assert(isCompilerUniverse)
15931592
if (infos == null || runId(infos.validFrom) == currentRunId) {
15941593
infos
1595-
} else if (isPackageClass) {
1596-
// SI-7801 early phase package scopes are mutated in new runs (Namers#enterPackage), so we have to
1597-
// discard transformed infos, rather than just marking them as from this run.
1598-
val oldest = infos.oldest
1599-
oldest.validFrom = validTo
1600-
this.infos = oldest
1601-
oldest
1594+
} else if (infos ne infos.oldest) {
1595+
// SI-8871 Discard all but the first element of type history. Specialization only works in the resident
1596+
// compiler / REPL if re-run its info transformer in this run to correctly populate its
1597+
// per-run caches, e.g. typeEnv
1598+
adaptInfos(infos.oldest)
16021599
} else {
16031600
val prev1 = adaptInfos(infos.prev)
16041601
if (prev1 ne infos.prev) prev1

test/files/res/t8871.check

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
nsc>
3+
nsc>
4+
nsc>
5+
nsc>

test/files/res/t8871.res

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
t8871/tag.scala
2+
t8871/usetag.scala
3+
t8871/usetag.scala
4+

test/files/res/t8871/tag.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class Tag {
2+
@inline def apply[@specialized A, T](a: A): A = a
3+
}

test/files/res/t8871/usetag.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
trait Foo
2+
3+
object Test {
4+
val y = new Tag().apply[Double, Foo](3.3)
5+
// under FSC, this gave t8871/usetag.scala:4: error: wrong number of type parameters for method apply$mDc$sp: [T](a: Double)Double
6+
}

0 commit comments

Comments
 (0)