Skip to content

Commit 257c6f3

Browse files
committed
Collect checks to run in CrossVersionChecks
Check for deprecation when inlining or constant folding, but avoid cyclic errors by deferring the exclusion check, which walks the owner chain, until CrossVersionChecks, where the check normally happens.
1 parent a3c0bef commit 257c6f3

File tree

14 files changed

+298
-246
lines changed

14 files changed

+298
-246
lines changed

Diff for: compiler/src/dotty/tools/dotc/core/Constants.scala

+7-7
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ package dotty.tools
22
package dotc
33
package core
44

5-
import Types._, Symbols._, Contexts._
5+
import Types.*, Symbols.*, Contexts.*
66
import printing.Printer
77
import printing.Texts.Text
88

9-
object Constants {
9+
object Constants:
1010

11+
type Tag = Int
1112
inline val NoTag = 0
1213
inline val UnitTag = 1
1314
inline val BooleanTag = 2
@@ -22,7 +23,7 @@ object Constants {
2223
inline val NullTag = 11
2324
inline val ClazzTag = 12
2425

25-
class Constant(val value: Any, val tag: Int) extends printing.Showable with Product1[Any] {
26+
class Constant(val value: Any, val tag: Tag) extends printing.Showable with Product1[Any]:
2627
import java.lang.Double.doubleToRawLongBits
2728
import java.lang.Float.floatToRawIntBits
2829

@@ -223,9 +224,8 @@ object Constants {
223224
def get: Any = value
224225
def isEmpty: Boolean = false
225226
def _1: Any = value
226-
}
227227

228-
object Constant {
228+
object Constant:
229229
def apply(x: Null): Constant = new Constant(x, NullTag)
230230
def apply(x: Unit): Constant = new Constant(x, UnitTag)
231231
def apply(x: Boolean): Constant = new Constant(x, BooleanTag)
@@ -257,5 +257,5 @@ object Constants {
257257
)
258258

259259
def unapply(c: Constant): Constant = c
260-
}
261-
}
260+
261+
end Constant

Diff for: compiler/src/dotty/tools/dotc/core/Contexts.scala

+24-5
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import config.Config
2323
import reporting._
2424
import io.{AbstractFile, NoAbstractFile, PlainFile, Path}
2525
import scala.io.Codec
26-
import collection.mutable
26+
import collection.mutable, mutable.ArrayBuffer
2727
import printing._
2828
import config.{JavaPlatform, SJSPlatform, Platform, ScalaSettings}
2929
import classfile.ReusableDataReader
@@ -52,8 +52,10 @@ object Contexts {
5252
private val (notNullInfosLoc, store8) = store7.newLocation[List[NotNullInfo]]()
5353
private val (importInfoLoc, store9) = store8.newLocation[ImportInfo | Null]()
5454
private val (typeAssignerLoc, store10) = store9.newLocation[TypeAssigner](TypeAssigner)
55+
private val (usagesLoc, store11) = store10.newLocation[Any]() // unusages feature
56+
private val (deferredChecksLoc, store12) = store11.newLocation[DeferredChecks]()
5557

56-
private val initialStore = store10
58+
private val initialStore = store12
5759

5860
/** The current context */
5961
inline def ctx(using ctx: Context): Context = ctx
@@ -93,6 +95,9 @@ object Contexts {
9395
inline def atPhaseNoEarlier[T](limit: Phase)(inline op: Context ?=> T)(using Context): T =
9496
op(using if !limit.exists || limit <= ctx.phase then ctx else ctx.withPhase(limit))
9597

98+
inline def deferredCheck(phase: String)(inline op: Context ?=> Unit)(using Context): Unit =
99+
ctx.deferredChecks.add(phase)(op)
100+
96101
inline def inMode[T](mode: Mode)(inline op: Context ?=> T)(using ctx: Context): T =
97102
op(using if mode != ctx.mode then ctx.fresh.setMode(mode) else ctx)
98103

@@ -239,6 +244,8 @@ object Contexts {
239244
/** The current type assigner or typer */
240245
def typeAssigner: TypeAssigner = store(typeAssignerLoc)
241246

247+
def deferredChecks: DeferredChecks = store(deferredChecksLoc)
248+
242249
/** The new implicit references that are introduced by this scope */
243250
protected var implicitsCache: ContextualImplicits | Null = null
244251
def implicits: ContextualImplicits = {
@@ -812,6 +819,7 @@ object Contexts {
812819
store = initialStore
813820
.updated(settingsStateLoc, settingsGroup.defaultState)
814821
.updated(notNullInfosLoc, Nil)
822+
.updated(deferredChecksLoc, DeferredChecks())
815823
.updated(compilationUnitLoc, NoCompilationUnit)
816824
searchHistory = new SearchRoot
817825
gadt = EmptyGadtConstraint
@@ -954,13 +962,13 @@ object Contexts {
954962

955963
protected[dotc] val indentTab: String = " "
956964

957-
private[Contexts] val exploreContexts = new mutable.ArrayBuffer[FreshContext]
965+
private[Contexts] val exploreContexts = ArrayBuffer.empty[FreshContext]
958966
private[Contexts] var exploresInUse: Int = 0
959967

960-
private[Contexts] val changeOwnerContexts = new mutable.ArrayBuffer[FreshContext]
968+
private[Contexts] val changeOwnerContexts = ArrayBuffer.empty[FreshContext]
961969
private[Contexts] var changeOwnersInUse: Int = 0
962970

963-
private[Contexts] val comparers = new mutable.ArrayBuffer[TypeComparer]
971+
private[Contexts] val comparers = ArrayBuffer.empty[TypeComparer]
964972
private[Contexts] var comparersInUse: Int = 0
965973

966974
private var charArray = new Array[Char](256)
@@ -996,4 +1004,15 @@ object Contexts {
9961004
if (thread == null) thread = Thread.currentThread()
9971005
else assert(thread == Thread.currentThread(), "illegal multithreaded access to ContextBase")
9981006
}
1007+
1008+
class DeferredChecks:
1009+
private val checks = mutable.Map[String, ArrayBuffer[Context ?=> Unit]]()
1010+
1011+
def add(phase: String)(item: Context ?=> Unit): Unit = checks.getOrElseUpdate(phase, ArrayBuffer.empty).addOne(item)
1012+
1013+
def run(phase: String)(using Context): Unit =
1014+
for items <- checks.remove(phase) do
1015+
for item <- items do
1016+
item
1017+
end DeferredChecks
9991018
}

Diff for: compiler/src/dotty/tools/dotc/core/Phases.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ object Phases {
5757
final def phasePlan: List[List[Phase]] = this.phasesPlan
5858
final def setPhasePlan(phasess: List[List[Phase]]): Unit = this.phasesPlan = phasess
5959

60-
/** Squash TreeTransform's beloning to same sublist to a single TreeTransformer
61-
* Each TreeTransform gets own period,
62-
* whereas a combined TreeTransformer gets period equal to union of periods of it's TreeTransforms
63-
*/
60+
/** Squash TreeTransforms that belong to same sublist to a single TreeTransformer.
61+
* Each TreeTransform gets own period,
62+
* whereas a combined TreeTransformer gets period equal to union of periods of its TreeTransforms.
63+
*/
6464
final def fusePhases(phasess: List[List[Phase]],
6565
phasesToSkip: List[String],
6666
stopBeforePhases: List[String],

Diff for: compiler/src/dotty/tools/dotc/inlines/Inlines.scala

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ object Inlines:
8686
if (tree.symbol == defn.CompiletimeTesting_typeCheckErrors) return Intrinsics.typeCheckErrors(tree)
8787

8888
CrossVersionChecks.checkExperimentalRef(tree.symbol, tree.srcPos)
89+
CrossVersionChecks.checkDeprecatedDeferred(tree.symbol, tree.srcPos)
8990

9091
if tree.symbol.isConstructor then return tree // error already reported for the inline constructor definition
9192

0 commit comments

Comments
 (0)