Skip to content

Commit 62975d3

Browse files
committed
heal ill-formed capture sets in type parameters
Given an applied function `f[cs A](g)`, where the type of `f` is `[T] -> (x: {*} C) -> T` and the type of `g` is dependent, e.g. `(x: {*} Cap) -> {x} A`, the reference `x` may be propagate to cs. But this makes `cs A` ill-formed since it is not allowed to mention `{x}`. This sometimes cause soundness problems. We heal this by pushing the capture set of `{x}` into cs.
1 parent f45e083 commit 62975d3

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,24 @@ class CheckCaptures extends Recheck, SymTransformer:
891891
capt.println(i"checked $root with $selfType")
892892
end checkSelfTypes
893893

894+
private def healTypeParamCaptureSet(cs: CaptureSet)(using Context) = {
895+
def avoidParam(tpr: TermParamRef): List[CaptureSet] =
896+
val refs = tpr.binder.paramInfos(tpr.paramNum).captureSet
897+
refs.filter(!_.isInstanceOf[TermParamRef]) :: refs.elems.toList.flatMap {
898+
case tpr: TermParamRef => avoidParam(tpr)
899+
case _ => Nil
900+
}
901+
902+
val widenedSets = cs.elems.toList flatMap {
903+
case tpr: TermParamRef => avoidParam(tpr)
904+
case _ => Nil
905+
}
906+
907+
widenedSets foreach { cs1 =>
908+
cs1.subCaptures(cs, frozen = false)
909+
}
910+
}
911+
894912
/** Perform the following kinds of checks
895913
* - Check all explicitly written capturing types for well-formedness using `checkWellFormedPost`.
896914
* - Check that externally visible `val`s or `def`s have empty capture sets. If not,
@@ -949,6 +967,19 @@ class CheckCaptures extends Recheck, SymTransformer:
949967
}
950968
checkBounds(normArgs, tl)
951969
case _ =>
970+
971+
args foreach { targ =>
972+
val tp = targ.knownType
973+
val tm = new TypeMap with IdempotentCaptRefMap:
974+
def apply(tp: Type): Type =
975+
tp match
976+
case CapturingType(parent, refs) =>
977+
healTypeParamCaptureSet(refs)
978+
mapOver(tp)
979+
case _ =>
980+
mapOver(tp)
981+
tm(tp)
982+
}
952983
case _ =>
953984
}
954985
if !ctx.reporter.errorsReported then

0 commit comments

Comments
 (0)