@@ -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,41 +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 ] = {
202
+ def stacked (ts : List [Type ]): List [Type ] = ts match {
203
+ case t :: ts1 =>
204
+ val ts2 = stacked(ts1.filterNot(po(_, t)))
205
+ if (ts2.exists(po(t, _))) ts2 else t :: ts2
206
+ case Nil => Nil
207
+ }
208
+
209
+ // loop thru tails, filtering for survivors of po test with the current element, which is saved for later culling
201
210
@ tailrec
202
- def loop (remaining : List [Type ], hs : List [Type ]): List [Type ] = remaining match {
211
+ def loop (survivors : List [Type ], toCull : List [Type ]): List [Type ] = survivors match {
203
212
case h :: rest =>
204
- loop(rest.filterNot(po(_, h)), h :: hs )
213
+ loop(rest.filterNot(po(_, h)), h :: toCull )
205
214
case _ =>
206
- def sieve (res : List [Type ], todo : List [Type ]): List [Type ] = todo match {
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 {
207
217
case h :: tail =>
208
218
val res1 = if (res.exists(po(h, _))) res else h :: res
209
219
sieve(res1, tail)
210
220
case _ => res
211
221
}
212
- sieve(Nil , hs)
222
+ toCull match {
223
+ case _ :: Nil => toCull
224
+ case _ => sieve(Nil , toCull)
225
+ }
213
226
}
214
227
215
- // The order here matters because type variables and
216
- // wildcards can act both as subtypes and supertypes.
217
- val (wilds, ts1) = partitionConserve(ts)(isWildCardOrNonGroundTypeVarCollector.collect(_).isDefined)
218
-
219
- loop(ts1 ::: wilds, Nil )
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)
220
235
}
221
236
222
237
/** Eliminate from list of types all elements which are a supertype
223
238
* of some other element of the list. */
224
239
private def elimSuper (ts : List [Type ]): List [Type ] =
225
- maxTypes(ts)((t1, t2) => t2 <:< t1)
240
+ if (ts.lengthCompare(1 ) <= 0 ) ts
241
+ else maxTypes(ts)((t1, t2) => t2 <:< t1)
226
242
227
243
/** Eliminate from list of types all elements which are a subtype
228
244
* of some other element of the list. */
229
- @ tailrec private def elimSub (ts : List [Type ], depth : Depth ): List [Type ] = {
230
- val ts1 = maxTypes(ts)(isSubType(_, _, depth.decr))
231
- if (ts1.lengthCompare(1 ) <= 0 ) ts1 else {
232
- val ts2 = ts1.mapConserve(t => elimAnonymousClass(t.dealiasWiden))
233
- if (ts1 eq ts2) ts1 else elimSub(ts2, depth)
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
+ }
234
252
}
235
- }
236
253
237
254
/** Does this set of types have the same weak lub as
238
255
* it does regular lub? This is exposed so lub callers
@@ -496,7 +513,7 @@ private[internal] trait GlbLubs {
496
513
val (ts, tparams) = stripExistentialsAndTypeVars(ts0)
497
514
val glbOwner = commonOwner(ts)
498
515
val ts1 = {
499
- val res = mutable. ListBuffer .empty[Type ]
516
+ val res = ListBuffer .empty[Type ]
500
517
def loop (ty : Type ): Unit = ty match {
501
518
case RefinedType (ps, _) => ps.foreach(loop)
502
519
case _ => res += ty
@@ -513,7 +530,7 @@ private[internal] trait GlbLubs {
513
530
def glbsym (proto : Symbol ): Symbol = {
514
531
val prototp = glbThisType.memberInfo(proto)
515
532
val symtypes : List [Type ] = {
516
- val res = mutable. ListBuffer .empty[Type ]
533
+ val res = ListBuffer .empty[Type ]
517
534
ts foreach { t =>
518
535
t.nonPrivateMember(proto.name).alternatives foreach { alt =>
519
536
val mi = glbThisType.memberInfo(alt)
0 commit comments