Skip to content

Commit 7b39007

Browse files
authored
Merge pull request #2835 from dotty-staging/nicer-pretty-printing
More user-friendly pretty printing of types
2 parents 962bc82 + f16b77a commit 7b39007

File tree

7 files changed

+24
-9
lines changed

7 files changed

+24
-9
lines changed

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class ScalaSettings extends Settings.SettingGroup {
9292
val YnoDeepSubtypes = BooleanSetting("-Yno-deep-subtypes", "throw an exception on deep subtyping call stacks.")
9393
val YplainPrinter = BooleanSetting("-Yplain-printer", "Pretty-print using a plain printer.")
9494
val YprintSyms = BooleanSetting("-Yprint-syms", "when printing trees print info in symbols instead of corresponding info in trees.")
95+
val YprintDebug = BooleanSetting("-Yprint-debug", "when printing trees, print some extra information useful for debugging.")
9596
val YtestPickler = BooleanSetting("-Ytest-pickler", "self-test for pickling functionality; should be used with -Ystop-after:pickler")
9697
val YcheckReentrant = BooleanSetting("-Ycheck-reentrant", "check that compiled program does not contain vars that can be accessed from a global root.")
9798
val YkeepComments = BooleanSetting("-Ykeep-comments", "Keep comments when scanning source files.")

compiler/src/dotty/tools/dotc/core/NameOps.scala

+5
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ object NameOps {
124124
name.rewrite { case ExpandedName(_, unexp) => unexp }
125125
}
126126

127+
/** Remove the variance from the name. */
128+
def invariantName: N = likeSpaced {
129+
name.rewrite { case VariantName(invariant, _) => invariant }
130+
}
131+
127132
def implClassName: N = likeSpaced(name ++ tpnme.IMPL_CLASS_SUFFIX)
128133

129134
def errorName: N = likeSpaced(name ++ nme.ERROR)

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

+7-4
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
142142
toTextLocal(tp.underlying) ~ "(" ~ toTextRef(tp) ~ ")"
143143
case tp: TypeRef =>
144144
toTextPrefix(tp.prefix) ~ selectionString(tp)
145+
case AppliedType(tycon, args) =>
146+
(toTextLocal(tycon) ~ "[" ~ Text(args map argText, ", ") ~ "]").close
145147
case tp: RefinedType =>
146148
val parent :: (refined: List[RefinedType @unchecked]) =
147149
refinementChain(tp).reverse
@@ -169,12 +171,13 @@ class PlainPrinter(_ctx: Context) extends Printer {
169171
changePrec(GlobalPrec) {
170172
(if (tp.isImplicit) "(implicit " else "(") ~
171173
Text((tp.paramNames, tp.paramInfos).zipped map paramText, ", ") ~
172-
")" ~ toText(tp.resultType)
174+
(if (tp.resultType.isInstanceOf[MethodType]) ")" else "): ") ~
175+
toText(tp.resultType)
173176
}
174177
case tp: ExprType =>
175178
changePrec(GlobalPrec) { "=> " ~ toText(tp.resultType) }
176179
case tp: TypeLambda =>
177-
def paramText(name: Name, bounds: TypeBounds): Text = name.toString ~ toText(bounds)
180+
def paramText(name: Name, bounds: TypeBounds): Text = name.unexpandedName.toString ~ toText(bounds)
178181
changePrec(GlobalPrec) {
179182
"[" ~ Text((tp.paramNames, tp.paramInfos).zipped.map(paramText), ", ") ~
180183
"]" ~ lambdaHash(tp) ~ (" => " provided !tp.resultType.isInstanceOf[MethodType]) ~
@@ -190,13 +193,13 @@ class PlainPrinter(_ctx: Context) extends Printer {
190193
toTextLocal(tycon) ~ "[" ~ Text(args.map(argText), ", ") ~ "]"
191194
case tp: TypeVar =>
192195
if (tp.isInstantiated)
193-
toTextLocal(tp.instanceOpt) ~ "^" // debug for now, so that we can see where the TypeVars are.
196+
toTextLocal(tp.instanceOpt) ~ ("^" provided ctx.settings.YprintDebug.value)
194197
else {
195198
val constr = ctx.typerState.constraint
196199
val bounds =
197200
if (constr.contains(tp)) constr.fullBounds(tp.origin)(ctx.addMode(Mode.Printing))
198201
else TypeBounds.empty
199-
if (bounds.isAlias) toText(bounds.lo) ~ "^"
202+
if (bounds.isAlias) toText(bounds.lo) ~ ("^" provided ctx.settings.YprintDebug.value)
200203
else if (ctx.settings.YshowVarBounds.value) "(" ~ toText(tp.origin) ~ "?" ~ toText(bounds) ~ ")"
201204
else toText(tp.origin)
202205
}

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
155155
if (defn.isFunctionClass(cls)) return toTextFunction(args, cls.name.isImplicitFunction)
156156
if (defn.isTupleClass(cls)) return toTextTuple(args)
157157
if (isInfixType(tp)) return toTextInfixType(tycon, args)
158-
return (toTextLocal(tycon) ~ "[" ~ Text(args map argText, ", ") ~ "]").close
158+
case EtaExpansion(tycon) =>
159+
return toText(tycon)
159160
case tp: TypeRef =>
160161
val hideType = !ctx.settings.debugAlias.value && (tp.symbol.isAliasPreferred)
161162
if (hideType && !ctx.phase.erasedTypes && !tp.symbol.isCompleting) {
@@ -635,7 +636,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
635636
if (tree.exists(!_.isEmpty)) encl(blockText(tree)) else ""
636637

637638
override protected def ParamRefNameString(name: Name): String =
638-
name.unexpandedName.toString
639+
name.unexpandedName.invariantName.toString
639640

640641
override protected def treatAsTypeParam(sym: Symbol): Boolean = sym is TypeParam
641642

compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ class ErrorMessagesTests extends ErrorMessagesTest {
384384
val MethodDoesNotTakeParameters(tree, methodPart) :: Nil = messages
385385

386386
assertEquals("Scope.foo(1)", tree.show)
387-
assertEquals("((a: Int)Unit)(Scope.foo)", methodPart.show)
387+
assertEquals("((a: Int): Unit)(Scope.foo)", methodPart.show)
388388
}
389389

390390
@Test def ambiugousOverloadWithWildcard =
@@ -408,7 +408,7 @@ class ErrorMessagesTests extends ErrorMessagesTest {
408408
assertMessageCount(1, messages)
409409
val AmbiguousOverload(tree, List(alt1, alt2), pt: WildcardType) :: Nil = messages
410410
assertEquals("method foo", alt1.show)
411-
assertEquals("(s: String)String", alt1.info.show)
411+
assertEquals("(s: String): String", alt1.info.show)
412412
assertEquals("method foo", alt2.show)
413413
}
414414

tests/repl/i2492.check

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ scala> val s: Map {type Map$K =String;type Map$V = Int} = null
44
-- [E055] Syntax Error: <console>:5:7 ------------------------------------------
55
5 |val s: Map {type Map$K =String;type Map$V = Int} = null
66
| ^^^
7-
|missing type parameter for [line1$object$$iw$$iw$Map$$K, line1$object$$iw$$iw$Map$$V] => Map[K, V]
7+
| missing type parameter for Map
88
scala> :quit

tests/repl/names.check

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
scala> case class Foo[M[_]](x: M[Int])
2+
defined class Foo
3+
scala> Foo(Option(1))
4+
val res0: Foo[Option] = Foo(Some(1))
5+
scala> :quit

0 commit comments

Comments
 (0)