@@ -238,6 +238,16 @@ class CheckCaptures extends Recheck, SymTransformer:
238
238
else i " references $cs1 are not all "
239
239
report.error(i " $header included in allowed capture set ${res.blocking}" , pos)
240
240
241
+ /** A specialized implementation of the selection rule.
242
+ *
243
+ * E |- f: Cf { m: Cr R }
244
+ * ------------------------
245
+ * E |- f.m: C R
246
+ *
247
+ * The implementation picks as `C` one of `{f}` or `Cr`, depending on the
248
+ * outcome of a `mightSubcapture` test. It picks `{f}` if this might subcapture Cr
249
+ * and Cr otherwise.
250
+ */
241
251
override def recheckSelection (tree : Select , qualType : Type , name : Name )(using Context ) = {
242
252
val selType = super .recheckSelection(tree, qualType, name)
243
253
val selCs = selType.widen.captureSet
@@ -395,18 +405,16 @@ class CheckCaptures extends Recheck, SymTransformer:
395
405
finally curEnv = curEnv.outer
396
406
recheckFinish(result, arg, pt)
397
407
398
- /** A specialized implementation of the apply rule from https://github.com/lampepfl/dotty/discussions/14387:
408
+ /** A specialized implementation of the apply rule.
399
409
*
400
- * E |- f: Cf (Ra -> Cr Rr)
401
- * E |- a: Ra
402
- * ------------------------
403
- * E |- f a: Cr /\ {f} Rr
410
+ * E |- f: Cf (Ra -> Cr Rr)
411
+ * E |- a: Ra
412
+ * ------------------------
413
+ * E |- f a: C Rr
404
414
*
405
- * Specialized for the case where `f` is a tracked and the arguments are pure.
406
- * This replaces the previous rule #13657 while still allowing the code in pos/lazylists1.scala.
407
- * We could consider generalizing to the case where the function arguments have non-empty
408
- * capture sets as suggested in #14387, but that would make capture set computations more complex,
409
- * so we should also evaluate the performance impact.
415
+ * The implementation picks as `C` one of `{f, a}` or `Cr`, depending on the
416
+ * outcome of a `mightSubcapture` test. It picks `{f, a}` if this might subcapture Cr
417
+ * and Cr otherwise.
410
418
*/
411
419
override def recheckApply (tree : Apply , pt : Type )(using Context ): Type =
412
420
includeCallCaptures(tree.symbol, tree.srcPos)
@@ -415,10 +423,11 @@ class CheckCaptures extends Recheck, SymTransformer:
415
423
tree.fun match
416
424
case Select (qual, nme.apply)
417
425
if defn.isFunctionType(qual.tpe.widen)
418
- && tree.args.forall(_.tpe.captureSet.isAlwaysEmpty)
419
426
&& qual.tpe.captureSet.mightSubcapture(refs)
427
+ && tree.args.forall(_.tpe.captureSet.mightSubcapture(refs))
420
428
=>
421
- tp.derivedCapturingType(tp1, qual.tpe.captureSet)
429
+ tp.derivedCapturingType(tp1, tree.args.foldLeft(qual.tpe.captureSet)((cs, arg) =>
430
+ cs ++ arg.tpe.captureSet))
422
431
.showing(i " narrow $tree: $tp --> $result" , capt)
423
432
case _ => tp
424
433
case tp => tp
0 commit comments