@@ -463,8 +463,8 @@ class CheckCaptures extends Recheck, SymTransformer:
463463
464464 /** A specialized implementation of the selection rule.
465465 *
466- * E |- f: f { m: Cr R }^Cf
467- * -----------------------
466+ * E |- f: T { m: R^ Cr }^{f}
467+ * ------------------------
468468 * E |- f.m: R^C
469469 *
470470 * The implementation picks as `C` one of `{f}` or `Cr`, depending on the
@@ -507,17 +507,6 @@ class CheckCaptures extends Recheck, SymTransformer:
507507 selType
508508 }// .showing(i"recheck sel $tree, $qualType = $result")
509509
510- /** A specialized implementation of the apply rule.
511- *
512- * E |- f: Ra ->Cf Rr^Cr
513- * E |- a: Ra^Ca
514- * ---------------------
515- * E |- f a: Rr^C
516- *
517- * The implementation picks as `C` one of `{f, a}` or `Cr`, depending on the
518- * outcome of a `mightSubcapture` test. It picks `{f, a}` if this might subcapture Cr
519- * and Cr otherwise.
520- */
521510 override def recheckApply (tree : Apply , pt : Type )(using Context ): Type =
522511 val meth = tree.fun.symbol
523512
@@ -552,31 +541,47 @@ class CheckCaptures extends Recheck, SymTransformer:
552541 tp.derivedCapturingType(forceBox(parent), refs)
553542 mapArgUsing(forceBox)
554543 else
555- handleCall(meth, tree, () => Existential .toCap(super .recheckApply(tree, pt))) match
556- case appType @ CapturingType (appType1, refs) =>
557- tree.fun match
558- case Select (qual, _)
559- if ! tree.fun.symbol.isConstructor
560- && ! qual.tpe.isBoxedCapturing
561- && ! tree.args.exists(_.tpe.isBoxedCapturing)
562- && qual.tpe.captureSet.mightSubcapture(refs)
563- && tree.args.forall(_.tpe.captureSet.mightSubcapture(refs))
564- =>
565- val callCaptures = tree.args.foldLeft(qual.tpe.captureSet): (cs, arg) =>
566- cs ++ arg.tpe.captureSet
567- appType.derivedCapturingType(appType1, callCaptures)
568- .showing(i " narrow $tree: $appType, refs = $refs, qual-cs = ${qual.tpe.captureSet} = $result" , capt)
569- case _ => appType
570- case appType => appType
544+ handleCall(meth, tree, () => super .recheckApply(tree, pt))
571545 end recheckApply
572546
573- override def recheckArg (arg : Tree , formal : Type )(using Context ): Type =
547+ protected override
548+ def recheckArg (arg : Tree , formal : Type )(using Context ): Type =
574549 val argType = recheck(arg, formal)
575550 if unboxedArgs.remove(arg) && ccConfig.useUnboxedParams then
576551 capt.println(i " charging deep capture set of $arg: ${argType} = ${CaptureSet .deepCaptureSet(argType)}" )
577552 markFree(CaptureSet .deepCaptureSet(argType), arg.srcPos)
578553 argType
579554
555+ /** A specialized implementation of the apply rule.
556+ *
557+ * E |- f: Ra ->Cf Rr^Cr
558+ * E |- a: Ra^Ca
559+ * ---------------------
560+ * E |- f a: Rr^C
561+ *
562+ * The implementation picks as `C` one of `{f, a}` or `Cr`, depending on the
563+ * outcome of a `mightSubcapture` test. It picks `{f, a}` if this might subcapture Cr
564+ * and Cr otherwise.
565+ */
566+ protected override
567+ def recheckApplication (tree : Apply , qualType : Type , funType : MethodType , argTypes : List [Type ])(using Context ): Type =
568+ Existential .toCap(super .recheckApplication(tree, qualType, funType, argTypes)) match
569+ case appType @ CapturingType (appType1, refs)
570+ if qualType.exists
571+ && ! tree.fun.symbol.isConstructor
572+ && ! qualType.isBoxedCapturing // TODO: This is not strng enough, we also have
573+ // to exclude existentials in function results
574+ && ! argTypes.exists(_.isBoxedCapturing)
575+ && qualType.captureSet.mightSubcapture(refs)
576+ && argTypes.forall(_.captureSet.mightSubcapture(refs))
577+ =>
578+ val callCaptures = tree.args.foldLeft(qualType.captureSet): (cs, arg) =>
579+ cs ++ arg.tpe.captureSet
580+ appType.derivedCapturingType(appType1, callCaptures)
581+ .showing(i " narrow $tree: $appType, refs = $refs, qual-cs = ${qualType.captureSet} = $result" , capt)
582+ case appType =>
583+ appType
584+
580585 private def isDistinct (xs : List [Type ]): Boolean = xs match
581586 case x :: xs1 => xs1.isEmpty || ! xs1.contains(x) && isDistinct(xs1)
582587 case Nil => true
0 commit comments