@@ -106,22 +106,32 @@ object Formatting {
106106
107107 private type Recorded = AnyRef /* Symbol | ParamRef | SkolemType */
108108
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 ]] {
110111
111- override def default (key : String ) = Nil
112+ override def default (key : SeenKey ) = Nil
112113
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+ */
114120 def followAlias (e1 : Recorded ): Recorded = e1 match {
115121 case e1 : Symbol if e1.isAliasType =>
116122 val underlying = e1.typeRef.underlyingClassRef(refinementOK = false ).typeSymbol
117123 if (underlying.name == e1.name) underlying else e1
118124 case _ => e1
119125 }
126+ val key = SeenKey (str, isType)
127+ val existing = apply(key)
120128 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))
122132 if (alts.isEmpty) {
123- alts = entry :: apply(str)
124- update(str , alts)
133+ alts = entry :: existing
134+ update(key , alts)
125135 }
126136 str + " '" * (alts.length - 1 )
127137 }
@@ -135,13 +145,13 @@ object Formatting {
135145
136146 override def simpleNameString (sym : Symbol ): String =
137147 if (useSourceModule(sym)) simpleNameString(sym.sourceModule)
138- else seen.record(super .simpleNameString(sym), sym)
148+ else seen.record(super .simpleNameString(sym), sym.isType, sym )
139149
140150 override def ParamRefNameString (param : ParamRef ): String =
141- seen.record(super .ParamRefNameString (param), param)
151+ seen.record(super .ParamRefNameString (param), param. isInstanceOf [ TypeParamRef ], param )
142152
143153 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)
145155 case _ => super .toTextRef(tp)
146156 }
147157
@@ -207,10 +217,13 @@ object Formatting {
207217 }
208218
209219 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+ }
214227 }.sortBy(_._1)
215228
216229 def columnar (parts : List [(String , String )]): List [String ] = {
0 commit comments