@@ -10,77 +10,25 @@ import util.{SimpleIdentitySet, SimpleIdentityMap}
10
10
import collection .mutable
11
11
import printing ._
12
12
13
- import scala .annotation .internal .sharable
13
+ object GadtConstraint :
14
+ def apply (): GadtConstraint = empty
15
+ def empty : GadtConstraint =
16
+ new ProperGadtConstraint (OrderingConstraint .empty, SimpleIdentityMap .empty, SimpleIdentityMap .empty, false )
14
17
15
18
/** Represents GADT constraints currently in scope */
16
- sealed abstract class GadtConstraint extends Showable {
17
- /** Immediate bounds of `sym`. Does not contain lower/upper symbols (see [[fullBounds ]]). */
18
- def bounds (sym : Symbol )(using Context ): TypeBounds | Null
19
-
20
- /** Full bounds of `sym`, including TypeRefs to other lower/upper symbols.
21
- *
22
- * @note this performs subtype checks between ordered symbols.
23
- * Using this in isSubType can lead to infinite recursion. Consider `bounds` instead.
24
- */
25
- def fullBounds (sym : Symbol )(using Context ): TypeBounds | Null
26
-
27
- /** Is `sym1` ordered to be less than `sym2`? */
28
- def isLess (sym1 : Symbol , sym2 : Symbol )(using Context ): Boolean
29
-
30
- /** Add symbols to constraint, correctly handling inter-dependencies.
31
- *
32
- * @see [[ConstraintHandling.addToConstraint ]]
33
- */
34
- def addToConstraint (syms : List [Symbol ])(using Context ): Boolean
35
- def addToConstraint (sym : Symbol )(using Context ): Boolean = addToConstraint(sym :: Nil )
36
-
37
- /** Further constrain a symbol already present in the constraint. */
38
- def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(using Context ): Boolean
39
-
40
- /** Is the symbol registered in the constraint?
41
- *
42
- * @note this is true even if the symbol is constrained to be equal to another type, unlike [[Constraint.contains ]].
43
- */
44
- def contains (sym : Symbol )(using Context ): Boolean
45
-
46
- /** GADT constraint narrows bounds of at least one variable */
47
- def isNarrowing : Boolean
48
-
49
- /** See [[ConstraintHandling.approximation ]] */
50
- def approximation (sym : Symbol , fromBelow : Boolean , maxLevel : Int = Int .MaxValue )(using Context ): Type
51
-
52
- def symbols : List [Symbol ]
53
-
54
- def fresh : GadtConstraint
55
-
56
- /** Restore the state from other [[GadtConstraint ]], probably copied using [[fresh ]] */
57
- def restore (other : GadtConstraint ): Unit
58
-
59
- /** Provides more information than toText, by showing the underlying Constraint details. */
60
- def debugBoundsDescription (using Context ): String
61
- }
62
-
63
- final class ProperGadtConstraint private (
19
+ sealed trait GadtConstraint (
64
20
private var myConstraint : Constraint ,
65
21
private var mapping : SimpleIdentityMap [Symbol , TypeVar ],
66
22
private var reverseMapping : SimpleIdentityMap [TypeParamRef , Symbol ],
67
23
private var wasConstrained : Boolean
68
- ) extends GadtConstraint with ConstraintHandling {
69
- import dotty . tools . dotc . config . Printers .{ gadts , gadtsConstr }
24
+ ) extends Showable {
25
+ this : ConstraintHandling =>
70
26
71
- def this () = this (
72
- myConstraint = new OrderingConstraint (SimpleIdentityMap .empty, SimpleIdentityMap .empty, SimpleIdentityMap .empty, SimpleIdentitySet .empty),
73
- mapping = SimpleIdentityMap .empty,
74
- reverseMapping = SimpleIdentityMap .empty,
75
- wasConstrained = false
76
- )
27
+ import dotty .tools .dotc .config .Printers .{gadts , gadtsConstr }
77
28
78
29
/** Exposes ConstraintHandling.subsumes */
79
30
def subsumes (left : GadtConstraint , right : GadtConstraint , pre : GadtConstraint )(using Context ): Boolean = {
80
- def extractConstraint (g : GadtConstraint ) = g match {
81
- case s : ProperGadtConstraint => s.constraint
82
- case EmptyGadtConstraint => OrderingConstraint .empty
83
- }
31
+ def extractConstraint (g : GadtConstraint ) = g.constraint
84
32
subsumes(extractConstraint(left), extractConstraint(right), extractConstraint(pre))
85
33
}
86
34
@@ -89,7 +37,12 @@ final class ProperGadtConstraint private(
89
37
// the case where they're valid, so no approximating is needed.
90
38
rawBound
91
39
92
- override def addToConstraint (params : List [Symbol ])(using Context ): Boolean = {
40
+ /** Add symbols to constraint, correctly handling inter-dependencies.
41
+ *
42
+ * @see [[ConstraintHandling.addToConstraint ]]
43
+ */
44
+ def addToConstraint (sym : Symbol )(using Context ): Boolean = addToConstraint(sym :: Nil )
45
+ def addToConstraint (params : List [Symbol ])(using Context ): Boolean = {
93
46
import NameKinds .DepParamName
94
47
95
48
val poly1 = PolyType (params.map { sym => DepParamName .fresh(sym.name.toTypeName) })(
@@ -138,7 +91,8 @@ final class ProperGadtConstraint private(
138
91
.showing(i " added to constraint: [ $poly1] $params%, % gadt = $this" , gadts)
139
92
}
140
93
141
- override def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(using Context ): Boolean = {
94
+ /** Further constrain a symbol already present in the constraint. */
95
+ def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(using Context ): Boolean = {
142
96
@ annotation.tailrec def stripInternalTypeVar (tp : Type ): Type = tp match {
143
97
case tv : TypeVar =>
144
98
val inst = constraint.instType(tv)
@@ -179,10 +133,16 @@ final class ProperGadtConstraint private(
179
133
result
180
134
}
181
135
182
- override def isLess (sym1 : Symbol , sym2 : Symbol )(using Context ): Boolean =
136
+ /** Is `sym1` ordered to be less than `sym2`? */
137
+ def isLess (sym1 : Symbol , sym2 : Symbol )(using Context ): Boolean =
183
138
constraint.isLess(tvarOrError(sym1).origin, tvarOrError(sym2).origin)
184
139
185
- override def fullBounds (sym : Symbol )(using Context ): TypeBounds | Null =
140
+ /** Full bounds of `sym`, including TypeRefs to other lower/upper symbols.
141
+ *
142
+ * @note this performs subtype checks between ordered symbols.
143
+ * Using this in isSubType can lead to infinite recursion. Consider `bounds` instead.
144
+ */
145
+ def fullBounds (sym : Symbol )(using Context ): TypeBounds | Null =
186
146
mapping(sym) match {
187
147
case null => null
188
148
// TODO: Improve flow typing so that ascription becomes redundant
@@ -191,7 +151,8 @@ final class ProperGadtConstraint private(
191
151
// .ensuring(containsNoInternalTypes(_))
192
152
}
193
153
194
- override def bounds (sym : Symbol )(using Context ): TypeBounds | Null =
154
+ /** Immediate bounds of `sym`. Does not contain lower/upper symbols (see [[fullBounds ]]). */
155
+ def bounds (sym : Symbol )(using Context ): TypeBounds | Null =
195
156
mapping(sym) match {
196
157
case null => null
197
158
// TODO: Improve flow typing so that ascription becomes redundant
@@ -202,11 +163,17 @@ final class ProperGadtConstraint private(
202
163
// .ensuring(containsNoInternalTypes(_))
203
164
}
204
165
205
- override def contains (sym : Symbol )(using Context ): Boolean = mapping(sym) != null
166
+ /** Is the symbol registered in the constraint?
167
+ *
168
+ * @note this is true even if the symbol is constrained to be equal to another type, unlike [[Constraint.contains ]].
169
+ */
170
+ def contains (sym : Symbol )(using Context ): Boolean = mapping(sym) != null
206
171
172
+ /** GADT constraint narrows bounds of at least one variable */
207
173
def isNarrowing : Boolean = wasConstrained
208
174
209
- override def approximation (sym : Symbol , fromBelow : Boolean , maxLevel : Int )(using Context ): Type = {
175
+ /** See [[ConstraintHandling.approximation ]] */
176
+ def approximation (sym : Symbol , fromBelow : Boolean , maxLevel : Int = Int .MaxValue )(using Context ): Type = {
210
177
val res =
211
178
approximation(tvarOrError(sym).origin, fromBelow, maxLevel) match
212
179
case tpr : TypeParamRef =>
@@ -220,23 +187,16 @@ final class ProperGadtConstraint private(
220
187
res
221
188
}
222
189
223
- override def symbols : List [Symbol ] = mapping.keys
224
-
225
- override def fresh : GadtConstraint = new ProperGadtConstraint (
226
- myConstraint,
227
- mapping,
228
- reverseMapping,
229
- wasConstrained
230
- )
231
-
232
- def restore (other : GadtConstraint ): Unit = other match {
233
- case other : ProperGadtConstraint =>
234
- this .myConstraint = other.myConstraint
235
- this .mapping = other.mapping
236
- this .reverseMapping = other.reverseMapping
237
- this .wasConstrained = other.wasConstrained
238
- case _ => ;
239
- }
190
+ def symbols : List [Symbol ] = mapping.keys
191
+
192
+ def fresh : GadtConstraint = new ProperGadtConstraint (myConstraint, mapping, reverseMapping, wasConstrained)
193
+
194
+ /** Restore the state from other [[GadtConstraint ]], probably copied using [[fresh ]] */
195
+ def restore (other : GadtConstraint ): Unit =
196
+ this .myConstraint = other.myConstraint
197
+ this .mapping = other.mapping
198
+ this .reverseMapping = other.reverseMapping
199
+ this .wasConstrained = other.wasConstrained
240
200
241
201
// ---- Protected/internal -----------------------------------------------
242
202
@@ -294,30 +254,13 @@ final class ProperGadtConstraint private(
294
254
295
255
override def toText (printer : Printer ): Texts .Text = printer.toText(this )
296
256
297
- override def debugBoundsDescription (using Context ): String = i " $this\n $constraint"
257
+ /** Provides more information than toText, by showing the underlying Constraint details. */
258
+ def debugBoundsDescription (using Context ): String = i " $this\n $constraint"
298
259
}
299
260
300
- @ sharable object EmptyGadtConstraint extends GadtConstraint {
301
- override def bounds (sym : Symbol )(using Context ): TypeBounds | Null = null
302
- override def fullBounds (sym : Symbol )(using Context ): TypeBounds | Null = null
303
-
304
- override def isLess (sym1 : Symbol , sym2 : Symbol )(using Context ): Boolean = unsupported(" EmptyGadtConstraint.isLess" )
305
-
306
- override def isNarrowing : Boolean = false
307
-
308
- override def contains (sym : Symbol )(using Context ) = false
309
-
310
- override def addToConstraint (params : List [Symbol ])(using Context ): Boolean = unsupported(" EmptyGadtConstraint.addToConstraint" )
311
- override def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(using Context ): Boolean = unsupported(" EmptyGadtConstraint.addBound" )
312
-
313
- override def approximation (sym : Symbol , fromBelow : Boolean , maxLevel : Int )(using Context ): Type = unsupported(" EmptyGadtConstraint.approximation" )
314
-
315
- override def symbols : List [Symbol ] = Nil
316
-
317
- override def fresh = new ProperGadtConstraint
318
- override def restore (other : GadtConstraint ): Unit =
319
- assert(! other.isNarrowing, " cannot restore a non-empty GADTMap" )
320
-
321
- override def toText (printer : Printer ): Texts .Text = printer.toText(this )
322
- override def debugBoundsDescription (using Context ): String = i " $this"
323
- }
261
+ private class ProperGadtConstraint (
262
+ myConstraint : Constraint ,
263
+ mapping : SimpleIdentityMap [Symbol , TypeVar ],
264
+ reverseMapping : SimpleIdentityMap [TypeParamRef , Symbol ],
265
+ wasConstrained : Boolean ,
266
+ ) extends ConstraintHandling with GadtConstraint (myConstraint, mapping, reverseMapping, wasConstrained)
0 commit comments