@@ -141,25 +141,12 @@ class CheckCaptures extends Recheck, SymTransformer:
141
141
142
142
override def run (using Context ): Unit =
143
143
if Feature .ccEnabled then
144
- checkOverrides.traverse(ctx.compilationUnit.tpdTree)
145
144
super .run
146
145
147
146
override def transformSym (sym : SymDenotation )(using Context ): SymDenotation =
148
147
if Synthetics .needsTransform(sym) then Synthetics .transformFromCC(sym)
149
148
else super .transformSym(sym)
150
149
151
- /** Check overrides again, taking capture sets into account.
152
- * TODO: Can we avoid doing overrides checks twice?
153
- * We need to do them here since only at this phase CaptureTypes are relevant
154
- * But maybe we can then elide the check during the RefChecks phase under captureChecking?
155
- */
156
- def checkOverrides = new TreeTraverser :
157
- def traverse (t : Tree )(using Context ) =
158
- t match
159
- case t : Template => checkAllOverrides(ctx.owner.asClass)
160
- case _ =>
161
- traverseChildren(t)
162
-
163
150
class CaptureChecker (ictx : Context ) extends Rechecker (ictx):
164
151
import ast .tpd .*
165
152
@@ -668,8 +655,11 @@ class CheckCaptures extends Recheck, SymTransformer:
668
655
case _ =>
669
656
expected
670
657
671
- /** Adapt `actual` type to `expected` type by inserting boxing and unboxing conversions */
672
- def adaptBoxed (actual : Type , expected : Type , pos : SrcPos )(using Context ): Type =
658
+ /** Adapt `actual` type to `expected` type by inserting boxing and unboxing conversions
659
+ *
660
+ * @param alwaysConst always make capture set variables constant after adaptation
661
+ */
662
+ def adaptBoxed (actual : Type , expected : Type , pos : SrcPos , alwaysConst : Boolean = false )(using Context ): Type =
673
663
674
664
/** Adapt function type `actual`, which is `aargs -> ares` (possibly with dependencies)
675
665
* to `expected` type.
@@ -806,9 +796,9 @@ class CheckCaptures extends Recheck, SymTransformer:
806
796
}
807
797
if ! insertBox then // unboxing
808
798
markFree(criticalSet, pos)
809
- recon(CapturingType (parent1, cs1, ! actualIsBoxed))
799
+ recon(CapturingType (parent1, if alwaysConst then CaptureSet (cs1.elems) else cs1, ! actualIsBoxed))
810
800
else
811
- recon(CapturingType (parent1, cs1, actualIsBoxed))
801
+ recon(CapturingType (parent1, if alwaysConst then CaptureSet (cs1.elems) else cs1, actualIsBoxed))
812
802
}
813
803
814
804
var actualw = actual.widenDealias
@@ -827,7 +817,38 @@ class CheckCaptures extends Recheck, SymTransformer:
827
817
else actual
828
818
end adaptBoxed
829
819
820
+ /** Check overrides again, taking capture sets into account.
821
+ * TODO: Can we avoid doing overrides checks twice?
822
+ * We need to do them here since only at this phase CaptureTypes are relevant
823
+ * But maybe we can then elide the check during the RefChecks phase under captureChecking?
824
+ */
825
+ def checkOverrides = new TreeTraverser :
826
+ /** Check subtype with box adaptation.
827
+ * This function is passed to RefChecks to check the compatibility of overriding pairs.
828
+ * @param sym symbol of the field definition that is being checked
829
+ */
830
+ def checkSubtype (sym : Symbol )(tree : Tree , actual : Type , expected : Type )(using Context ): Boolean =
831
+ val expected1 = alignDependentFunction(addOuterRefs(expected, actual), actual.stripCapturing)
832
+ val actual1 =
833
+ val saved = curEnv
834
+ try
835
+ curEnv = Env (sym, nestedInOwner = false , CaptureSet .Var (), isBoxed = false , outer0 = curEnv)
836
+ adaptBoxed(actual, expected1, tree.srcPos, alwaysConst = true ) match
837
+ case tp @ CapturingType (parent, refs) =>
838
+ CapturingType (parent, CaptureSet (refs.elems))
839
+ case tp => tp
840
+ finally curEnv = saved
841
+ actual1 frozen_<:< expected1
842
+
843
+ def traverse (t : Tree )(using Context ) =
844
+ t match
845
+ case t : Template =>
846
+ checkAllOverrides(ctx.owner.asClass, isSubType = sym => (tp1, tp2) => checkSubtype(sym)(t, tp1, tp2))
847
+ case _ =>
848
+ traverseChildren(t)
849
+
830
850
override def checkUnit (unit : CompilationUnit )(using Context ): Unit =
851
+ checkOverrides.traverse(unit.tpdTree)
831
852
Setup (preRecheckPhase, thisPhase, recheckDef)
832
853
.traverse(ctx.compilationUnit.tpdTree)
833
854
// println(i"SETUP:\n${Recheck.addRecheckedTypes.transform(ctx.compilationUnit.tpdTree)}")
0 commit comments