Skip to content

Commit d656307

Browse files
committed
Sbt-compatible implementation of isPastXXXPhase
sbt's [API extraction phase](https://github.com/sbt/sbt/blob/0.13/compile/interface/src/main/scala/xsbt/API.scala#L25) extends `scala.reflect.internal.Phase`, which implements a bunch of methods, such as `erasedTypes` as `false`, which are then overridden by scalac in `GlobalPhase` (nested in scala.tools.nsc.Global). (`erasedTypes` in particular is again overridden in the back-end -- for performance?) However, since sbt's compiler phases extend `reflect.internal.Phase`, the logic for detecting the current phase does not work, as the default implementation is called (simply returning `false`), when chasing the `prev` pointers hits an sbt-injected phase, as its implementation is `reflect.internal`'s constant `false`.
1 parent 81d7c25 commit d656307

File tree

2 files changed

+9
-17
lines changed

2 files changed

+9
-17
lines changed

src/compiler/scala/tools/nsc/Global.scala

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -400,18 +400,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
400400

401401
def apply(unit: CompilationUnit): Unit
402402

403-
private val isErased = prev.name == "erasure" || prev.erasedTypes
404-
override def erasedTypes: Boolean = isErased
405-
private val isFlat = prev.name == "flatten" || prev.flatClasses
406-
override def flatClasses: Boolean = isFlat
407-
private val isSpecialized = prev.name == "specialize" || prev.specialized
408-
override def specialized: Boolean = isSpecialized
409-
private val isRefChecked = prev.name == "refchecks" || prev.refChecked
410-
override def refChecked: Boolean = isRefChecked
411-
412-
private val isAssigningFields = name == "fields" || prev.assignsFields
413-
override def assignsFields: Boolean = isAssigningFields // allow assigning to val
414-
415403
/** Is current phase cancelled on this unit? */
416404
def cancelled(unit: CompilationUnit) = {
417405
// run the typer only if in `createJavadoc` mode

src/reflect/scala/reflect/internal/Phase.scala

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,15 @@ abstract class Phase(val prev: Phase) {
3939
def description: String = name
4040
// Will running with -Ycheck:name work?
4141
def checkable: Boolean = true
42-
def specialized: Boolean = false
43-
def erasedTypes: Boolean = false
44-
def assignsFields: Boolean = false // allow assigning to val
45-
def flatClasses: Boolean = false
46-
def refChecked: Boolean = false
42+
43+
// NOTE: sbt injects its own phases which extend this class, and not GlobalPhase, so we must implement this logic here
44+
private val _erasedTypes = ((prev ne null) && (prev ne NoPhase)) && (prev.name == "erasure" || prev.erasedTypes)
45+
def erasedTypes: Boolean = _erasedTypes // overridden in back-end
46+
final val flatClasses: Boolean = ((prev ne null) && (prev ne NoPhase)) && (prev.name == "flatten" || prev.flatClasses)
47+
final val specialized: Boolean = ((prev ne null) && (prev ne NoPhase)) && (prev.name == "specialize" || prev.specialized)
48+
final val refChecked: Boolean = ((prev ne null) && (prev ne NoPhase)) && (prev.name == "refchecks" || prev.refChecked)
49+
// are we past the fields phase, so that we should allow writing to vals (as part of type checking trait setters)
50+
final val assignsFields: Boolean = ((prev ne null) && (prev ne NoPhase)) && (prev.name == "fields" || prev.assignsFields)
4751

4852
/** This is used only in unsafeTypeParams, and at this writing is
4953
* overridden to false in parser, namer, typer, and erasure. (And NoPhase.)

0 commit comments

Comments
 (0)