@@ -12,60 +12,17 @@ import printing._
12
12
13
13
import scala .annotation .internal .sharable
14
14
15
- /** 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
15
+ object GadtConstraint :
16
+ @ sharable val empty =
17
+ new GadtConstraint (OrderingConstraint .empty, SimpleIdentityMap .empty, SimpleIdentityMap .empty, false )
39
18
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
+ /** Represents GADT constraints currently in scope */
20
+ final class GadtConstraint private (
64
21
private var myConstraint : Constraint ,
65
22
private var mapping : SimpleIdentityMap [Symbol , TypeVar ],
66
23
private var reverseMapping : SimpleIdentityMap [TypeParamRef , Symbol ],
67
24
private var wasConstrained : Boolean
68
- ) extends GadtConstraint with ConstraintHandling {
25
+ ) extends ConstraintHandling with Showable {
69
26
import dotty .tools .dotc .config .Printers .{gadts , gadtsConstr }
70
27
71
28
def this () = this (
@@ -77,10 +34,7 @@ final class ProperGadtConstraint private(
77
34
78
35
/** Exposes ConstraintHandling.subsumes */
79
36
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
- }
37
+ def extractConstraint (g : GadtConstraint ) = g.constraint
84
38
subsumes(extractConstraint(left), extractConstraint(right), extractConstraint(pre))
85
39
}
86
40
@@ -89,7 +43,12 @@ final class ProperGadtConstraint private(
89
43
// the case where they're valid, so no approximating is needed.
90
44
rawBound
91
45
92
- override def addToConstraint (params : List [Symbol ])(using Context ): Boolean = {
46
+ /** Add symbols to constraint, correctly handling inter-dependencies.
47
+ *
48
+ * @see [[ConstraintHandling.addToConstraint ]]
49
+ */
50
+ def addToConstraint (sym : Symbol )(using Context ): Boolean = addToConstraint(sym :: Nil )
51
+ def addToConstraint (params : List [Symbol ])(using Context ): Boolean = {
93
52
import NameKinds .DepParamName
94
53
95
54
val poly1 = PolyType (params.map { sym => DepParamName .fresh(sym.name.toTypeName) })(
@@ -138,7 +97,8 @@ final class ProperGadtConstraint private(
138
97
.showing(i " added to constraint: [ $poly1] $params%, % gadt = $this" , gadts)
139
98
}
140
99
141
- override def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(using Context ): Boolean = {
100
+ /** Further constrain a symbol already present in the constraint. */
101
+ def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(using Context ): Boolean = {
142
102
@ annotation.tailrec def stripInternalTypeVar (tp : Type ): Type = tp match {
143
103
case tv : TypeVar =>
144
104
val inst = constraint.instType(tv)
@@ -179,10 +139,16 @@ final class ProperGadtConstraint private(
179
139
result
180
140
}
181
141
182
- override def isLess (sym1 : Symbol , sym2 : Symbol )(using Context ): Boolean =
142
+ /** Is `sym1` ordered to be less than `sym2`? */
143
+ def isLess (sym1 : Symbol , sym2 : Symbol )(using Context ): Boolean =
183
144
constraint.isLess(tvarOrError(sym1).origin, tvarOrError(sym2).origin)
184
145
185
- override def fullBounds (sym : Symbol )(using Context ): TypeBounds | Null =
146
+ /** Full bounds of `sym`, including TypeRefs to other lower/upper symbols.
147
+ *
148
+ * @note this performs subtype checks between ordered symbols.
149
+ * Using this in isSubType can lead to infinite recursion. Consider `bounds` instead.
150
+ */
151
+ def fullBounds (sym : Symbol )(using Context ): TypeBounds | Null =
186
152
mapping(sym) match {
187
153
case null => null
188
154
// TODO: Improve flow typing so that ascription becomes redundant
@@ -191,7 +157,8 @@ final class ProperGadtConstraint private(
191
157
// .ensuring(containsNoInternalTypes(_))
192
158
}
193
159
194
- override def bounds (sym : Symbol )(using Context ): TypeBounds | Null =
160
+ /** Immediate bounds of `sym`. Does not contain lower/upper symbols (see [[fullBounds ]]). */
161
+ def bounds (sym : Symbol )(using Context ): TypeBounds | Null =
195
162
mapping(sym) match {
196
163
case null => null
197
164
// TODO: Improve flow typing so that ascription becomes redundant
@@ -202,11 +169,17 @@ final class ProperGadtConstraint private(
202
169
// .ensuring(containsNoInternalTypes(_))
203
170
}
204
171
205
- override def contains (sym : Symbol )(using Context ): Boolean = mapping(sym) != null
172
+ /** Is the symbol registered in the constraint?
173
+ *
174
+ * @note this is true even if the symbol is constrained to be equal to another type, unlike [[Constraint.contains ]].
175
+ */
176
+ def contains (sym : Symbol )(using Context ): Boolean = mapping(sym) != null
206
177
178
+ /** GADT constraint narrows bounds of at least one variable */
207
179
def isNarrowing : Boolean = wasConstrained
208
180
209
- override def approximation (sym : Symbol , fromBelow : Boolean , maxLevel : Int )(using Context ): Type = {
181
+ /** See [[ConstraintHandling.approximation ]] */
182
+ def approximation (sym : Symbol , fromBelow : Boolean , maxLevel : Int = Int .MaxValue )(using Context ): Type = {
210
183
val res =
211
184
approximation(tvarOrError(sym).origin, fromBelow, maxLevel) match
212
185
case tpr : TypeParamRef =>
@@ -220,23 +193,16 @@ final class ProperGadtConstraint private(
220
193
res
221
194
}
222
195
223
- override def symbols : List [Symbol ] = mapping.keys
196
+ def symbols : List [Symbol ] = mapping.keys
224
197
225
- override def fresh : GadtConstraint = new ProperGadtConstraint (
226
- myConstraint,
227
- mapping,
228
- reverseMapping,
229
- wasConstrained
230
- )
198
+ def fresh : GadtConstraint = new GadtConstraint (myConstraint, mapping, reverseMapping, wasConstrained)
231
199
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
- }
200
+ /** Restore the state from other [[GadtConstraint ]], probably copied using [[fresh ]] */
201
+ def restore (other : GadtConstraint ): Unit =
202
+ this .myConstraint = other.myConstraint
203
+ this .mapping = other.mapping
204
+ this .reverseMapping = other.reverseMapping
205
+ this .wasConstrained = other.wasConstrained
240
206
241
207
// ---- Protected/internal -----------------------------------------------
242
208
@@ -294,30 +260,6 @@ final class ProperGadtConstraint private(
294
260
295
261
override def toText (printer : Printer ): Texts .Text = printer.toText(this )
296
262
297
- override def debugBoundsDescription (using Context ): String = i " $this\n $constraint"
298
- }
299
-
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"
263
+ /** Provides more information than toText, by showing the underlying Constraint details. */
264
+ def debugBoundsDescription (using Context ): String = i " $this\n $constraint"
323
265
}
0 commit comments