@@ -88,6 +88,8 @@ sealed abstract class CaptureSet extends Showable:
8888 final def isUnboxable (using Context ) =
8989 elems.exists(elem => elem.isRootCapability || Existential .isExistentialVar(elem))
9090
91+ final def keepAlways : Boolean = this .isInstanceOf [EmptyWithProvenance ]
92+
9193 /** Try to include an element in this capture set.
9294 * @param elem The element to be added
9395 * @param origin The set that originated the request, or `empty` if the request came from outside.
@@ -219,7 +221,8 @@ sealed abstract class CaptureSet extends Showable:
219221 * `this` and `that`
220222 */
221223 def ++ (that : CaptureSet )(using Context ): CaptureSet =
222- if this .subCaptures(that, frozen = true ).isOK then that
224+ if this .subCaptures(that, frozen = true ).isOK then
225+ if that.isAlwaysEmpty && this .keepAlways then this else that
223226 else if that.subCaptures(this , frozen = true ).isOK then this
224227 else if this .isConst && that.isConst then Const (this .elems ++ that.elems)
225228 else Union (this , that)
@@ -294,7 +297,7 @@ sealed abstract class CaptureSet extends Showable:
294297 case _ =>
295298 val mapped = mapRefs(elems, tm, tm.variance)
296299 if isConst then
297- if mapped.isConst && mapped.elems == elems then this
300+ if mapped.isConst && mapped.elems == elems && ! mapped.keepAlways then this
298301 else mapped
299302 else Mapped (asVar, tm, tm.variance, mapped)
300303
@@ -398,6 +401,12 @@ object CaptureSet:
398401 override def toString = elems.toString
399402 end Const
400403
404+ case class EmptyWithProvenance (ref : CaptureRef , mapped : Type ) extends Const (SimpleIdentitySet .empty):
405+ override def optionalInfo (using Context ): String =
406+ if ctx.settings.YccDebug .value
407+ then i " under-approximating the result of mapping $ref to $mapped"
408+ else " "
409+
401410 /** A special capture set that gets added to the types of symbols that were not
402411 * themselves capture checked, in order to admit arbitrary corresponding capture
403412 * sets in subcapturing comparisons. Similar to platform types for explicit
@@ -863,7 +872,7 @@ object CaptureSet:
863872 || upper.isConst && upper.elems.size == 1 && upper.elems.contains(r1)
864873 || r.derivesFrom(defn.Caps_CapSet )
865874 if variance > 0 || isExact then upper
866- else if variance < 0 then CaptureSet .empty
875+ else if variance < 0 then CaptureSet .EmptyWithProvenance (r, r1)
867876 else upper.maybe
868877
869878 /** Apply `f` to each element in `xs`, and join result sets with `++` */
0 commit comments