@@ -88,6 +88,8 @@ sealed abstract class CaptureSet extends Showable:
88
88
final def isUnboxable (using Context ) =
89
89
elems.exists(elem => elem.isRootCapability || Existential .isExistentialVar(elem))
90
90
91
+ final def keepAlways : Boolean = this .isInstanceOf [EmptyWithProvenance ]
92
+
91
93
/** Try to include an element in this capture set.
92
94
* @param elem The element to be added
93
95
* @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:
219
221
* `this` and `that`
220
222
*/
221
223
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
223
226
else if that.subCaptures(this , frozen = true ).isOK then this
224
227
else if this .isConst && that.isConst then Const (this .elems ++ that.elems)
225
228
else Union (this , that)
@@ -294,7 +297,7 @@ sealed abstract class CaptureSet extends Showable:
294
297
case _ =>
295
298
val mapped = mapRefs(elems, tm, tm.variance)
296
299
if isConst then
297
- if mapped.isConst && mapped.elems == elems then this
300
+ if mapped.isConst && mapped.elems == elems && ! mapped.keepAlways then this
298
301
else mapped
299
302
else Mapped (asVar, tm, tm.variance, mapped)
300
303
@@ -398,6 +401,12 @@ object CaptureSet:
398
401
override def toString = elems.toString
399
402
end Const
400
403
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
+
401
410
/** A special capture set that gets added to the types of symbols that were not
402
411
* themselves capture checked, in order to admit arbitrary corresponding capture
403
412
* sets in subcapturing comparisons. Similar to platform types for explicit
@@ -863,7 +872,7 @@ object CaptureSet:
863
872
|| upper.isConst && upper.elems.size == 1 && upper.elems.contains(r1)
864
873
|| r.derivesFrom(defn.Caps_CapSet )
865
874
if variance > 0 || isExact then upper
866
- else if variance < 0 then CaptureSet .empty
875
+ else if variance < 0 then CaptureSet .EmptyWithProvenance (r, r1)
867
876
else upper.maybe
868
877
869
878
/** Apply `f` to each element in `xs`, and join result sets with `++` */
0 commit comments