Skip to content

Commit 1432634

Browse files
committed
Also increase level for classes
1 parent fa30d7f commit 1432634

File tree

5 files changed

+46
-42
lines changed

5 files changed

+46
-42
lines changed

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

+5
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ class CCState:
7070
myLevel += 1
7171
try op finally myLevel -=1
7272

73+
inline def inNestedLevelUnless[T](inline p: Boolean)(inline op: T): T =
74+
val saved = myLevel
75+
if !p then myLevel += 1
76+
try op finally myLevel = saved
77+
7378
/** The level of the current environment. Levels start at 0 and increase for
7479
* each nested function or class. -1 means the level is undefined.
7580
*/

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

+2-7
Original file line numberDiff line numberDiff line change
@@ -520,14 +520,9 @@ object CaptureSet:
520520
if elem.isRootCapability then !noUniversal
521521
else elem match
522522
case elem: TermRef if levelLimit.exists =>
523-
var sym = elem.symbol
524-
val now = level == -1 || ccState.level(sym) <= level
525-
val was = levelLimit.isContainedIn(elem.symbol.levelOwner)
526-
if was != now then
527-
println(i"Diff levelOK $sym at ${ccState.level(sym)} for $this at $level in ${directOwner}, now $now")
528-
now
523+
level == -1 || ccState.level(elem.symbol) <= level
529524
case elem: ThisType if levelLimit.exists =>
530-
levelLimit.isContainedIn(elem.cls.levelOwner)
525+
level == -1 || ccState.level(elem.cls) + 1 <= level
531526
case ReachCapability(elem1) =>
532527
levelOK(elem1)
533528
case MaybeCapability(elem1) =>

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,8 @@ class CheckCaptures extends Recheck, SymTransformer:
775775
checkSubset(thisSet,
776776
CaptureSet.empty.withDescription(i"of pure base class $pureBase"),
777777
selfType.srcPos, cs1description = " captured by this self type")
778-
super.recheckClassDef(tree, impl, cls)
778+
ccState.inNestedLevelUnless(cls.is(Module)):
779+
super.recheckClassDef(tree, impl, cls)
779780
finally
780781
curEnv = saved
781782

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

+36-33
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,11 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
437437
transformTT(arg, boxed = true, exact = false) // type arguments in type applications are boxed
438438

439439
case tree: TypeDef if tree.symbol.isClass =>
440-
ccState.recordLevel(tree.symbol)
441-
inContext(ctx.withOwner(tree.symbol)):
442-
traverseChildren(tree)
440+
val sym = tree.symbol
441+
ccState.recordLevel(sym)
442+
ccState.inNestedLevelUnless(sym.is(Module)):
443+
inContext(ctx.withOwner(sym))
444+
traverseChildren(tree)
443445

444446
case tree @ SeqLiteral(elems, tpt: TypeTree) =>
445447
traverse(elems)
@@ -546,36 +548,37 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
546548
case tree: TypeDef =>
547549
tree.symbol match
548550
case cls: ClassSymbol =>
549-
val cinfo @ ClassInfo(prefix, _, ps, decls, selfInfo) = cls.classInfo
550-
def innerModule = cls.is(ModuleClass) && !cls.isStatic
551-
val selfInfo1 =
552-
if (selfInfo ne NoType) && !innerModule then
553-
// if selfInfo is explicitly given then use that one, except if
554-
// self info applies to non-static modules, these still need to be inferred
555-
selfInfo
556-
else if cls.isPureClass then
557-
// is cls is known to be pure, nothing needs to be added to self type
558-
selfInfo
559-
else if !cls.isEffectivelySealed && !cls.baseClassHasExplicitSelfType then
560-
// assume {cap} for completely unconstrained self types of publicly extensible classes
561-
CapturingType(cinfo.selfType, CaptureSet.universal)
562-
else
563-
// Infer the self type for the rest, which is all classes without explicit
564-
// self types (to which we also add nested module classes), provided they are
565-
// neither pure, nor are publicily extensible with an unconstrained self type.
566-
CapturingType(cinfo.selfType, CaptureSet.Var(cls, level = ccState.currentLevel))
567-
val ps1 = inContext(ctx.withOwner(cls)):
568-
ps.mapConserve(transformExplicitType(_))
569-
if (selfInfo1 ne selfInfo) || (ps1 ne ps) then
570-
val newInfo = ClassInfo(prefix, cls, ps1, decls, selfInfo1)
571-
updateInfo(cls, newInfo)
572-
capt.println(i"update class info of $cls with parents $ps selfinfo $selfInfo to $newInfo")
573-
cls.thisType.asInstanceOf[ThisType].invalidateCaches()
574-
if cls.is(ModuleClass) then
575-
// if it's a module, the capture set of the module reference is the capture set of the self type
576-
val modul = cls.sourceModule
577-
updateInfo(modul, CapturingType(modul.info, selfInfo1.asInstanceOf[Type].captureSet))
578-
modul.termRef.invalidateCaches()
551+
ccState.inNestedLevelUnless(cls.is(Module)):
552+
val cinfo @ ClassInfo(prefix, _, ps, decls, selfInfo) = cls.classInfo
553+
def innerModule = cls.is(ModuleClass) && !cls.isStatic
554+
val selfInfo1 =
555+
if (selfInfo ne NoType) && !innerModule then
556+
// if selfInfo is explicitly given then use that one, except if
557+
// self info applies to non-static modules, these still need to be inferred
558+
selfInfo
559+
else if cls.isPureClass then
560+
// is cls is known to be pure, nothing needs to be added to self type
561+
selfInfo
562+
else if !cls.isEffectivelySealed && !cls.baseClassHasExplicitSelfType then
563+
// assume {cap} for completely unconstrained self types of publicly extensible classes
564+
CapturingType(cinfo.selfType, CaptureSet.universal)
565+
else
566+
// Infer the self type for the rest, which is all classes without explicit
567+
// self types (to which we also add nested module classes), provided they are
568+
// neither pure, nor are publicily extensible with an unconstrained self type.
569+
CapturingType(cinfo.selfType, CaptureSet.Var(cls, level = ccState.currentLevel))
570+
val ps1 = inContext(ctx.withOwner(cls)):
571+
ps.mapConserve(transformExplicitType(_))
572+
if (selfInfo1 ne selfInfo) || (ps1 ne ps) then
573+
val newInfo = ClassInfo(prefix, cls, ps1, decls, selfInfo1)
574+
updateInfo(cls, newInfo)
575+
capt.println(i"update class info of $cls with parents $ps selfinfo $selfInfo to $newInfo")
576+
cls.thisType.asInstanceOf[ThisType].invalidateCaches()
577+
if cls.is(ModuleClass) then
578+
// if it's a module, the capture set of the module reference is the capture set of the self type
579+
val modul = cls.sourceModule
580+
updateInfo(modul, CapturingType(modul.info, selfInfo1.asInstanceOf[Type].captureSet))
581+
modul.termRef.invalidateCaches()
579582
case _ =>
580583
case _ =>
581584
end postProcess

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import util.SourcePosition
1515
import scala.util.control.NonFatal
1616
import scala.annotation.switch
1717
import config.{Config, Feature}
18-
import cc.{CapturingType, RetainingType, CaptureSet, ReachCapability, MaybeCapability, isBoxed, levelOwner, retainedElems, isRetainsLike}
18+
import cc.{CapturingType, RetainingType, CaptureSet, ReachCapability, MaybeCapability, isBoxed, retainedElems, isRetainsLike}
1919

2020
class PlainPrinter(_ctx: Context) extends Printer {
2121

0 commit comments

Comments
 (0)