@@ -696,6 +696,13 @@ class CheckCaptures extends Recheck, SymTransformer:
696
696
interpolateVarsIn(tree.tpt)
697
697
curEnv = saved
698
698
699
+ override def recheckRHS (rhs : Tree , pt : Type )(using Context ): Type =
700
+ def avoidMap = new TypeOps .AvoidMap :
701
+ def toAvoid (tp : NamedType ) =
702
+ tp.isTerm && tp.symbol.owner == ctx.owner && ! tp.symbol.is(Param )
703
+ val tp = recheck(rhs, pt)
704
+ if ctx.owner.is(Method ) then avoidMap(tp) else tp
705
+
699
706
/** If val or def definition with inferred (result) type is visible
700
707
* in other compilation units, check that the actual inferred type
701
708
* conforms to the expected type where all inferred capture sets are dropped.
@@ -812,7 +819,8 @@ class CheckCaptures extends Recheck, SymTransformer:
812
819
* Otherwise, if the result type is boxed, simulate an unboxing by
813
820
* adding all references in the boxed capture set to the current environment.
814
821
*/
815
- override def recheck (tree : Tree , pt : Type = WildcardType )(using Context ): Type =
822
+ override def recheck (tree : Tree , pt0 : Type = WildcardType )(using Context ): Type =
823
+ val pt = Existential .openExpected(pt0)
816
824
val saved = curEnv
817
825
tree match
818
826
case _ : RefTree | closureDef(_) if pt.isBoxedCapturing =>
@@ -878,23 +886,24 @@ class CheckCaptures extends Recheck, SymTransformer:
878
886
* where local capture roots are instantiated to root variables.
879
887
*/
880
888
override def checkConformsExpr (actual : Type , expected : Type , tree : Tree , addenda : Addenda )(using Context ): Type =
881
- var expected1 = alignDependentFunction(expected, actual.stripCapturing)
882
- val actualBoxed = adaptBoxed(actual, expected1, tree.srcPos)
889
+ val actualUnpacked = Existential .skolemize(actual)
890
+ var expected1 = alignDependentFunction(expected, actualUnpacked.stripCapturing)
891
+ val actualBoxed = adaptBoxed(actualUnpacked, expected1, tree.srcPos)
883
892
// println(i"check conforms $actualBoxed <<< $expected1")
884
893
885
- if actualBoxed eq actual then
894
+ if actualBoxed eq actualUnpacked then
886
895
// Only `addOuterRefs` when there is no box adaptation
887
- expected1 = addOuterRefs(expected1, actual )
896
+ expected1 = addOuterRefs(expected1, actualUnpacked )
888
897
if isCompatible(actualBoxed, expected1) then
889
898
if debugSuccesses then tree match
890
899
case Ident (_) =>
891
- println(i " SUCCESS $tree: \n ${TypeComparer .explained(_.isSubType(actual , expected))}" )
900
+ println(i " SUCCESS $tree: \n ${TypeComparer .explained(_.isSubType(actualUnpacked , expected))}" )
892
901
case _ =>
893
902
actualBoxed
894
903
else
895
904
capt.println(i " conforms failed for ${tree}: $actual vs $expected" )
896
905
err.typeMismatch(tree.withType(actualBoxed), expected1, addenda ++ CaptureSet .levelErrors)
897
- actual
906
+ actualUnpacked
898
907
end checkConformsExpr
899
908
900
909
/** Turn `expected` into a dependent function when `actual` is dependent. */
@@ -1121,7 +1130,7 @@ class CheckCaptures extends Recheck, SymTransformer:
1121
1130
/** If result derives from caps.Capability, yet is not a capturing type itself,
1122
1131
* make its capture set explicit.
1123
1132
*/
1124
- def makeCaptureSetExplicit (result : Type ) = result match
1133
+ def makeCaptureSetExplicit (actual : Type , result : Type ) = result match
1125
1134
case CapturingType (_, _) => result
1126
1135
case _ =>
1127
1136
if result.derivesFromCapability then
@@ -1147,16 +1156,17 @@ class CheckCaptures extends Recheck, SymTransformer:
1147
1156
case _ =>
1148
1157
case _ =>
1149
1158
val adapted = adapt(actualw.withReachCaptures(actual), expected, covariant = true )
1150
- makeCaptureSetExplicit :
1159
+ makeCaptureSetExplicit(actual,
1151
1160
if adapted ne actualw then
1152
1161
capt.println(i " adapt boxed $actual vs $expected ===> $adapted" )
1153
1162
adapted
1154
1163
else
1155
- actual
1164
+ actual)
1156
1165
end adaptBoxed
1157
1166
1158
1167
/** Check overrides again, taking capture sets into account.
1159
1168
* TODO: Can we avoid doing overrides checks twice?
1169
+ *
1160
1170
* We need to do them here since only at this phase CaptureTypes are relevant
1161
1171
* But maybe we can then elide the check during the RefChecks phase under captureChecking?
1162
1172
*/
@@ -1167,12 +1177,12 @@ class CheckCaptures extends Recheck, SymTransformer:
1167
1177
* @param sym symbol of the field definition that is being checked
1168
1178
*/
1169
1179
override def checkSubType (actual : Type , expected : Type )(using Context ): Boolean =
1170
- val expected1 = alignDependentFunction(addOuterRefs(expected, actual), actual.stripCapturing)
1180
+ val expected1 = alignDependentFunction(addOuterRefs(Existential .strip( expected) , actual), actual.stripCapturing)
1171
1181
val actual1 =
1172
1182
val saved = curEnv
1173
1183
try
1174
1184
curEnv = Env (clazz, EnvKind .NestedInOwner , capturedVars(clazz), outer0 = curEnv)
1175
- val adapted = adaptBoxed(actual, expected1, srcPos, alwaysConst = true )
1185
+ val adapted = adaptBoxed(Existential .strip( actual) , expected1, srcPos, alwaysConst = true )
1176
1186
actual match
1177
1187
case _ : MethodType =>
1178
1188
// We remove the capture set resulted from box adaptation for method types,
0 commit comments