aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/printing/RefinedPrinter.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/printing/RefinedPrinter.scala')
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala125
1 files changed, 47 insertions, 78 deletions
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 06fe0c9ef..204fc95f0 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -10,6 +10,8 @@ import ast.{Trees, untpd, tpd}
import typer.Namer
import typer.ProtoTypes.{SelectionProto, ViewProto, FunProto, IgnoredProto, dummyTreeOfType}
import Trees._
+import TypeApplications._
+import Decorators._
import scala.annotation.switch
import language.implicitConversions
@@ -17,7 +19,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
/** A stack of enclosing DefDef, TypeDef, or ClassDef, or ModuleDefs nodes */
private var enclosingDef: untpd.Tree = untpd.EmptyTree
-
+ private var lambdaNestingLevel: Int = 0
private var myCtx: Context = _ctx
override protected[this] implicit def ctx: Context = myCtx
@@ -108,26 +110,41 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
argStr ~ " => " ~ toText(args.last)
}
homogenize(tp) match {
- case tp: RefinedType =>
- val args = tp.argInfos
- if (args.nonEmpty) {
- val tycon = tp.unrefine
- val cls = tycon.typeSymbol
- if (cls.typeParams.length == args.length) {
- if (tycon.isRepeatedParam) return toTextLocal(args.head) ~ "*"
- if (defn.isFunctionClass(cls)) return toTextFunction(args)
- if (defn.isTupleClass(cls)) return toTextTuple(args)
- }
- return (toTextLocal(tycon) ~ "[" ~ Text(args map argText, ", ") ~ "]").close
- }
- if (tp.isSafeLambda) {
- val (prefix, body, bindings) = decomposeHKApply(tp)
- prefix match {
- case prefix: TypeRef if prefix.symbol.isLambdaTrait && body.exists =>
- return typeLambdaText(prefix.symbol, body, bindings)
+ case AppliedType(tycon, args) =>
+ val cls = tycon.typeSymbol
+ if (tycon.isRepeatedParam) return toTextLocal(args.head) ~ "*"
+ if (defn.isFunctionClass(cls)) return toTextFunction(args)
+ if (defn.isTupleClass(cls)) return toTextTuple(args)
+ return (toTextLocal(tycon) ~ "[" ~ Text(args map argText, ", ") ~ "]").close
+ case tp @ TypeLambda(variances, argBoundss, body) =>
+ val prefix = ((('X' - 'A') + lambdaNestingLevel) % 26 + 'A').toChar
+ val paramNames = variances.indices.toList.map(prefix.toString + _)
+ val instantiate = new TypeMap {
+ def contains(tp1: Type, tp2: Type): Boolean =
+ tp1.eq(tp2) || {
+ tp1.stripTypeVar match {
+ case RefinedType(parent, _) => contains(parent, tp2)
+ case _ => false
+ }
+ }
+ def apply(t: Type): Type = t match {
+ case TypeRef(RefinedThis(rt), name) if name.isHkArgName && contains(tp, rt) =>
+ // Make up a name that prints as "Xi". Need to be careful we do not
+ // accidentally unique-hash to something else. That's why we can't
+ // use prefix = NoPrefix or a WithFixedSym instance.
+ TypeRef.withSymAndName(
+ defn.EmptyPackageClass.thisType, defn.AnyClass,
+ paramNames(name.hkArgIndex).toTypeName)
case _ =>
+ mapOver(t)
}
}
+ val instArgs = argBoundss.map(instantiate).asInstanceOf[List[TypeBounds]]
+ val instBody = instantiate(body).dropAlias
+ lambdaNestingLevel += 1
+ try
+ return typeLambdaText(paramNames, variances, instArgs, instBody)
+ finally lambdaNestingLevel -=1
case tp: TypeRef =>
val hideType = tp.symbol is AliasPreferred
if (hideType && !ctx.phase.erasedTypes && !tp.symbol.isCompleting) {
@@ -167,71 +184,23 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
def blockText[T >: Untyped](trees: List[Tree[T]]): Text =
"{" ~ toText(trees, "\n") ~ "}"
- /** If type `tp` represents a potential type Lambda of the form
- *
- * parent { type Apply = body; argBindings? }
- *
- * split it into
- *
- * - the `parent`
- * - the simplified `body`
- * - the bindings HK$ members, if there are any
- *
- * The body is simplified as follows
- * - if it is a TypeAlias, follow it
- * - replace all references to of the form <refined-this>.HK$i by references
- * without a prefix, because the latter print nicer.
- *
- */
- def decomposeHKApply(tp: Type): (Type, Type, List[(Name, Type)]) = tp.stripTypeVar match {
- case tp @ RefinedType(parent, name) =>
- if (name == tpnme.hkApply) {
- // simplify arguments so that parameters just print HK$i and not
- // LambdaI{...}.HK$i
- val simplifyArgs = new TypeMap {
- override def apply(tp: Type) = tp match {
- case tp @ TypeRef(RefinedThis(_), name) if name.isLambdaArgName =>
- TypeRef(NoPrefix, tp.symbol.asType)
- case _ =>
- mapOver(tp)
- }
- }
- (parent, simplifyArgs(tp.refinedInfo.followTypeAlias), Nil)
- } else if (name.isLambdaArgName) {
- val (prefix, body, argBindings) = decomposeHKApply(parent)
- (prefix, body, (name, tp.refinedInfo) :: argBindings)
- } else (tp, NoType, Nil)
- case _ =>
- (tp, NoType, Nil)
- }
-
/** The text for a TypeLambda
*
- * LambdaXYZ { type Apply = body'; bindings? }
+ * [v_1 p_1: B_1, ..., v_n p_n: B_n] -> T
*
* where
- * @param lambdaCls The class symbol for `LambdaXYZ`
- * @param body The simplified lambda body
- * @param bindings The bindings of any HK$i arguments
- *
- * @return A text of the form
- *
- * [HK$0, ..., HK$n] => body
- *
- * possibly followed by bindings
- *
- * [HK$i = arg_i, ..., HK$k = arg_k]
+ * @param paramNames = p_1, ..., p_n
+ * @param variances = v_1, ..., v_n
+ * @param argBoundss = B_1, ..., B_n
+ * @param body = T
*/
- def typeLambdaText(lambdaCls: Symbol, body: Type, bindings: List[(Name, Type)]): Text = {
- def lambdaParamText(tparam: Symbol): Text = {
- varianceString(tparam) ~ nameString(tparam.name)
- }
- def lambdaText = changePrec(GlobalPrec) {
- "[" ~ Text(lambdaCls.typeParams.map(lambdaParamText), ", ") ~ "] => " ~ toTextGlobal(body)
+ def typeLambdaText(paramNames: List[String], variances: List[Int], argBoundss: List[TypeBounds], body: Type): Text = {
+ def lambdaParamText(variance: Int, name: String, bounds: TypeBounds): Text =
+ varianceString(variance) ~ name ~ toText(bounds)
+ changePrec(GlobalPrec) {
+ "[" ~ Text((variances, paramNames, argBoundss).zipped.map(lambdaParamText), ", ") ~
+ "] -> " ~ toTextGlobal(body)
}
- def bindingText(binding: (Name, Type)) = binding._1.toString ~ toTextGlobal(binding._2)
- if (bindings.isEmpty) lambdaText
- else atPrec(DotPrec)(lambdaText) ~ "[" ~ Text(bindings.map(bindingText), ", ") ~ "]"
}
override def toText[T >: Untyped](tree: Tree[T]): Text = controlled {
@@ -648,7 +617,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
override def toText(denot: Denotation): Text = denot match {
- case denot: MultiDenotation => denot.toString
+ case denot: MultiDenotation => Text(denot.alternatives.map(dclText), " <and> ")
case NoDenotation => "NoDenotation"
case _ =>
if (denot.symbol.exists) toText(denot.symbol)