@@ -106,22 +106,32 @@ object Formatting {
106
106
107
107
private type Recorded = AnyRef /* Symbol | ParamRef | SkolemType */
108
108
109
- private class Seen extends mutable.HashMap [String , List [Recorded ]] {
109
+ private case class SeenKey (str : String , isType : Boolean )
110
+ private class Seen extends mutable.HashMap [SeenKey , List [Recorded ]] {
110
111
111
- override def default (key : String ) = Nil
112
+ override def default (key : SeenKey ) = Nil
112
113
113
- def record (str : String , entry : Recorded )(implicit ctx : Context ): String = {
114
+ def record (str : String , isType : Boolean , entry : Recorded )(implicit ctx : Context ): String = {
115
+
116
+ /** If `e1` is an alias of another class of the same name, return the other
117
+ * class symbol instead. This normalization avoids recording e.g. scala.List
118
+ * and scala.collection.immutable.List as two different types
119
+ */
114
120
def followAlias (e1 : Recorded ): Recorded = e1 match {
115
121
case e1 : Symbol if e1.isAliasType =>
116
122
val underlying = e1.typeRef.underlyingClassRef(refinementOK = false ).typeSymbol
117
123
if (underlying.name == e1.name) underlying else e1
118
124
case _ => e1
119
125
}
126
+ val key = SeenKey (str, isType)
127
+ val existing = apply(key)
120
128
lazy val dealiased = followAlias(entry)
121
- var alts = apply(str).dropWhile(alt => dealiased ne followAlias(alt))
129
+
130
+ // alts: The alternatives in `existing` that are equal, or follow (an alias of) `entry`
131
+ var alts = existing.dropWhile(alt => dealiased ne followAlias(alt))
122
132
if (alts.isEmpty) {
123
- alts = entry :: apply(str)
124
- update(str , alts)
133
+ alts = entry :: existing
134
+ update(key , alts)
125
135
}
126
136
str + " '" * (alts.length - 1 )
127
137
}
@@ -135,13 +145,13 @@ object Formatting {
135
145
136
146
override def simpleNameString (sym : Symbol ): String =
137
147
if (useSourceModule(sym)) simpleNameString(sym.sourceModule)
138
- else seen.record(super .simpleNameString(sym), sym)
148
+ else seen.record(super .simpleNameString(sym), sym.isType, sym )
139
149
140
150
override def ParamRefNameString (param : ParamRef ): String =
141
- seen.record(super .ParamRefNameString (param), param)
151
+ seen.record(super .ParamRefNameString (param), param. isInstanceOf [ TypeParamRef ], param )
142
152
143
153
override def toTextRef (tp : SingletonType ): Text = tp match {
144
- case tp : SkolemType => seen.record(tp.repr.toString, tp)
154
+ case tp : SkolemType => seen.record(tp.repr.toString, isType = true , tp)
145
155
case _ => super .toTextRef(tp)
146
156
}
147
157
@@ -207,10 +217,13 @@ object Formatting {
207
217
}
208
218
209
219
val toExplain : List [(String , Recorded )] = seen.toList.flatMap {
210
- case (str, entry :: Nil ) =>
211
- if (needsExplanation(entry)) (str, entry) :: Nil else Nil
212
- case (str, entries) =>
213
- entries.map(alt => (seen.record(str, alt), alt))
220
+ case (key, entry :: Nil ) =>
221
+ if (needsExplanation(entry)) (key.str, entry) :: Nil else Nil
222
+ case (key, entries) =>
223
+ for (alt <- entries) yield {
224
+ val tickedString = seen.record(key.str, key.isType, alt)
225
+ (tickedString, alt)
226
+ }
214
227
}.sortBy(_._1)
215
228
216
229
def columnar (parts : List [(String , String )]): List [String ] = {
0 commit comments