@@ -15,7 +15,7 @@ package reflect
15
15
package internal
16
16
package tpe
17
17
18
- import scala .collection .mutable
18
+ import scala .collection .mutable , mutable . ListBuffer
19
19
import scala .annotation .tailrec
20
20
import Variance ._
21
21
@@ -101,20 +101,20 @@ private[internal] trait GlbLubs {
101
101
102
102
def headOf (ix : Int ) = baseTypeSeqs(ix).rawElem(ices(ix))
103
103
104
- val pretypes : mutable. ListBuffer [Type ] = mutable. ListBuffer .empty[Type ]
104
+ val pretypes : ListBuffer [Type ] = ListBuffer .empty[Type ]
105
105
106
106
var isFinished = false
107
- while (! isFinished && ices(0 ) < baseTypeSeqs(0 ).length){
107
+ while (! isFinished && ices(0 ) < baseTypeSeqs(0 ).length) {
108
108
lubListDepth = lubListDepth.incr
109
109
// Step 1: run through the List with these variables:
110
110
// 1) Is there any empty list? Are they equal or are we taking the smallest?
111
111
// isFinished: tsBts.exists(typeListIsEmpty)
112
112
// Is the frontier made up of types with the same symbol?
113
- var isUniformFrontier = true
113
+ var isUniformFrontier = true
114
114
var sym = headOf(0 ).typeSymbol
115
115
// var tsYs = tsBts
116
116
var ix = 0
117
- while (! isFinished && ix < baseTypeSeqs.length){
117
+ while (! isFinished && ix < baseTypeSeqs.length) {
118
118
if (ices(ix) == baseTypeSeqs(ix).length)
119
119
isFinished = true
120
120
else {
@@ -130,7 +130,7 @@ private[internal] trait GlbLubs {
130
130
// the invariant holds, i.e., the one that conveys most information regarding subtyping. Before
131
131
// merging, strip targs that refer to bound tparams (when we're computing the lub of type
132
132
// constructors.) Also filter out all types that are a subtype of some other type.
133
- if (! isFinished){
133
+ if (! isFinished) {
134
134
// ts0 is the 1-dimensional frontier of symbols cutting through 2-dimensional tsBts.
135
135
// Invariant: all symbols "under" (closer to the first row) the frontier
136
136
// are smaller (according to _.isLess) than the ones "on and beyond" the frontier
@@ -145,7 +145,7 @@ private[internal] trait GlbLubs {
145
145
}
146
146
147
147
if (isUniformFrontier) {
148
- val ts1 = elimSub(ts0, depth) map elimHigherOrderTypeParam
148
+ val ts1 = elimSub(ts0, depth). map( elimHigherOrderTypeParam)
149
149
mergePrefixAndArgs(ts1, Covariant , depth) match {
150
150
case NoType =>
151
151
case tp => pretypes += tp
@@ -165,11 +165,12 @@ private[internal] trait GlbLubs {
165
165
jx += 1
166
166
}
167
167
if (printLubs) {
168
- val str = baseTypeSeqs.zipWithIndex.map({ case (tps, idx) =>
169
- tps.toList.drop(ices(idx)).map(" " + _ + " \n " ).mkString(" (" + idx + " )\n " , " " , " \n " )
170
- }).mkString(" " )
171
-
172
- println(" Frontier(\n " + str + " )" )
168
+ println {
169
+ baseTypeSeqs.zipWithIndex.map { case (tps, idx) =>
170
+ tps.toList.drop(ices(idx)).map(" " + _).mkString(" (" + idx + " )\n " , " \n " , " \n " )
171
+ }
172
+ .mkString(" Frontier(\n " , " " , " )" )
173
+ }
173
174
printLubMatrixAux(lubListDepth)
174
175
}
175
176
}
@@ -198,36 +199,57 @@ private[internal] trait GlbLubs {
198
199
199
200
/** From a list of types, retain only maximal types as determined by the partial order `po`. */
200
201
private def maxTypes (ts : List [Type ])(po : (Type , Type ) => Boolean ): List [Type ] = {
201
- def loop (ts : List [Type ]): List [Type ] = ts match {
202
+ def stacked (ts : List [Type ]): List [Type ] = ts match {
202
203
case t :: ts1 =>
203
- val ts2 = loop (ts1.filterNot(po(_, t)))
204
+ val ts2 = stacked (ts1.filterNot(po(_, t)))
204
205
if (ts2.exists(po(t, _))) ts2 else t :: ts2
205
206
case Nil => Nil
206
207
}
207
208
208
- // The order here matters because type variables and
209
- // wildcards can act both as subtypes and supertypes.
210
- val (ts2, ts1) = partitionConserve(ts) { tp =>
211
- isWildCardOrNonGroundTypeVarCollector.collect(tp).isDefined
209
+ // loop thru tails, filtering for survivors of po test with the current element, which is saved for later culling
210
+ @ tailrec
211
+ def loop (survivors : List [Type ], toCull : List [Type ]): List [Type ] = survivors match {
212
+ case h :: rest =>
213
+ loop(rest.filterNot(po(_, h)), h :: toCull)
214
+ case _ =>
215
+ // unwind the stack of saved elements, accumulating a result containing elements surviving po (in swapped order)
216
+ def sieve (res : List [Type ], remaining : List [Type ]): List [Type ] = remaining match {
217
+ case h :: tail =>
218
+ val res1 = if (res.exists(po(h, _))) res else h :: res
219
+ sieve(res1, tail)
220
+ case _ => res
221
+ }
222
+ toCull match {
223
+ case _ :: Nil => toCull
224
+ case _ => sieve(Nil , toCull)
225
+ }
212
226
}
213
227
214
- loop(ts1 ::: ts2)
228
+ // The order here matters because type variables and wildcards can act both as subtypes and supertypes.
229
+ val sorted = {
230
+ val (wilds, ts1) = partitionConserve(ts)(isWildCardOrNonGroundTypeVarCollector.collect(_).isDefined)
231
+ ts1 ::: wilds
232
+ }
233
+ if (sorted.lengthCompare(5 ) > 0 ) loop(sorted, Nil )
234
+ else stacked(sorted)
215
235
}
216
236
217
237
/** Eliminate from list of types all elements which are a supertype
218
- * of some other element of the list. */
238
+ * of some other element of the list. */
219
239
private def elimSuper (ts : List [Type ]): List [Type ] =
220
- maxTypes(ts)((t1, t2) => t2 <:< t1)
240
+ if (ts.lengthCompare(1 ) <= 0 ) ts
241
+ else maxTypes(ts)((t1, t2) => t2 <:< t1)
221
242
222
243
/** Eliminate from list of types all elements which are a subtype
223
- * of some other element of the list. */
224
- @ tailrec private def elimSub (ts : List [Type ], depth : Depth ): List [Type ] = {
225
- val ts1 = maxTypes(ts)(isSubType(_, _, depth.decr))
226
- if (ts1.lengthCompare(1 ) <= 0 ) ts1 else {
227
- val ts2 = ts1.mapConserve(t => elimAnonymousClass(t.dealiasWiden))
228
- if (ts1 eq ts2) ts1 else elimSub(ts2, depth)
244
+ * of some other element of the list. */
245
+ @ tailrec private def elimSub (ts : List [Type ], depth : Depth ): List [Type ] =
246
+ if (ts.lengthCompare(1 ) <= 0 ) ts else {
247
+ val ts1 = maxTypes(ts)(isSubType(_, _, depth.decr))
248
+ if (ts1.lengthCompare(1 ) <= 0 ) ts1 else {
249
+ val ts2 = ts1.mapConserve(t => elimAnonymousClass(t.dealiasWiden))
250
+ if (ts1 eq ts2) ts1 else elimSub(ts2, depth)
251
+ }
229
252
}
230
- }
231
253
232
254
/** Does this set of types have the same weak lub as
233
255
* it does regular lub? This is exposed so lub callers
@@ -491,7 +513,7 @@ private[internal] trait GlbLubs {
491
513
val (ts, tparams) = stripExistentialsAndTypeVars(ts0)
492
514
val glbOwner = commonOwner(ts)
493
515
val ts1 = {
494
- val res = mutable. ListBuffer .empty[Type ]
516
+ val res = ListBuffer .empty[Type ]
495
517
def loop (ty : Type ): Unit = ty match {
496
518
case RefinedType (ps, _) => ps.foreach(loop)
497
519
case _ => res += ty
@@ -508,7 +530,7 @@ private[internal] trait GlbLubs {
508
530
def glbsym (proto : Symbol ): Symbol = {
509
531
val prototp = glbThisType.memberInfo(proto)
510
532
val symtypes : List [Type ] = {
511
- val res = mutable. ListBuffer .empty[Type ]
533
+ val res = ListBuffer .empty[Type ]
512
534
ts foreach { t =>
513
535
t.nonPrivateMember(proto.name).alternatives foreach { alt =>
514
536
val mi = glbThisType.memberInfo(alt)
0 commit comments