Skip to content

Commit 85bd587

Browse files
committed
Allow for possibility that variables are constant
1 parent 092e3bc commit 85bd587

File tree

2 files changed

+33
-28
lines changed

2 files changed

+33
-28
lines changed

compiler/src/dotty/tools/dotc/cc/CaptureSet.scala

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ sealed abstract class CaptureSet extends Showable:
3535
*/
3636
def elems: Refs
3737

38-
/** Is this capture set constant (i.e. not a capture variable)?
38+
/** Is this capture set constant (i.e. not an unsolved capture variable)?
39+
* Solved capture variables count as constant.
3940
*/
4041
def isConst: Boolean
4142

@@ -47,6 +48,11 @@ sealed abstract class CaptureSet extends Showable:
4748
/** Is this capture set definitely non-empty? */
4849
final def isNotEmpty: Boolean = !elems.isEmpty
4950

51+
/** Cast to variable. @pre: @isConst */
52+
def asVar: Var =
53+
assert(!isConst)
54+
asInstanceOf[Var]
55+
5056
/** Add new elements to this capture set if allowed.
5157
* @pre `newElems` is not empty and does not overlap with `this.elems`.
5258
* Constant capture sets never allow to add new elements.
@@ -133,24 +139,22 @@ sealed abstract class CaptureSet extends Showable:
133139
def **(that: CaptureSet)(using Context): CaptureSet =
134140
if this.subCaptures(that, frozen = true) == CompareResult.OK then this
135141
else if that.subCaptures(this, frozen = true) == CompareResult.OK then that
136-
else (this, that) match
137-
case (cs1: Const, cs2: Const) => Const(cs1.elems.intersect(cs2.elems))
138-
case (cs1: Var, cs2) => Intersected(cs1, cs2)
139-
case (cs1, cs2: Var) => Intersected(cs2, cs1)
142+
else if this.isConst && that.isConst then Const(elems.intersect(that.elems))
143+
else if that.isConst then Intersected(this.asVar, that)
144+
else Intersected(that.asVar, this)
140145

141146
def -- (that: CaptureSet.Const)(using Context): CaptureSet =
142147
val elems1 = elems.filter(!that.accountsFor(_))
143148
if elems1.size == elems.size then this
144-
else this match
145-
case cs1: Const => Const(elems1)
146-
case cs1: Var => Diff(cs1, that)
149+
else if this.isConst then Const(elems1)
150+
else Diff(asVar, that)
147151

148152
def - (ref: CaptureRef)(using Context): CaptureSet =
149153
this -- ref.singletonCaptureSet
150154

151-
def filter(p: CaptureRef => Boolean)(using Context): CaptureSet = this match
152-
case cs1: Const => Const(elems.filter(p))
153-
case cs1: Var => Filtered(cs1, p)
155+
def filter(p: CaptureRef => Boolean)(using Context): CaptureSet =
156+
if this.isConst then Const(elems.filter(p))
157+
else Filtered(asVar, p)
154158

155159
/** capture set obtained by applying `f` to all elements of the current capture set
156160
* and joining the results. If the current capture set is a variable, the same
@@ -159,14 +163,12 @@ sealed abstract class CaptureSet extends Showable:
159163
def map(tm: TypeMap)(using Context): CaptureSet = tm match
160164
case tm: BiTypeMap =>
161165
val mappedElems = elems.map(tm.forward)
162-
this match
163-
case cs: Const => Const(mappedElems)
164-
case cs: Var => BiMapped(cs, tm, mappedElems)
166+
if isConst then Const(mappedElems)
167+
else BiMapped(asVar, tm, mappedElems)
165168
case _ =>
166169
val mapped = mapRefs(elems, tm, tm.variance)
167-
this match
168-
case cs: Const => mapped
169-
case cs: Var => Mapped(cs, tm, tm.variance, mapped)
170+
if isConst then mapped
171+
else Mapped(asVar, tm, tm.variance, mapped)
170172

171173
def substParams(tl: BindingType, to: List[Type])(using Context) =
172174
map(Substituters.SubstParamsMap(tl, to))
@@ -227,9 +229,11 @@ object CaptureSet:
227229
varId += 1
228230
varId
229231

232+
private var isSolved: Boolean = false
233+
230234
var elems: Refs = initialElems
231235
var deps: Deps = emptySet
232-
def isConst = false
236+
def isConst = isSolved
233237
def isAlwaysEmpty = false
234238

235239
private def recordElemsState()(using VarState): Boolean =
@@ -249,7 +253,7 @@ object CaptureSet:
249253
deps = state.deps(this)
250254

251255
def addNewElems(newElems: Refs, origin: CaptureSet)(using Context, VarState): CompareResult =
252-
if recordElemsState() then
256+
if !isConst && recordElemsState() then
253257
elems ++= newElems
254258
// assert(id != 2 || elems.size != 2, this)
255259
val depsIt = deps.iterator
@@ -298,12 +302,10 @@ object CaptureSet:
298302
Const(newElems)
299303
val result = super.addNewElems(added.elems, origin)
300304
if result == CompareResult.OK then
301-
added match
302-
case added: Var =>
303-
if added.recordDepsState() then addSub(added)
304-
else CompareResult.fail(this)
305-
case _ =>
306-
result
305+
if added.isConst then result
306+
else if added.asVar.recordDepsState() then { addSub(added); result }
307+
else CompareResult.fail(this)
308+
else result
307309

308310
override def toString = s"Mapped$id($cv, elems = $elems)"
309311
end Mapped
@@ -367,8 +369,10 @@ object CaptureSet:
367369
val OK: Type = Const(emptySet)
368370
def fail(cs: CaptureSet): Type = cs
369371
extension (result: Type)
372+
def isOK: Boolean = result eq OK
370373
def blocking: CaptureSet = result
371374
def show: String = if result == OK then "OK" else result.toString
375+
inline def andAlso(op: => Type) = if result.isOK then op else result
372376

373377
class VarState:
374378
private val elemsMap: util.EqHashMap[Var, Refs] = new util.EqHashMap

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,10 @@ class PlainPrinter(_ctx: Context) extends Printer {
189189
(" <: " ~ toText(bound) provided !bound.isAny)
190190
}.close
191191
case CapturingType(parent, refs, boxed) =>
192-
def refsId = refs match
193-
case refs: CaptureSet.Var if ctx.settings.YccDebug.value => refs.id.toString
194-
case _ => ""
192+
def refsId =
193+
if !refs.isConst && ctx.settings.YccDebug.value
194+
then refs.asVar.id.toString
195+
else ""
195196
def box = Str("box ") provided boxed
196197
if printDebug && !refs.isConst then
197198
changePrec(GlobalPrec)(box ~ s"$refs " ~ toText(parent))

0 commit comments

Comments
 (0)