Skip to content

Commit c78df14

Browse files
committed
Move most of self type setup to transformSym
We need to do it for compiled as well as imported types. We only keep adding variables to selftypes of local classes in postProcess. This allows us to drop one occurrence of LooseRootChecking
1 parent c9a02c8 commit c78df14

File tree

4 files changed

+41
-51
lines changed

4 files changed

+41
-51
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ trait FollowAliases extends TypeMap:
9595
if t2 ne t1 then return t2
9696
mapOver(t)
9797

98-
class mapRoots(from0: CaptureRoot, to: CaptureRoot)(using Context) extends BiTypeMap, FollowAliases:
98+
class mapRoots(from0: CaptureRoot, to: CaptureRoot)(using Context) extends DeepTypeMap, BiTypeMap, FollowAliases:
9999
val from = from0.followAlias
100100

101101
//override val toString = i"mapRoots($from, $to)"

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

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,12 +1110,7 @@ class CheckCaptures extends Recheck, SymTransformer:
11101110
}
11111111
assert(roots.nonEmpty)
11121112
for case root: ClassSymbol <- roots do
1113-
inContext(ctx.fresh.setOwner(root).withProperty(LooseRootChecking, Some(()))):
1114-
// Without LooseRootChecking, we get problems with F-bounded parent types.
1115-
// These can make `cap` "pop out" in ways that are hard to prevent. I believe
1116-
// to prevent it we'd have to map `cap` in a whole class graph with all parent
1117-
// classes, which would be very expensive. So for now we approximate by assuming
1118-
// different roots are compatible for self type conformance checking.
1113+
inContext(ctx.fresh.setOwner(root)):
11191114
checkSelfAgainstParents(root, root.baseClasses)
11201115
val selfType = root.asClass.classInfo.selfType
11211116
interpolator(startingVariance = -1).traverse(selfType)
@@ -1238,16 +1233,15 @@ class CheckCaptures extends Recheck, SymTransformer:
12381233
setup.postCheck()
12391234

12401235
if !ctx.reporter.errorsReported then
1241-
//inContext(ctx.withProperty(LooseRootChecking, Some(()))):
1242-
// We dont report errors here if previous errors were reported, because other
1243-
// errors often result in bad applied types, but flagging these bad types gives
1244-
// often worse error messages than the original errors.
1245-
val checkApplied = new TreeTraverser:
1246-
def traverse(t: Tree)(using Context) = t match
1247-
case tree: InferredTypeTree =>
1248-
case tree: New =>
1249-
case tree: TypeTree => checkAppliedTypesIn(tree.withKnownType)
1250-
case _ => traverseChildren(t)
1251-
checkApplied.traverse(unit)
1236+
// We dont report errors here if previous errors were reported, because other
1237+
// errors often result in bad applied types, but flagging these bad types gives
1238+
// often worse error messages than the original errors.
1239+
val checkApplied = new TreeTraverser:
1240+
def traverse(t: Tree)(using Context) = t match
1241+
case tree: InferredTypeTree =>
1242+
case tree: New =>
1243+
case tree: TypeTree => checkAppliedTypesIn(tree.withKnownType)
1244+
case _ => traverseChildren(t)
1245+
checkApplied.traverse(unit)
12521246
end CaptureChecker
12531247
end CheckCaptures

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

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -113,24 +113,39 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
113113
def transformSym(symd: SymDenotation)(using Context): SymDenotation =
114114
if !pastRecheck && Feature.ccEnabledSomewhere then
115115
val sym = symd.symbol
116+
def rootTarget =
117+
if sym.isAliasType && sym.isStatic then NoSymbol else sym
116118
def mappedInfo =
117119
if toBeUpdated.contains(sym) then symd.info
118-
else transformExplicitType(symd.info, rootTarget = sym)
120+
else transformExplicitType(symd.info, rootTarget)
119121
// TODO if sym is class && level owner: add a capture root
120122
if Synthetics.needsTransform(symd) then
121123
Synthetics.transform(symd, mappedInfo)
122124
else if isPreCC(sym) then
123125
symd.copySymDenotation(info = fluidify(sym.info))
124126
else if symd.owner.isTerm || symd.is(CaptureChecked) || symd.owner.is(CaptureChecked) then
125127
val newFlags = newFlagsFor(symd)
126-
val newInfo = mappedInfo
128+
var newInfo = mappedInfo
129+
if sym.is(ModuleVal) && !sym.isStatic then
130+
val selfType1 = transformSelfType(sym.moduleClass)
131+
if selfType1.exists then
132+
newInfo = newInfo.capturing(selfType1.captureSet)
133+
sym.termRef.invalidateCaches()
134+
if sym.isClass then
135+
sym.thisType.asInstanceOf[ThisType].invalidateCaches()
127136
if newFlags != symd.flags || (newInfo ne sym.info)
128137
then symd.copySymDenotation(initFlags = newFlags, info = newInfo)
129138
else symd
130139
else symd
131140
else symd
132141
end transformSym
133142

143+
def transformSelfType(sym: Symbol)(using Context) = (sym.info: @unchecked) match
144+
case ClassInfo(_, cls, _, _, selfInfo: Type) =>
145+
inContext(ctx.withOwner(cls)):
146+
transformExplicitType(selfInfo, rootTarget = ctx.owner)
147+
case _ => NoType
148+
134149
/** If `tp` is an unboxed capturing type or a function returning an unboxed capturing type,
135150
* convert it to be boxed.
136151
*/
@@ -490,15 +505,12 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
490505
postProcess(tree)
491506
end traverse
492507

493-
extension (sym: Symbol)(using Context) def unlessStatic =
494-
val owner = sym.levelOwner
495-
if sym.isStaticOwner then NoSymbol else owner
496-
497508
def postProcess(tree: Tree)(using Context): Unit = tree match
498509
case tree: TypeTree =>
499510
val lowner =
500511
transformTT(tree, boxed = false, exact = false,
501-
rootTarget = ctx.owner.unlessStatic // roots of other types in static locations are not mapped
512+
rootTarget = if ctx.owner.isStaticOwner then NoSymbol else ctx.owner
513+
// roots of other types in static locations are not mapped
502514
)
503515
case tree: ValOrDefDef =>
504516
val sym = tree.symbol
@@ -594,22 +606,13 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
594606
tree.symbol match
595607
case cls: ClassSymbol =>
596608
val cinfo @ ClassInfo(prefix, _, ps, decls, selfInfo) = cls.classInfo
597-
val newSelfType =
598-
if (selfInfo eq NoType) || cls.is(ModuleClass) && !cls.isStatic then
599-
// add capture set to self type of nested classes if no self type is given explicitly.
600-
// It's unclear what the right level owner should be. A self type should
601-
// be able to mention class parameters, which are owned by the class; that's
602-
// why the class was picked as level owner. But self types should not be able
603-
// to mention other fields.
604-
CapturingType(cinfo.selfType, CaptureSet.Var(cls))
605-
else selfInfo match
606-
case selfInfo: Type =>
607-
val selfInfo1 = inContext(ctx.withOwner(cls)):
608-
transformExplicitType(selfInfo, rootTarget = ctx.owner)
609-
if selfInfo1 eq selfInfo then NoType else selfInfo1
610-
case _ =>
611-
NoType
612-
if newSelfType.exists then
609+
if (selfInfo eq NoType) || cls.is(ModuleClass) && !cls.isStatic then
610+
// add capture set to self type of nested classes if no self type is given explicitly.
611+
// It's unclear what the right level owner should be. A self type should
612+
// be able to mention class parameters, which are owned by the class; that's
613+
// why the class was picked as level owner. But self types should not be able
614+
// to mention other fields.
615+
val newSelfType = CapturingType(cinfo.selfType, CaptureSet.Var(cls))
613616
ccSetup.println(i"mapped self type for $cls: $newSelfType, was $selfInfo")
614617
val ps1 = ps.mapConserve(transformExplicitType(_, rootTarget = ctx.owner))
615618
val newInfo = ClassInfo(prefix, cls, ps1, decls, newSelfType)
@@ -621,11 +624,6 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
621624
updateInfo(modul, CapturingType(modul.info, newSelfType.captureSet))
622625
modul.termRef.invalidateCaches()
623626
case _ =>
624-
val info = tree.symbol.info
625-
val newInfo = transformExplicitType(info, rootTarget = ctx.owner.unlessStatic)
626-
updateInfo(tree.symbol, newInfo)
627-
if newInfo ne info then
628-
ccSetup.println(i"update info of ${tree.symbol} from $info to $newInfo")
629627
case _ =>
630628
end postProcess
631629
end setupTraverser

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5120,10 +5120,8 @@ object Types {
51205120
else if (clsd.is(Module)) givenSelf
51215121
else if (ctx.erasedTypes) appliedRef
51225122
else givenSelf.dealiasKeepAnnots match
5123-
case givenSelf1 @ CapturingType(tp, _) =>
5124-
givenSelf1.derivedAnnotatedType(tp & appliedRef, givenSelf1.annot)
5125-
case givenSelf1 @ RetainingType(tp, _) =>
5126-
givenSelf1.derivedAnnotatedType(tp & appliedRef, givenSelf1.annot)
5123+
case givenSelf1 @ AnnotatedType(tp, ann) if ann.symbol == defn.RetainsAnnot =>
5124+
givenSelf1.derivedAnnotatedType(tp & appliedRef, ann)
51275125
case _ =>
51285126
AndType(givenSelf, appliedRef)
51295127
}
@@ -5969,7 +5967,7 @@ object Types {
59695967
val prefix1 = this(tp.prefix)
59705968
val parents1 = tp.declaredParents mapConserve this
59715969
val selfInfo1: TypeOrSymbol = tp.selfInfo match {
5972-
case selfInfo: Type => this(selfInfo)
5970+
case selfInfo: Type => inContext(ctx.withOwner(tp.cls))(this(selfInfo))
59735971
case selfInfo => selfInfo
59745972
}
59755973
tp.derivedClassInfo(prefix1, parents1, tp.decls, selfInfo1)

0 commit comments

Comments
 (0)