Skip to content

Commit 5cdc65c

Browse files
committed
Better printing of variant types with wildcard arguments.
We used to approximate these by their bounds, but this is confusing. See comment in printbounds.scala.
1 parent 2a4c4e4 commit 5cdc65c

File tree

3 files changed

+31
-6
lines changed

3 files changed

+31
-6
lines changed

src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,9 @@ class TypeApplications(val self: Type) extends AnyVal {
290290
/** If this is an encoding of a (partially) applied type, return its arguments,
291291
* otherwise return Nil.
292292
* Existential types in arguments are returned as TypeBounds instances.
293+
* @param interpolate See argInfo
293294
*/
294-
final def argInfos(implicit ctx: Context): List[Type] = {
295+
final def argInfos(interpolate: Boolean)(implicit ctx: Context): List[Type] = {
295296
var tparams: List[TypeSymbol] = null
296297
def recur(tp: Type, refineCount: Int): mutable.ListBuffer[Type] = tp.stripTypeVar match {
297298
case tp @ RefinedType(tycon, name) =>
@@ -301,7 +302,7 @@ class TypeApplications(val self: Type) extends AnyVal {
301302
if (tparams == null) tparams = tycon.typeParams
302303
if (buf.size < tparams.length) {
303304
val tparam = tparams(buf.size)
304-
if (name == tparam.name) buf += tp.refinedInfo.argInfo(tparam)
305+
if (name == tparam.name) buf += tp.refinedInfo.argInfo(tparam, interpolate)
305306
else null
306307
} else null
307308
}
@@ -313,6 +314,8 @@ class TypeApplications(val self: Type) extends AnyVal {
313314
if (buf == null) Nil else buf.toList
314315
}
315316

317+
final def argInfos(implicit ctx: Context): List[Type] = argInfos(interpolate = true)
318+
316319
/** Argument types where existential types in arguments are disallowed */
317320
def argTypes(implicit ctx: Context) = argInfos mapConserve noBounds
318321

@@ -335,16 +338,27 @@ class TypeApplications(val self: Type) extends AnyVal {
335338

336339
/** If this is the image of a type argument to type parameter `tparam`,
337340
* recover the type argument, otherwise NoType.
341+
* @param interpolate If true, replace type bounds as arguments corresponding to
342+
* variant type parameters by their dominating element. I.e. an argument
343+
*
344+
* T <: U
345+
*
346+
* for a covariant type-parameter becomes U, and an argument
347+
*
348+
* T >: L
349+
*
350+
* for a contravariant type-parameter becomes L.
338351
*/
339-
final def argInfo(tparam: Symbol)(implicit ctx: Context): Type = self match {
352+
final def argInfo(tparam: Symbol, interpolate: Boolean = true)(implicit ctx: Context): Type = self match {
340353
case TypeBounds(lo, hi) =>
341354
if (lo eq hi) hi
342-
else {
355+
else if (interpolate) {
343356
val v = tparam.variance
344357
if (v > 0 && (lo isRef defn.NothingClass)) hi
345358
else if (v < 0 && (hi isRef defn.AnyClass)) lo
346-
else self // it's wildcard type; return its bounds
359+
else self
347360
}
361+
else self
348362
case _ =>
349363
NoType
350364
}

src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
9797
}
9898
tp match {
9999
case tp: RefinedType =>
100-
val args = tp.argInfos
100+
val args = tp.argInfos(interpolate = false)
101101
if (args.nonEmpty) {
102102
val tycon = tp.unrefine
103103
val cls = tycon.typeSymbol

tests/pos/printbounds.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Tree[-T >: Number]
2+
3+
4+
class Test {
5+
6+
val x: Tree[_] = ???
7+
8+
val y = x // With -Xprint:front this should print val x: Tree[_] = x
9+
// used to print Tree[Nothing], which is confusing.
10+
11+
}

0 commit comments

Comments
 (0)