Skip to content

Commit ef3192f

Browse files
committed
Add element validation
Add element validation for capture variables. This can be used to disallow * in instances, or to give better error messages if variable bounds are violated.
1 parent 34f155a commit ef3192f

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

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

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,27 @@ package dotty.tools
22
package dotc
33
package core
44

5-
import util.*
65
import Types.*, Symbols.*, Flags.*, Contexts.*, Decorators.*
76
import config.Printers.capt
87
import annotation.threadUnsafe
98
import annotation.internal.sharable
109
import reporting.trace
1110
import printing.{Showable, Printer}
1211
import printing.Texts.*
12+
import util.SimpleIdentitySet
13+
import util.common.alwaysTrue
1314

1415
/** A class for capture sets. Capture sets can be constants or variables.
16+
* Capture sets support inclusion constraints <:< where <:< is subcapturing.
17+
* They also allow mapping with arbitrary functions from elements to capture sets,
18+
* by supporting a monadic flatMap operation. That is, constraints can be
19+
* of one of the following forms
20+
*
21+
* cs1 <:< cs2
22+
* cs1 = ∪ {f(x) | x ∈ cs2}
23+
*
24+
* where the `f`s are arbitrary functions from capture references to capture sets.
25+
* We call the resulting constraint system "monadic set constraints".
1526
*/
1627
sealed abstract class CaptureSet extends Showable:
1728
import CaptureSet.*
@@ -148,7 +159,7 @@ object CaptureSet:
148159
override def toString = elems.toString
149160
end Const
150161

151-
class Var private[CaptureSet] (initialElems: Refs) extends CaptureSet:
162+
class Var private[CaptureSet] (initialElems: Refs, validate: Refs => Boolean = alwaysTrue) extends CaptureSet:
152163
val id =
153164
varId += 1
154165
varId
@@ -158,6 +169,8 @@ object CaptureSet:
158169
def isConst = false
159170
def isEmpty = false
160171

172+
assert(validate(elems))
173+
161174
private def recordState()(using VarState) = varState.get(this) match
162175
case None => varState(this) = elems
163176
case _ =>
@@ -166,7 +179,8 @@ object CaptureSet:
166179
elems = state(this)
167180

168181
def addNewElems(newElems: Refs)(using Context, VarState): Boolean =
169-
deps.forall(_.tryInclude(newElems))
182+
validate(newElems)
183+
&& deps.forall(_.tryInclude(newElems))
170184
&& {
171185
recordState()
172186
elems ++= newElems
@@ -190,13 +204,13 @@ object CaptureSet:
190204
override def toString = s"Mapped$id$elems"
191205
end Mapped
192206

207+
def mapRefs(xs: Refs, f: CaptureRef => CaptureSet)(using Context): CaptureSet =
208+
(empty /: xs)((cs, x) => cs ++ f(x))
209+
193210
type VarState = util.EqHashMap[Var, Refs]
194211

195212
def varState(using state: VarState): VarState = state
196213

197-
def mapRefs(xs: Refs, f: CaptureRef => CaptureSet)(using Context): CaptureSet =
198-
(empty /: xs)((cs, x) => cs ++ f(x))
199-
200214
def ofClass(cinfo: ClassInfo, argTypes: List[Type])(using Context): CaptureSet =
201215
def captureSetOf(tp: Type): CaptureSet = tp match
202216
case tp: TypeRef if tp.symbol.is(ParamAccessor) =>

0 commit comments

Comments
 (0)