@@ -245,6 +245,13 @@ object CheckCaptures:
245245 * a separation check?
246246 */
247247 def needsSepCheck : Boolean
248+
249+ /** If a tree is an argument for which needsSepCheck is true,
250+ * the actual type of the argument before it was widened to formal.
251+ * The nuType of this argument is the formal parameter type in this case,
252+ * but for error diagnosis it's important to know what the actual type was.
253+ */
254+ def actualType : Type
248255 end CheckerAPI
249256
250257class CheckCaptures extends Recheck , SymTransformer :
@@ -285,11 +292,14 @@ class CheckCaptures extends Recheck, SymTransformer:
285292 */
286293 private val todoAtPostCheck = new mutable.ListBuffer [() => Unit ]
287294
288- /** Trees that will need a separation check because they contain cap */
289- private val sepCheckable = util.EqHashSet [Tree ]()
295+ /** Maps trees that will need a separation check because they contain cap
296+ * to the actual, non-widened type.
297+ */
298+ private val sepCheckable = util.EqHashMap [Tree , Type ]()
290299
291300 extension [T <: Tree ](tree : T )
292301 def needsSepCheck : Boolean = sepCheckable.contains(tree)
302+ def actualType : Type = sepCheckable.getOrElse(tree, NoType )
293303
294304 /** Instantiate capture set variables appearing contra-variantly to their
295305 * upper approximation.
@@ -666,15 +676,13 @@ class CheckCaptures extends Recheck, SymTransformer:
666676 val freshenedFormal = Fresh .fromCap(formal)
667677 val argType = recheck(arg, freshenedFormal)
668678 .showing(i " recheck arg $arg vs $freshenedFormal" , capt)
669- formal match
670- case AnnotatedType (formal1, ann) if ann.symbol == defn.UseAnnot =>
671- // The UseAnnot is added to `formal` by `prepareFunction`
672- capt.println(i " charging deep capture set of $arg: ${argType} = ${argType.deepCaptureSet}" )
673- markFree(argType.deepCaptureSet, arg.srcPos)
674- case _ =>
679+ if formal.hasUseAnnot then
680+ // The @use annotation is added to `formal` by `prepareFunction`
681+ capt.println(i " charging deep capture set of $arg: ${argType} = ${argType.deepCaptureSet}" )
682+ markFree(argType.deepCaptureSet, arg.srcPos)
675683 if formal.containsCap then
676684 arg.updNuType(freshenedFormal)
677- sepCheckable += arg
685+ sepCheckable(arg) = argType
678686 argType
679687
680688 /** Map existential captures in result to `cap` and implement the following
@@ -704,9 +712,7 @@ class CheckCaptures extends Recheck, SymTransformer:
704712 val qualCaptures = qualType.captureSet
705713 val argCaptures =
706714 for (argType, formal) <- argTypes.lazyZip(funType.paramInfos) yield
707- formal match
708- case AnnotatedType (_, ann) if ann.symbol == defn.UseAnnot => argType.deepCaptureSet
709- case _ => argType.captureSet
715+ if formal.hasUseAnnot then argType.deepCaptureSet else argType.captureSet
710716 appType match
711717 case appType @ CapturingType (appType1, refs)
712718 if qualType.exists
0 commit comments