@@ -145,15 +145,16 @@ sealed abstract class CaptureSet extends Showable:
145145
146146 /** x subsumes x
147147 * this subsumes this.f
148- * x subsumes y ==> x* subsumes y
149- * x subsumes y ==> x* subsumes y*
148+ * x subsumes y ==> x* subsumes y, x subsumes y?
149+ * x subsumes y ==> x* subsumes y*, x? subsumes y?
150150 */
151151 extension (x : CaptureRef )
152152 private def subsumes (y : CaptureRef )(using Context ): Boolean =
153153 (x eq y)
154154 || x.isRootCapability
155155 || y.match
156- case y : TermRef => ! y.isReach && (y.prefix eq x)
156+ case y : TermRef => y.prefix eq x
157+ case MaybeCapability (y1) => x.stripMaybe.subsumes(y1)
157158 case _ => false
158159 || x.match
159160 case ReachCapability (x1) => x1.subsumes(y.stripReach)
@@ -312,6 +313,8 @@ sealed abstract class CaptureSet extends Showable:
312313 def substParams (tl : BindingType , to : List [Type ])(using Context ) =
313314 map(Substituters .SubstParamsMap (tl, to))
314315
316+ def maybe (using Context ): CaptureSet = map(MaybeMap ())
317+
315318 /** Invoke handler if this set has (or later aquires) the root capability `cap` */
316319 def disallowRootCapability (handler : () => Context ?=> Unit )(using Context ): this .type =
317320 if isUniversal then handler()
@@ -445,6 +448,8 @@ object CaptureSet:
445448 def isConst = isSolved
446449 def isAlwaysEmpty = false
447450
451+ def isMaybeSet = false // overridden in BiMapped
452+
448453 /** A handler to be invoked if the root reference `cap` is added to this set */
449454 var rootAddedHandler : () => Context ?=> Unit = () => ()
450455
@@ -490,9 +495,10 @@ object CaptureSet:
490495 if elem.isRootCapability then
491496 rootAddedHandler()
492497 newElemAddedHandler(elem)
498+ val normElem = if isMaybeSet then elem else elem.stripMaybe
493499 // assert(id != 5 || elems.size != 3, this)
494500 val res = (CompareResult .OK /: deps): (r, dep) =>
495- r.andAlso(dep.tryInclude(elem , this ))
501+ r.andAlso(dep.tryInclude(normElem , this ))
496502 res.orElse:
497503 elems -= elem
498504 res.addToTrace(this )
@@ -508,6 +514,8 @@ object CaptureSet:
508514 levelLimit.isContainedIn(elem.cls.levelOwner)
509515 case ReachCapability (elem1) =>
510516 levelOK(elem1)
517+ case MaybeCapability (elem1) =>
518+ levelOK(elem1)
511519 case _ =>
512520 true
513521
@@ -760,6 +768,7 @@ object CaptureSet:
760768 if source eq origin then supApprox.map(bimap.inverse)
761769 else source.upperApprox(this ).map(bimap) ** supApprox
762770
771+ override def isMaybeSet : Boolean = bimap.isInstanceOf [MaybeMap ]
763772 override def toString = s " BiMapped $id( $source, elems = $elems) "
764773 end BiMapped
765774
@@ -840,8 +849,7 @@ object CaptureSet:
840849 upper.isAlwaysEmpty || upper.isConst && upper.elems.size == 1 && upper.elems.contains(r1)
841850 if variance > 0 || isExact then upper
842851 else if variance < 0 then CaptureSet .empty
843- else if ctx.mode.is(Mode .Printing ) then upper
844- else assert(false , i " trying to add $upper from $r via ${tm.getClass} in a non-variant setting " )
852+ else upper.maybe
845853
846854 /** Apply `f` to each element in `xs`, and join result sets with `++` */
847855 def mapRefs (xs : Refs , f : CaptureRef => CaptureSet )(using Context ): CaptureSet =
@@ -980,6 +988,26 @@ object CaptureSet:
980988 /** The current VarState, as passed by the implicit context */
981989 def varState (using state : VarState ): VarState = state
982990
991+ /** Maps `x` to `x?` */
992+ private class MaybeMap (using Context ) extends BiTypeMap :
993+
994+ def apply (t : Type ) = t match
995+ case t : CaptureRef if t.isTrackableRef => t.maybe
996+ case _ => mapOver(t)
997+
998+ override def toString = " Maybe"
999+
1000+ lazy val inverse = new BiTypeMap :
1001+
1002+ def apply (t : Type ) = t match
1003+ case t : CaptureRef if t.isMaybe => t.stripMaybe
1004+ case t => mapOver(t)
1005+
1006+ def inverse = MaybeMap .this
1007+
1008+ override def toString = " Maybe.inverse"
1009+ end MaybeMap
1010+
9831011 /* Not needed:
9841012 def ofClass(cinfo: ClassInfo, argTypes: List[Type])(using Context): CaptureSet =
9851013 CaptureSet.empty
0 commit comments