1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
package dotty.tools
package dotc
package core
import Types._, Contexts._
import util.SimpleMap
import collection.mutable.ListBuffer
import printing.{Printer, Showable}
import printing.Texts._
/** Constraint over undetermined type parameters
* @param map a map from PolyType to the type bounds that constrain the
* polytype's type parameters. A type parameter that does not
* have a constraint is represented by a `NoType` in the corresponding
* array entry.
*/
class Constraint(val map: SimpleMap[PolyType, Array[Type]]) extends AnyVal with Showable {
/** Does the constraint's domain contain the type parameters of `pt`? */
def contains(pt: PolyType): Boolean = map(pt) != null
/** The constraint for given type parameter `param`, or NoType if `param` is not part of
* the constraint domain.
*/
def apply(param: PolyParam): Type = {
val entries = map(param.binder)
if (entries == null) NoType else entries(param.paramNum)
}
/** The constraint for the type parameters of `pt`.
* @pre The polytype's type parameters are contained in the constraint's domain.
*/
def apply(pt: PolyType): Array[Type] = map(pt)
/** A new constraint which is derived from this constraint by adding or replacing
* the entries corresponding to `pt` with `entries`.
*/
def updated(pt: PolyType, entries: Array[Type]) = {
assert(map(pt) != null)
new Constraint(map.updated(pt, entries))
}
/** A new constraint which is derived from this constraint by removing
* the type parameter `param` from the domain.
*/
def - (param: PolyParam)(implicit ctx: Context) = {
val pt = param.binder
val pnum = param.paramNum
val entries = map(pt)
var noneLeft = true
var i = 0
while (noneLeft && (i < entries.length)) {
noneLeft = (entries(i) eq NoType) || i == pnum
i += 1
}
new Constraint(
if (noneLeft) map remove pt
else {
val newEntries = entries.clone
newEntries(pnum) = NoType
map.updated(pt, newEntries)
})
}
def +(pt: PolyType) = {
/*
pt.resultType match {
case MethodType(pname :: rest, _) =>
assert(pname.toString != "__thingToAdd")
case _ =>
}
*/
new Constraint(map.updated(pt, pt.paramBounds.toArray))
}
/** A new constraint which is derived from this constraint by removing
* the type parameter `param` from the domain and replacing all occurrences
* of the parameter elsewhere in the constraint by type `tp`.
*/
def replace(param: PolyParam, tp: Type)(implicit ctx: Context) = {
def subst(entries: Array[Type]) = {
var result = entries
var i = 0
while (i < entries.length) {
entries(i) match {
case oldBounds: TypeBounds =>
val newBounds = oldBounds.substParam(param, tp)
if (oldBounds ne newBounds) {
if (result eq entries) result = entries.clone
result(i) = newBounds
}
case _ =>
}
i += 1
}
result
}
new Constraint((this - param).map mapValues subst)
}
def domainPolys: List[PolyType] = map.keys
def domainParams: List[PolyParam] =
for {
(poly, entries) <- map.toList
n <- 0 until entries.length
if entries(n).exists
} yield PolyParam(poly, n)
def constrainedTypesText(printer: Printer): Text =
Text(domainPolys map (_.toText(printer)), ", ")
def constraintText(indent: Int, printer: Printer): Text = {
val assocs =
for (param <- domainParams)
yield (" " * indent) ~ param.toText(printer) ~ this(param).toText(printer)
Text(assocs, "\n")
}
override def toText(printer: Printer): Text =
"Constraint(" ~ constrainedTypesText(printer) ~ ") {" ~ constraintText(2, printer) ~ "}"
}
|