@@ -223,6 +223,9 @@ class CheckCaptures extends Recheck, SymTransformer:
223
223
if tpt.isInstanceOf [InferredTypeTree ] then
224
224
interpolator().traverse(tpt.knownType)
225
225
.showing(i " solved vars in ${tpt.knownType}" , capt)
226
+ for msg <- ccState.approxWarnings do
227
+ report.warning(msg, tpt.srcPos)
228
+ ccState.approxWarnings.clear()
226
229
227
230
/** Assert subcapturing `cs1 <: cs2` */
228
231
def assertSub (cs1 : CaptureSet , cs2 : CaptureSet )(using Context ) =
@@ -492,7 +495,7 @@ class CheckCaptures extends Recheck, SymTransformer:
492
495
tp.derivedCapturingType(forceBox(parent), refs)
493
496
mapArgUsing(forceBox)
494
497
else
495
- super .recheckApply(tree, pt) match
498
+ Existential .toCap( super .recheckApply(tree, pt) ) match
496
499
case appType @ CapturingType (appType1, refs) =>
497
500
tree.fun match
498
501
case Select (qual, _)
@@ -505,7 +508,7 @@ class CheckCaptures extends Recheck, SymTransformer:
505
508
val callCaptures = tree.args.foldLeft(qual.tpe.captureSet): (cs, arg) =>
506
509
cs ++ arg.tpe.captureSet
507
510
appType.derivedCapturingType(appType1, callCaptures)
508
- .showing(i " narrow $tree: $appType, refs = $refs, qual = ${qual.tpe.captureSet} --> $result" , capt)
511
+ .showing(i " narrow $tree: $appType, refs = $refs, qual-cs = ${qual.tpe.captureSet} = $result" , capt)
509
512
case _ => appType
510
513
case appType => appType
511
514
end recheckApply
@@ -591,7 +594,7 @@ class CheckCaptures extends Recheck, SymTransformer:
591
594
i " Sealed type variable $pname" , " be instantiated to" ,
592
595
i " This is often caused by a local capability $where\n leaking as part of its result. " ,
593
596
tree.srcPos)
594
- super .recheckTypeApply(tree, pt)
597
+ Existential .toCap( super .recheckTypeApply(tree, pt) )
595
598
596
599
override def recheckBlock (tree : Block , pt : Type )(using Context ): Type =
597
600
inNestedLevel(super .recheckBlock(tree, pt))
@@ -624,7 +627,12 @@ class CheckCaptures extends Recheck, SymTransformer:
624
627
// Example is the line `a = x` in neg-custom-args/captures/vars.scala.
625
628
// For all other closures, early constraints are preferred since they
626
629
// give more localized error messages.
627
- checkConformsExpr(res, pt, expr)
630
+ val res1 = Existential .toCapDeeply(res)
631
+ val pt1 = Existential .toCapDeeply(pt)
632
+ // We need to open existentials here in order not to get vars mixed up in them
633
+ // We do the proper check with existentials when we are finished with the closure block.
634
+ capt.println(i " pre-check closure $expr of type $res1 against $pt1" )
635
+ checkConformsExpr(res1, pt1, expr)
628
636
recheckDef(mdef, mdef.symbol)
629
637
res
630
638
finally
@@ -1009,35 +1017,50 @@ class CheckCaptures extends Recheck, SymTransformer:
1009
1017
*/
1010
1018
def adaptBoxed (actual : Type , expected : Type , pos : SrcPos , covariant : Boolean , alwaysConst : Boolean , boxErrors : BoxErrors )(using Context ): Type =
1011
1019
1012
- /** Adapt the inner shape type: get the adapted shape type, and the capture set leaked during adaptation
1013
- * @param boxed if true we adapt to a boxed expected type
1014
- */
1015
- def adaptShape (actualShape : Type , boxed : Boolean ): (Type , CaptureSet ) = actualShape match
1016
- case FunctionOrMethod (aargs, ares) =>
1017
- val saved = curEnv
1018
- curEnv = Env (
1019
- curEnv.owner, EnvKind .NestedInOwner ,
1020
- CaptureSet .Var (curEnv.owner, level = currentLevel),
1021
- if boxed then null else curEnv)
1022
- try
1023
- val (eargs, eres) = expected.dealias.stripCapturing match
1024
- case FunctionOrMethod (eargs, eres) => (eargs, eres)
1025
- case _ => (aargs.map(_ => WildcardType ), WildcardType )
1026
- val aargs1 = aargs.zipWithConserve(eargs):
1027
- adaptBoxed(_, _, pos, ! covariant, alwaysConst, boxErrors)
1028
- val ares1 = adaptBoxed(ares, eres, pos, covariant, alwaysConst, boxErrors)
1029
- val resTp =
1030
- if (aargs1 eq aargs) && (ares1 eq ares) then actualShape // optimize to avoid redundant matches
1031
- else actualShape.derivedFunctionOrMethod(aargs1, ares1)
1032
- (resTp, CaptureSet (curEnv.captured.elems))
1033
- finally curEnv = saved
1034
- case _ =>
1035
- (actualShape, CaptureSet ())
1020
+ def recur (actual : Type , expected : Type , covariant : Boolean ): Type =
1021
+
1022
+ /** Adapt the inner shape type: get the adapted shape type, and the capture set leaked during adaptation
1023
+ * @param boxed if true we adapt to a boxed expected type
1024
+ */
1025
+ def adaptShape (actualShape : Type , boxed : Boolean ): (Type , CaptureSet ) = actualShape match
1026
+ case FunctionOrMethod (aargs, ares) =>
1027
+ val saved = curEnv
1028
+ curEnv = Env (
1029
+ curEnv.owner, EnvKind .NestedInOwner ,
1030
+ CaptureSet .Var (curEnv.owner, level = currentLevel),
1031
+ if boxed then null else curEnv)
1032
+ try
1033
+ val (eargs, eres) = expected.dealias.stripCapturing match
1034
+ case FunctionOrMethod (eargs, eres) => (eargs, eres)
1035
+ case _ => (aargs.map(_ => WildcardType ), WildcardType )
1036
+ val aargs1 = aargs.zipWithConserve(eargs):
1037
+ recur(_, _, ! covariant)
1038
+ val ares1 = recur(ares, eres, covariant)
1039
+ val resTp =
1040
+ if (aargs1 eq aargs) && (ares1 eq ares) then actualShape // optimize to avoid redundant matches
1041
+ else actualShape.derivedFunctionOrMethod(aargs1, ares1)
1042
+ (resTp, CaptureSet (curEnv.captured.elems))
1043
+ finally curEnv = saved
1044
+ case _ =>
1045
+ (actualShape, CaptureSet ())
1046
+ end adaptShape
1036
1047
1037
- def adaptStr = i " adapting $actual ${if covariant then " ~~>" else " <~~" } $expected"
1048
+ def adaptStr = i " adapting $actual ${if covariant then " ~~>" else " <~~" } $expected"
1049
+
1050
+ actual match
1051
+ case actual @ Existential (_, actualUnpacked) =>
1052
+ return Existential .derivedExistentialType(actual):
1053
+ recur(actualUnpacked, expected, covariant)
1054
+ case _ =>
1055
+ expected match
1056
+ case expected @ Existential (_, expectedUnpacked) =>
1057
+ return recur(actual, expectedUnpacked, covariant)
1058
+ case _ : WildcardType =>
1059
+ return actual
1060
+ case _ =>
1061
+
1062
+ trace(adaptStr, capt, show = true ) {
1038
1063
1039
- if expected.isInstanceOf [WildcardType ] then actual
1040
- else trace(adaptStr, recheckr, show = true ):
1041
1064
// Decompose the actual type into the inner shape type, the capture set and the box status
1042
1065
val actualShape = if actual.isFromJavaObject then actual else actual.stripCapturing
1043
1066
val actualIsBoxed = actual.isBoxedCapturing
@@ -1099,6 +1122,10 @@ class CheckCaptures extends Recheck, SymTransformer:
1099
1122
adaptedType(! actualIsBoxed)
1100
1123
else
1101
1124
adaptedType(actualIsBoxed)
1125
+ }
1126
+ end recur
1127
+
1128
+ recur(actual, expected, covariant)
1102
1129
end adaptBoxed
1103
1130
1104
1131
/** If actual derives from caps.Capability, yet is not a capturing type itself,
@@ -1139,7 +1166,7 @@ class CheckCaptures extends Recheck, SymTransformer:
1139
1166
widened.withReachCaptures(actual), expected, pos,
1140
1167
covariant = true , alwaysConst = false , boxErrors)
1141
1168
if adapted eq widened then normalized
1142
- else adapted.showing(i " adapt boxed $actual vs $expected ===> $adapted" , capt)
1169
+ else adapted.showing(i " adapt boxed $actual vs $expected = $adapted" , capt)
1143
1170
end adapt
1144
1171
1145
1172
/** Check overrides again, taking capture sets into account.
@@ -1154,13 +1181,13 @@ class CheckCaptures extends Recheck, SymTransformer:
1154
1181
* @param sym symbol of the field definition that is being checked
1155
1182
*/
1156
1183
override def checkSubType (actual : Type , expected : Type )(using Context ): Boolean =
1157
- val expected1 = alignDependentFunction(addOuterRefs(/* Existential.strip */ ( expected) , actual), actual.stripCapturing)
1184
+ val expected1 = alignDependentFunction(addOuterRefs(expected, actual), actual.stripCapturing)
1158
1185
val actual1 =
1159
1186
val saved = curEnv
1160
1187
try
1161
1188
curEnv = Env (clazz, EnvKind .NestedInOwner , capturedVars(clazz), outer0 = curEnv)
1162
1189
val adapted =
1163
- adaptBoxed(/* Existential.strip */ ( actual) , expected1, srcPos, covariant = true , alwaysConst = true , null )
1190
+ adaptBoxed(actual, expected1, srcPos, covariant = true , alwaysConst = true , null )
1164
1191
actual match
1165
1192
case _ : MethodType =>
1166
1193
// We remove the capture set resulted from box adaptation for method types,
0 commit comments