Skip to content

Commit de9519f

Browse files
committed
Refactor function operations in Definitions
Also: show implicit function types correctly. Also: refine applications of implicit funcitons - don't do it for closure trees - don't do it after typer.
1 parent 972470e commit de9519f

File tree

5 files changed

+32
-21
lines changed

5 files changed

+32
-21
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,12 +501,14 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
501501
*/
502502
object closure {
503503
def unapply(tree: Tree): Option[(List[Tree], Tree, Tree)] = tree match {
504-
case Block(_, Closure(env, meth, tpt)) => Some(env, meth, tpt)
504+
case Block(_, expr) => unapply(expr)
505505
case Closure(env, meth, tpt) => Some(env, meth, tpt)
506506
case _ => None
507507
}
508508
}
509509

510+
def isClosure(tree: Tree) = closure.unapply(tree).isDefined
511+
510512
/** If tree is a closure, its body, otherwise tree itself */
511513
def closureBody(tree: Tree)(implicit ctx: Context): Tree = tree match {
512514
case Block((meth @ DefDef(nme.ANON_FUN, _, _, _, _)) :: Nil, Closure(_, _, _)) => meth.rhs

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

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -617,15 +617,16 @@ class Definitions {
617617
sym.owner.linkedClass.typeRef
618618

619619
object FunctionOf {
620-
def apply(args: List[Type], resultType: Type)(implicit ctx: Context) =
621-
FunctionType(args.length).appliedTo(args ::: resultType :: Nil)
620+
def apply(args: List[Type], resultType: Type, isImplicit: Boolean = false)(implicit ctx: Context) =
621+
FunctionType(args.length, isImplicit).appliedTo(args ::: resultType :: Nil)
622622
def unapply(ft: Type)(implicit ctx: Context) = {
623623
val tsym = ft.typeSymbol
624-
if (isFunctionClass(tsym)) {
625-
lazy val targs = ft.argInfos
624+
val isImplicitFun = isImplicitFunctionClass(tsym)
625+
if (isImplicitFun || isFunctionClass(tsym)) {
626+
val targs = ft.argInfos
626627
val numArgs = targs.length - 1
627-
if (numArgs >= 0 && FunctionType(numArgs).symbol == tsym)
628-
Some(targs.init, targs.last)
628+
if (numArgs >= 0 && FunctionType(numArgs, isImplicitFun).symbol == tsym)
629+
Some(targs.init, targs.last, isImplicitFun)
629630
else None
630631
}
631632
else None
@@ -689,8 +690,9 @@ class Definitions {
689690
def ImplicitFunctionClass(n: Int)(implicit ctx: Context) =
690691
ctx.requiredClass("scala.ImplicitFunction" + n.toString)
691692

692-
def FunctionType(n: Int)(implicit ctx: Context): TypeRef =
693-
if (n < MaxImplementedFunctionArity) ImplementedFunctionType(n)
693+
def FunctionType(n: Int, isImplicit: Boolean = false)(implicit ctx: Context): TypeRef =
694+
if (isImplicit && !ctx.erasedTypes) ImplicitFunctionClass(n).typeRef
695+
else if (n < MaxImplementedFunctionArity) ImplementedFunctionType(n)
694696
else FunctionClass(n).typeRef
695697

696698
private lazy val TupleTypes: Set[TypeRef] = TupleType.toSet
@@ -766,11 +768,15 @@ class Definitions {
766768
def isProductSubType(tp: Type)(implicit ctx: Context) =
767769
(tp derivesFrom ProductType.symbol) && tp.baseClasses.exists(isProductClass)
768770

769-
def isFunctionType(tp: Type)(implicit ctx: Context) =
770-
isFunctionClass(tp.dealias.typeSymbol) && {
771-
val arity = functionArity(tp)
772-
arity >= 0 && tp.isRef(FunctionType(functionArity(tp)).typeSymbol)
773-
}
771+
/** Is `tp` (an alias) of either a scala.FunctionN or a scala.ImplicitFunctionN ? */
772+
def isFunctionType(tp: Type)(implicit ctx: Context) = {
773+
val arity = functionArity(tp)
774+
val sym = tp.dealias.typeSymbol
775+
arity >= 0 && (
776+
isFunctionClass(sym) && tp.isRef(FunctionType(arity, isImplicit = false).typeSymbol) ||
777+
isImplicitFunctionClass(sym) && tp.isRef(FunctionType(arity, isImplicit = true).typeSymbol)
778+
)
779+
}
774780

775781
def functionArity(tp: Type)(implicit ctx: Context) = tp.dealias.argInfos.length - 1
776782

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,20 +113,21 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
113113
override def toText(tp: Type): Text = controlled {
114114
def toTextTuple(args: List[Type]): Text =
115115
"(" ~ Text(args.map(argText), ", ") ~ ")"
116-
def toTextFunction(args: List[Type]): Text =
116+
def toTextFunction(args: List[Type], isImplicit: Boolean): Text =
117117
changePrec(GlobalPrec) {
118118
val argStr: Text =
119119
if (args.length == 2 && !defn.isTupleType(args.head))
120120
atPrec(InfixPrec) { argText(args.head) }
121121
else
122122
toTextTuple(args.init)
123-
argStr ~ " => " ~ argText(args.last)
123+
("implicit " provided isImplicit) ~ argStr ~ " => " ~ argText(args.last)
124124
}
125125
homogenize(tp) match {
126126
case AppliedType(tycon, args) =>
127127
val cls = tycon.typeSymbol
128128
if (tycon.isRepeatedParam) return toTextLocal(args.head) ~ "*"
129-
if (defn.isFunctionClass(cls)) return toTextFunction(args)
129+
if (defn.isFunctionClass(cls)) return toTextFunction(args, isImplicit = false)
130+
if (defn.isImplicitFunctionClass(cls)) return toTextFunction(args, isImplicit = true)
130131
if (defn.isTupleClass(cls)) return toTextTuple(args)
131132
return (toTextLocal(tycon) ~ "[" ~ Text(args map argText, ", ") ~ "]").close
132133
case tp: TypeRef =>

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,7 +1231,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
12311231
val alts1 = alts filter pt.isMatchedBy
12321232
resolveOverloaded(alts1, pt1, targs1)
12331233

1234-
case defn.FunctionOf(args, resultType) =>
1234+
case defn.FunctionOf(args, resultType, _) =>
12351235
narrowByTypes(alts, args, resultType)
12361236

12371237
case pt =>
@@ -1282,7 +1282,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
12821282
// (p_1_1, ..., p_m_1) => r_1
12831283
// ...
12841284
// (p_1_n, ..., p_m_n) => r_n
1285-
val decomposedFormalsForArg: List[Option[(List[Type], Type)]] =
1285+
val decomposedFormalsForArg: List[Option[(List[Type], Type, Boolean)]] =
12861286
formalsForArg.map(defn.FunctionOf.unapply)
12871287
if (decomposedFormalsForArg.forall(_.isDefined)) {
12881288
val formalParamTypessForArg: List[List[Type]] =

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,8 +1876,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
18761876
missingArgs
18771877
case wtp: RefinedType
18781878
if defn.isImplicitFunctionClass(wtp.underlyingClassRef(refinementOK = false).classSymbol) &&
1879-
!isApplyProto(pt) =>
1880-
typr.println(i"insert apply on implicit $tree")
1879+
!isClosure(tree) &&
1880+
!isApplyProto(pt) &&
1881+
!ctx.isAfterTyper =>
1882+
typr.println("insert apply on implicit $tree")
18811883
typed(untpd.Select(untpd.TypedSplice(tree), nme.apply), pt)
18821884
case _ =>
18831885
ctx.typeComparer.GADTused = false

0 commit comments

Comments
 (0)