@@ -696,6 +696,13 @@ class CheckCaptures extends Recheck, SymTransformer:
696696 interpolateVarsIn(tree.tpt)
697697 curEnv = saved
698698
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+
699706 /** If val or def definition with inferred (result) type is visible
700707 * in other compilation units, check that the actual inferred type
701708 * conforms to the expected type where all inferred capture sets are dropped.
@@ -812,7 +819,8 @@ class CheckCaptures extends Recheck, SymTransformer:
812819 * Otherwise, if the result type is boxed, simulate an unboxing by
813820 * adding all references in the boxed capture set to the current environment.
814821 */
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)
816824 val saved = curEnv
817825 tree match
818826 case _ : RefTree | closureDef(_) if pt.isBoxedCapturing =>
@@ -878,23 +886,24 @@ class CheckCaptures extends Recheck, SymTransformer:
878886 * where local capture roots are instantiated to root variables.
879887 */
880888 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)
883892 // println(i"check conforms $actualBoxed <<< $expected1")
884893
885- if actualBoxed eq actual then
894+ if actualBoxed eq actualUnpacked then
886895 // Only `addOuterRefs` when there is no box adaptation
887- expected1 = addOuterRefs(expected1, actual )
896+ expected1 = addOuterRefs(expected1, actualUnpacked )
888897 if isCompatible(actualBoxed, expected1) then
889898 if debugSuccesses then tree match
890899 case Ident (_) =>
891- println(i " SUCCESS $tree: \n ${TypeComparer .explained(_.isSubType(actual , expected))}" )
900+ println(i " SUCCESS $tree: \n ${TypeComparer .explained(_.isSubType(actualUnpacked , expected))}" )
892901 case _ =>
893902 actualBoxed
894903 else
895904 capt.println(i " conforms failed for ${tree}: $actual vs $expected" )
896905 err.typeMismatch(tree.withType(actualBoxed), expected1, addenda ++ CaptureSet .levelErrors)
897- actual
906+ actualUnpacked
898907 end checkConformsExpr
899908
900909 /** Turn `expected` into a dependent function when `actual` is dependent. */
@@ -1121,7 +1130,7 @@ class CheckCaptures extends Recheck, SymTransformer:
11211130 /** If result derives from caps.Capability, yet is not a capturing type itself,
11221131 * make its capture set explicit.
11231132 */
1124- def makeCaptureSetExplicit (result : Type ) = result match
1133+ def makeCaptureSetExplicit (actual : Type , result : Type ) = result match
11251134 case CapturingType (_, _) => result
11261135 case _ =>
11271136 if result.derivesFromCapability then
@@ -1147,16 +1156,17 @@ class CheckCaptures extends Recheck, SymTransformer:
11471156 case _ =>
11481157 case _ =>
11491158 val adapted = adapt(actualw.withReachCaptures(actual), expected, covariant = true )
1150- makeCaptureSetExplicit :
1159+ makeCaptureSetExplicit(actual,
11511160 if adapted ne actualw then
11521161 capt.println(i " adapt boxed $actual vs $expected ===> $adapted" )
11531162 adapted
11541163 else
1155- actual
1164+ actual)
11561165 end adaptBoxed
11571166
11581167 /** Check overrides again, taking capture sets into account.
11591168 * TODO: Can we avoid doing overrides checks twice?
1169+ *
11601170 * We need to do them here since only at this phase CaptureTypes are relevant
11611171 * But maybe we can then elide the check during the RefChecks phase under captureChecking?
11621172 */
@@ -1167,12 +1177,12 @@ class CheckCaptures extends Recheck, SymTransformer:
11671177 * @param sym symbol of the field definition that is being checked
11681178 */
11691179 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)
11711181 val actual1 =
11721182 val saved = curEnv
11731183 try
11741184 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 )
11761186 actual match
11771187 case _ : MethodType =>
11781188 // We remove the capture set resulted from box adaptation for method types,
0 commit comments