@@ -1089,7 +1089,7 @@ class CheckCaptures extends Recheck, SymTransformer:
1089
1089
1090
1090
if actualBoxed eq actual then
1091
1091
// Only `addOuterRefs` when there is no box adaptation
1092
- expected1 = addOuterRefs(expected1, actual)
1092
+ expected1 = addOuterRefs(expected1, actual, tree.srcPos )
1093
1093
if isCompatible(actualBoxed, expected1) then
1094
1094
if debugSuccesses then tree match
1095
1095
case Ident (_) =>
@@ -1130,8 +1130,12 @@ class CheckCaptures extends Recheck, SymTransformer:
1130
1130
* that are outside `Cls`. These are all accessed through `Cls.this`,
1131
1131
* so we can assume they are already accounted for by `Ce` and adding
1132
1132
* them explicitly to `Ce` changes nothing.
1133
+ * - To make up for this, we also add these variables to the capture set of `Cls`,
1134
+ * so that all instances of `Cls` will capture these outer references.
1135
+ * So in a sense we use `{Cls.this}` as a placeholder for certain outer captures.
1136
+ * that we needed to be subsumed by `Cls.this`.
1133
1137
*/
1134
- private def addOuterRefs (expected : Type , actual : Type )(using Context ): Type =
1138
+ private def addOuterRefs (expected : Type , actual : Type , pos : SrcPos )(using Context ): Type =
1135
1139
1136
1140
def isPure (info : Type ): Boolean = info match
1137
1141
case info : PolyType => isPure(info.resType)
@@ -1144,19 +1148,40 @@ class CheckCaptures extends Recheck, SymTransformer:
1144
1148
else isPure(owner.info) && isPureContext(owner.owner, limit)
1145
1149
1146
1150
// Augment expeced capture set `erefs` by all references in actual capture
1147
- // set `arefs` that are outside some `this.type` reference in `erefs`
1151
+ // set `arefs` that are outside some `C.this.type` reference in `erefs` for an enclosing
1152
+ // class `C`. If an added reference is not a ThisType itself, add it to the capture set
1153
+ // (i.e. use set) of the `C`. This makes sure that any outer reference implicitly subsumed
1154
+ // by `C.this` becomes a capture reference of every instance of `C`.
1148
1155
def augment (erefs : CaptureSet , arefs : CaptureSet ): CaptureSet =
1149
1156
(erefs /: erefs.elems): (erefs, eref) =>
1150
1157
eref match
1151
1158
case eref : ThisType if isPureContext(ctx.owner, eref.cls) =>
1152
- def isOuterRef (aref : Type ): Boolean = aref match
1153
- case aref : TermRef =>
1154
- val owner = aref.symbol.owner
1155
- if owner.isClass then isOuterRef(aref.prefix)
1156
- else eref.cls.isProperlyContainedIn(owner)
1159
+
1160
+ def pathRoot (aref : Type ): Type = aref match
1161
+ case aref : NamedType if aref.symbol.owner.isClass => pathRoot(aref.prefix)
1162
+ case _ => aref
1163
+
1164
+ def isOuterRef (aref : Type ): Boolean = pathRoot(aref) match
1165
+ case aref : NamedType => eref.cls.isProperlyContainedIn(aref.symbol.owner)
1157
1166
case aref : ThisType => eref.cls.isProperlyContainedIn(aref.cls)
1158
1167
case _ => false
1159
- erefs ++ arefs.filter(isOuterRef)
1168
+
1169
+ val outerRefs = arefs.filter(isOuterRef)
1170
+
1171
+ // Include implicitly added outer references in the capture set of the class of `eref`.
1172
+ for outerRef <- outerRefs.elems do
1173
+ if ! erefs.elems.contains(outerRef)
1174
+ && ! pathRoot(outerRef).isInstanceOf [ThisType ]
1175
+ // we don't need to add outer ThisTypes as these are anyway added as path
1176
+ // prefixes at the use site. And this exemption is required since capture sets
1177
+ // of non-local classes are always empty, so we can't add an outer this to them.
1178
+ then
1179
+ def provenance =
1180
+ i """ of the enclosing class ${eref.cls}.
1181
+ |The reference was included since we tried to establish that $arefs <: $erefs"""
1182
+ checkElem(outerRef, capturedVars(eref.cls), pos, provenance)
1183
+
1184
+ erefs ++ outerRefs
1160
1185
case _ =>
1161
1186
erefs
1162
1187
@@ -1341,7 +1366,7 @@ class CheckCaptures extends Recheck, SymTransformer:
1341
1366
* @param sym symbol of the field definition that is being checked
1342
1367
*/
1343
1368
override def checkSubType (actual : Type , expected : Type )(using Context ): Boolean =
1344
- val expected1 = alignDependentFunction(addOuterRefs(expected, actual), actual.stripCapturing)
1369
+ val expected1 = alignDependentFunction(addOuterRefs(expected, actual, srcPos ), actual.stripCapturing)
1345
1370
val actual1 =
1346
1371
val saved = curEnv
1347
1372
try
0 commit comments