Skip to content

Commit 3fe6080

Browse files
committed
Remove old level checking code
Remove old level checking code and debug infra to compare old with new.
1 parent 7a36a3e commit 3fe6080

File tree

5 files changed

+72
-176
lines changed

5 files changed

+72
-176
lines changed

compiler/src/dotty/tools/dotc/cc/CCState.scala

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,6 @@ class CCState:
2121
*/
2222
val approxWarnings: mutable.ListBuffer[Message] = mutable.ListBuffer()
2323

24-
// ------ Level handling ---------------------------
25-
26-
private var curLevel: Level = outermostLevel
27-
28-
/** The level of the current environment. Levels start at 0 and increase for
29-
* each nested function or class. -1 means the level is undefined.
30-
*/
31-
def currentLevel(using Context): Level = curLevel
32-
33-
/** Perform `op` in the next inner level */
34-
inline def inNestedLevel[T](inline op: T)(using Context): T =
35-
val saved = curLevel
36-
curLevel = curLevel.nextInner
37-
try op finally curLevel = saved
38-
39-
/** Perform `op` in the next inner level unless `p` holds. */
40-
inline def inNestedLevelUnless[T](inline p: Boolean)(inline op: T)(using Context): T =
41-
val saved = curLevel
42-
if !p then curLevel = curLevel.nextInner
43-
try op finally curLevel = saved
44-
45-
/** A map recording the level of a symbol */
46-
private val mySymLevel: mutable.Map[Symbol, Level] = mutable.Map()
47-
48-
def symLevel(sym: Symbol): Level = mySymLevel.getOrElse(sym, undefinedLevel)
49-
50-
def recordLevel(sym: Symbol)(using Context): Unit = mySymLevel(sym) = curLevel
51-
5224
// ------ BiTypeMap adjustment -----------------------
5325

5426
private var myMapFutureElems = true
@@ -117,17 +89,6 @@ class CCState:
11789

11890
object CCState:
11991

120-
opaque type Level = Int
121-
122-
val undefinedLevel: Level = -1
123-
124-
val outermostLevel: Level = 0
125-
126-
extension (x: Level)
127-
def isDefined: Boolean = x >= 0
128-
def <= (y: Level) = (x: Int) <= y
129-
def nextInner: Level = if isDefined then x + 1 else x
130-
13192
/** If we are currently in capture checking or setup, and `mt` is a method
13293
* type that is not a prefix of a curried method, perform `op` assuming
13394
* a fresh enclosing existential scope `mt`, otherwise perform `op` directly.

compiler/src/dotty/tools/dotc/cc/Capability.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import CaptureSet.VarState
1616
import Annotations.Annotation
1717
import Flags.*
1818
import config.Printers.capt
19-
import CCState.{Level, undefinedLevel}
2019
import annotation.constructorOnly
2120
import ast.tpd
2221
import printing.{Printer, Showable}

compiler/src/dotty/tools/dotc/cc/CaptureSet.scala

Lines changed: 6 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,6 @@ sealed abstract class CaptureSet extends Showable:
7676
/** Is this set provisionally solved, so that another cc run might unfreeze it? */
7777
def isProvisionallySolved(using Context): Boolean
7878

79-
/** An optional level limit, or undefinedLevel if none exists. All elements of the set
80-
* must be at levels equal or smaller than the level of the set, if it is defined.
81-
*/
82-
def level: Level
83-
8479
/** An optional owner, or NoSymbol if none exists. Used for diagnstics
8580
*/
8681
def owner: Symbol
@@ -607,8 +602,6 @@ object CaptureSet:
607602

608603
def withDescription(description: String): Const = Const(elems, description)
609604

610-
def level = undefinedLevel
611-
612605
def owner = NoSymbol
613606

614607
def dropEmpties()(using Context) = this
@@ -663,7 +656,7 @@ object CaptureSet:
663656
inline val debugTarget = 1745
664657

665658
/** The subclass of captureset variables with given initial elements */
666-
class Var(initialOwner: Symbol = NoSymbol, initialElems: Refs = emptyRefs, val level: Level = undefinedLevel, underBox: Boolean = false)(using /*@constructorOnly*/ ictx: Context) extends CaptureSet:
659+
class Var(initialOwner: Symbol = NoSymbol, initialElems: Refs = emptyRefs, underBox: Boolean = false)(using /*@constructorOnly*/ ictx: Context) extends CaptureSet:
667660

668661
override def owner = initialOwner
669662

@@ -833,40 +826,7 @@ object CaptureSet:
833826
case _ => foldOver(b, t)
834827
find(false, binder)
835828

836-
def levelOKold(elem: Capability)(using Context): Boolean = elem match
837-
case _: FreshCap =>
838-
!level.isDefined
839-
|| ccState.symLevel(elem.ccOwner) <= level
840-
|| {
841-
capt.println(i"LEVEL ERROR $elem cannot be included in $this of $owner")
842-
false
843-
}
844-
case elem @ ResultCap(binder) =>
845-
rootLimit == null && (this.isInstanceOf[BiMapped] || isPartOf(binder.resType))
846-
case GlobalCap =>
847-
rootLimit == null
848-
case elem: TermRef if level.isDefined =>
849-
elem.prefix match
850-
case prefix: Capability =>
851-
levelOK(prefix)
852-
case _ =>
853-
ccState.symLevel(elem.symbol) <= level
854-
case elem: ThisType if level.isDefined =>
855-
ccState.symLevel(elem.cls).nextInner <= level
856-
case elem: ParamRef if !this.isInstanceOf[BiMapped] =>
857-
isPartOf(elem.binder.resType)
858-
|| {
859-
capt.println(
860-
i"""LEVEL ERROR $elem for $this
861-
|elem binder = ${elem.binder}""")
862-
false
863-
}
864-
case elem: DerivedCapability =>
865-
levelOK(elem.underlying)
866-
case _ =>
867-
true
868-
869-
def levelOKnew(elem: Capability)(using Context): Boolean = elem match
829+
def levelOK(elem: Capability)(using Context): Boolean = elem match
870830
case elem @ ResultCap(binder) =>
871831
rootLimit == null && (this.isInstanceOf[BiMapped] || isPartOf(binder.resType))
872832
case GlobalCap =>
@@ -879,16 +839,6 @@ object CaptureSet:
879839
!elemVis.isProperlyContainedIn(owner)
880840
else true
881841

882-
inline val debugLevelChecking = false
883-
884-
def levelOK(elem: Capability)(using Context): Boolean =
885-
val now = levelOKnew(elem)
886-
if debugLevelChecking then
887-
val was = levelOKold(elem)
888-
if was != now then
889-
println(i"LEVEL DIFF for $this / $getClass in ${owner.ownersIterator.toList} and elem $elem in ${elem.ccOwner}, was $was")
890-
now
891-
892842
def addDependent(cs: CaptureSet)(using Context, VarState): Boolean =
893843
(cs eq this)
894844
|| cs.isUniversal
@@ -968,15 +918,9 @@ object CaptureSet:
968918
*/
969919
override def optionalInfo(using Context): String =
970920
for vars <- ctx.property(ShownVars) do vars += this
971-
val debugInfo =
972-
if !ctx.settings.YccDebug.value then ""
973-
else if isConst then ids ++ "(solved)"
974-
else ids
975-
val limitInfo =
976-
if ctx.settings.YprintLevel.value && level.isDefined
977-
then i"<at level ${level.toString}>"
978-
else ""
979-
debugInfo ++ limitInfo
921+
if !ctx.settings.YccDebug.value then ""
922+
else if isConst then ids ++ "(solved)"
923+
else ids
980924

981925
/** Used for diagnostics and debugging: A string that traces the creation
982926
* history of a variable by following source links. Each variable on the
@@ -1378,7 +1322,7 @@ object CaptureSet:
13781322
override def toText(printer: Printer): Text =
13791323
inContext(printer.printerContext):
13801324
if levelError then
1381-
i"($elem at wrong level for $cs at level ${cs.level.toString})"
1325+
i"($elem at wrong level for $cs in ${cs.owner.showLocated})"
13821326
else
13831327
if ctx.settings.YccDebug.value
13841328
then i"$elem cannot be included in $trace"

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ class CheckCaptures extends Recheck, SymTransformer:
430430
def capturedVars(sym: Symbol)(using Context): CaptureSet =
431431
myCapturedVars.getOrElseUpdate(sym,
432432
if sym.isTerm || !sym.owner.isStaticOwner
433-
then CaptureSet.Var(sym, level = ccState.symLevel(sym))
433+
then CaptureSet.Var(sym)
434434
else CaptureSet.empty)
435435

436436
// ---- Record Uses with MarkFree ----------------------------------------------------
@@ -1091,14 +1091,13 @@ class CheckCaptures extends Recheck, SymTransformer:
10911091
if ac.isEmpty then ctx
10921092
else ctx.withProperty(CaptureSet.AssumedContains, Some(ac))
10931093

1094-
ccState.inNestedLevel: // TODO: nestedLevel needed here?
1095-
try checkInferredResult(super.recheckDefDef(tree, sym)(using bodyCtx), tree)
1096-
finally
1097-
if !sym.isAnonymousFunction then
1098-
// Anonymous functions propagate their type to the enclosing environment
1099-
// so it is not in general sound to interpolate their types.
1100-
interpolateIfInferred(tree.tpt, sym)
1101-
curEnv = saved
1094+
try checkInferredResult(super.recheckDefDef(tree, sym)(using bodyCtx), tree)
1095+
finally
1096+
if !sym.isAnonymousFunction then
1097+
// Anonymous functions propagate their type to the enclosing environment
1098+
// so it is not in general sound to interpolate their types.
1099+
interpolateIfInferred(tree.tpt, sym)
1100+
curEnv = saved
11021101
end recheckDefDef
11031102

11041103
/** If val or def definition with inferred (result) type is visible
@@ -1228,8 +1227,7 @@ class CheckCaptures extends Recheck, SymTransformer:
12281227
case AppliedType(fn, args) =>
12291228
markFreeTypeArgs(tpt, fn.typeSymbol, args.map(TypeTree(_)))
12301229
case _ =>
1231-
ccState.inNestedLevelUnless(cls.is(Module)):
1232-
super.recheckClassDef(tree, impl, cls)
1230+
super.recheckClassDef(tree, impl, cls)
12331231
finally
12341232
completed += cls
12351233
curEnv = saved
@@ -1311,7 +1309,7 @@ class CheckCaptures extends Recheck, SymTransformer:
13111309
tree match
13121310
case _: RefTree | closureDef(_) if pt.isBoxedCapturing =>
13131311
curEnv = Env(curEnv.owner, EnvKind.Boxed,
1314-
CaptureSet.Var(curEnv.owner, level = ccState.currentLevel), curEnv)
1312+
CaptureSet.Var(curEnv.owner), curEnv)
13151313
case _ =>
13161314
val res =
13171315
try
@@ -1577,7 +1575,7 @@ class CheckCaptures extends Recheck, SymTransformer:
15771575
curEnv = Env(
15781576
curEnv.owner,
15791577
if boxed then EnvKind.Boxed else EnvKind.NestedInOwner,
1580-
CaptureSet.Var(curEnv.owner, level = ccState.currentLevel),
1578+
CaptureSet.Var(curEnv.owner),
15811579
if boxed then null else curEnv)
15821580
try
15831581
val (eargs, eres) = expected.dealias.stripCapturing match

compiler/src/dotty/tools/dotc/cc/Setup.scala

Lines changed: 55 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -520,16 +520,13 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
520520
if isExcluded(meth) then
521521
return
522522

523-
ccState.recordLevel(meth)
524-
ccState.inNestedLevel:
525-
inContext(ctx.withOwner(meth)):
526-
paramss.foreach(traverse)
527-
transformResultType(tpt, meth)
528-
traverse(tree.rhs)
523+
inContext(ctx.withOwner(meth)):
524+
paramss.foreach(traverse)
525+
transformResultType(tpt, meth)
526+
traverse(tree.rhs)
529527

530528
case tree @ ValDef(_, tpt: TypeTree, _) =>
531529
val sym = tree.symbol
532-
ccState.recordLevel(sym)
533530
val defCtx = if sym.isOneOf(TermParamOrAccessor) then ctx else ctx.withOwner(sym)
534531
inContext(defCtx):
535532
transformResultType(tpt, sym)
@@ -546,10 +543,8 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
546543

547544
case tree: TypeDef if tree.symbol.isClass =>
548545
val sym = tree.symbol
549-
ccState.recordLevel(sym)
550-
ccState.inNestedLevelUnless(sym.is(Module)):
551-
inContext(ctx.withOwner(sym))
552-
traverseChildren(tree)
546+
inContext(ctx.withOwner(sym))
547+
traverseChildren(tree)
553548

554549
case tree @ TypeDef(_, rhs: TypeTree) =>
555550
transformTT(rhs, tree.symbol, boxed = false)
@@ -670,55 +665,54 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
670665
tree.symbol match
671666
case cls: ClassSymbol =>
672667
checkClassifiedInheritance(cls)
673-
ccState.inNestedLevelUnless(cls.is(Module)):
674-
val cinfo @ ClassInfo(prefix, _, ps, decls, selfInfo) = cls.classInfo
675-
676-
// Compute new self type
677-
def isInnerModule = cls.is(ModuleClass) && !cls.isStatic
678-
val selfInfo1 =
679-
if (selfInfo ne NoType) && !isInnerModule then
680-
// if selfInfo is explicitly given then use that one, except if
681-
// self info applies to non-static modules, these still need to be inferred
682-
selfInfo
683-
else if cls.isPureClass then
684-
// is cls is known to be pure, nothing needs to be added to self type
685-
selfInfo
686-
else if !cls.isEffectivelySealed && !cls.baseClassHasExplicitNonUniversalSelfType then
687-
// assume {cap} for completely unconstrained self types of publicly extensible classes
688-
CapturingType(cinfo.selfType, CaptureSet.universal)
689-
else
690-
// Infer the self type for the rest, which is all classes without explicit
691-
// self types (to which we also add nested module classes), provided they are
692-
// neither pure, nor are publicily extensible with an unconstrained self type.
693-
val cs = CaptureSet.Var(cls, level = ccState.currentLevel)
694-
if cls.derivesFrom(defn.Caps_Capability) then
695-
// If cls is a capability class, we need to add a fresh readonly capability to
696-
// ensure we cannot treat the class as pure.
697-
CaptureSet.fresh(Origin.InDecl(cls)).readOnly.subCaptures(cs)
698-
CapturingType(cinfo.selfType, cs)
699-
700-
// Compute new parent types
701-
val ps1 = inContext(ctx.withOwner(cls)):
702-
ps.mapConserve(transformExplicitType(_, NoSymbol, freshen = false))
703-
704-
// Install new types and if it is a module class also update module object
705-
if (selfInfo1 ne selfInfo) || (ps1 ne ps) then
706-
val newInfo = ClassInfo(prefix, cls, ps1, decls, selfInfo1)
707-
updateInfo(cls, newInfo, cls.owner)
708-
capt.println(i"update class info of $cls with parents $ps selfinfo $selfInfo to $newInfo")
709-
cls.thisType.asInstanceOf[ThisType].invalidateCaches()
710-
if cls.is(ModuleClass) then
711-
// if it's a module, the capture set of the module reference is the capture set of the self type
712-
val modul = cls.sourceModule
713-
val selfCaptures = selfInfo1 match
714-
case CapturingType(_, refs) => refs
715-
case _ => CaptureSet.empty
716-
// Note: Can't do val selfCaptures = selfInfo1.captureSet here.
717-
// This would potentially give stackoverflows when setup is run repeatedly.
718-
// One test case is pos-custom-args/captures/checkbounds.scala under
719-
// ccConfig.alwaysRepeatRun = true.
720-
updateInfo(modul, CapturingType(modul.info, selfCaptures), modul.owner)
721-
modul.termRef.invalidateCaches()
668+
val cinfo @ ClassInfo(prefix, _, ps, decls, selfInfo) = cls.classInfo
669+
670+
// Compute new self type
671+
def isInnerModule = cls.is(ModuleClass) && !cls.isStatic
672+
val selfInfo1 =
673+
if (selfInfo ne NoType) && !isInnerModule then
674+
// if selfInfo is explicitly given then use that one, except if
675+
// self info applies to non-static modules, these still need to be inferred
676+
selfInfo
677+
else if cls.isPureClass then
678+
// is cls is known to be pure, nothing needs to be added to self type
679+
selfInfo
680+
else if !cls.isEffectivelySealed && !cls.baseClassHasExplicitNonUniversalSelfType then
681+
// assume {cap} for completely unconstrained self types of publicly extensible classes
682+
CapturingType(cinfo.selfType, CaptureSet.universal)
683+
else
684+
// Infer the self type for the rest, which is all classes without explicit
685+
// self types (to which we also add nested module classes), provided they are
686+
// neither pure, nor are publicily extensible with an unconstrained self type.
687+
val cs = CaptureSet.Var(cls)
688+
if cls.derivesFrom(defn.Caps_Capability) then
689+
// If cls is a capability class, we need to add a fresh readonly capability to
690+
// ensure we cannot treat the class as pure.
691+
CaptureSet.fresh(Origin.InDecl(cls)).readOnly.subCaptures(cs)
692+
CapturingType(cinfo.selfType, cs)
693+
694+
// Compute new parent types
695+
val ps1 = inContext(ctx.withOwner(cls)):
696+
ps.mapConserve(transformExplicitType(_, NoSymbol, freshen = false))
697+
698+
// Install new types and if it is a module class also update module object
699+
if (selfInfo1 ne selfInfo) || (ps1 ne ps) then
700+
val newInfo = ClassInfo(prefix, cls, ps1, decls, selfInfo1)
701+
updateInfo(cls, newInfo, cls.owner)
702+
capt.println(i"update class info of $cls with parents $ps selfinfo $selfInfo to $newInfo")
703+
cls.thisType.asInstanceOf[ThisType].invalidateCaches()
704+
if cls.is(ModuleClass) then
705+
// if it's a module, the capture set of the module reference is the capture set of the self type
706+
val modul = cls.sourceModule
707+
val selfCaptures = selfInfo1 match
708+
case CapturingType(_, refs) => refs
709+
case _ => CaptureSet.empty
710+
// Note: Can't do val selfCaptures = selfInfo1.captureSet here.
711+
// This would potentially give stackoverflows when setup is run repeatedly.
712+
// One test case is pos-custom-args/captures/checkbounds.scala under
713+
// ccConfig.alwaysRepeatRun = true.
714+
updateInfo(modul, CapturingType(modul.info, selfCaptures), modul.owner)
715+
modul.termRef.invalidateCaches()
722716
case _ =>
723717
case _ =>
724718
end postProcess
@@ -857,7 +851,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
857851

858852
/** Add a capture set variable to `tp` if necessary. */
859853
private def addVar(tp: Type, owner: Symbol)(using Context): Type =
860-
decorate(tp, CaptureSet.Var(owner, _, level = ccState.currentLevel))
854+
decorate(tp, CaptureSet.Var(owner, _))
861855

862856
/** A map that adds <fluid> capture sets at all contra- and invariant positions
863857
* in a type where a capture set would be needed. This is used to make types

0 commit comments

Comments
 (0)