@@ -1032,9 +1032,9 @@ class CheckCaptures extends Recheck, SymTransformer:
1032
1032
* that this type parameter can't see.
1033
1033
* For example, when capture checking the following expression:
1034
1034
*
1035
- * def usingLogFile[T](op: (f: {cap} File) => T): T = ...
1035
+ * def usingLogFile[T](op: File^ => T): T = ...
1036
1036
*
1037
- * usingLogFile[box ?1 () -> Unit] { (f: {cap} File) => () => { f.write(0) } }
1037
+ * usingLogFile[box ?1 () -> Unit] { (f: File^ ) => () => { f.write(0) } }
1038
1038
*
1039
1039
* We may propagate `f` into ?1, making ?1 ill-formed.
1040
1040
* This also causes soundness issues, since `f` in ?1 should be widened to `cap`,
@@ -1046,34 +1046,26 @@ class CheckCaptures extends Recheck, SymTransformer:
1046
1046
*/
1047
1047
private def healTypeParam (tree : Tree )(using Context ): Unit =
1048
1048
val checker = new TypeTraverser :
1049
+ private var allowed : SimpleIdentitySet [TermParamRef ] = SimpleIdentitySet .empty
1050
+
1049
1051
private def isAllowed (ref : CaptureRef ): Boolean = ref match
1050
1052
case ref : TermParamRef => allowed.contains(ref)
1051
1053
case _ => true
1052
1054
1053
- // Widen the given term parameter refs x₁ : C₁ S₁ , ⋯ , xₙ : Cₙ Sₙ to their capture sets C₁ , ⋯ , Cₙ.
1054
- //
1055
- // If in these capture sets there are any capture references that are term parameter references we should avoid,
1056
- // we will widen them recursively.
1057
- private def widenParamRefs (refs : List [TermParamRef ]): List [CaptureSet ] =
1058
- @ scala.annotation.tailrec
1059
- def recur (todos : List [TermParamRef ], acc : List [CaptureSet ]): List [CaptureSet ] =
1060
- todos match
1061
- case Nil => acc
1062
- case ref :: rem =>
1063
- val cs = ref.captureSetOfInfo
1064
- val nextAcc = cs.filter(isAllowed(_)) :: acc
1065
- val nextRem : List [TermParamRef ] = (cs.elems.toList.filter(! isAllowed(_)) ++ rem).asInstanceOf
1066
- recur(nextRem, nextAcc)
1067
- recur(refs, Nil )
1068
-
1069
1055
private def healCaptureSet (cs : CaptureSet ): Unit =
1070
- def avoidance (elems : List [CaptureRef ])(using Context ): Unit =
1071
- val toInclude = widenParamRefs(elems.filter(! isAllowed(_)).asInstanceOf )
1072
- // println(i"HEAL $cs by widening to $toInclude")
1073
- toInclude.foreach(checkSubset(_, cs, tree.srcPos))
1074
- cs.ensureWellformed(avoidance)
1075
-
1076
- private var allowed : SimpleIdentitySet [TermParamRef ] = SimpleIdentitySet .empty
1056
+ cs.ensureWellformed: elems =>
1057
+ ctx ?=>
1058
+ var seen = new util.HashSet [CaptureRef ]
1059
+ def recur (elems : List [CaptureRef ]): Unit =
1060
+ for ref <- elems do
1061
+ if ! isAllowed(ref) && ! seen.contains(ref) then
1062
+ seen += ref
1063
+ val widened = ref.captureSetOfInfo
1064
+ val added = widened.filter(isAllowed(_))
1065
+ capt.println(i " heal $ref in $cs by widening to $added" )
1066
+ checkSubset(added, cs, tree.srcPos)
1067
+ recur(widened.elems.toList)
1068
+ recur(elems)
1077
1069
1078
1070
def traverse (tp : Type ) =
1079
1071
tp match
0 commit comments