aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-12-03 19:32:09 +0100
committerMartin Odersky <odersky@gmail.com>2016-12-17 18:34:27 +0100
commit4fb19e43f696845a18cbe2a7671654674ffce9b7 (patch)
treeeaa6abbcaf7966041f2e10f1d7840d4f4ca1c6a9
parentad7edc7bd8af963b768afdc50b7038a8daa47ccb (diff)
downloaddotty-4fb19e43f696845a18cbe2a7671654674ffce9b7.tar.gz
dotty-4fb19e43f696845a18cbe2a7671654674ffce9b7.tar.bz2
dotty-4fb19e43f696845a18cbe2a7671654674ffce9b7.zip
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.
-rw-r--r--compiler/src/dotty/tools/dotc/ast/TreeInfo.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala32
-rw-r--r--compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala7
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Applications.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala6
5 files changed, 32 insertions, 21 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
index d1e6bd38a..ae7c93784 100644
--- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -501,12 +501,14 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
*/
object closure {
def unapply(tree: Tree): Option[(List[Tree], Tree, Tree)] = tree match {
- case Block(_, Closure(env, meth, tpt)) => Some(env, meth, tpt)
+ case Block(_, expr) => unapply(expr)
case Closure(env, meth, tpt) => Some(env, meth, tpt)
case _ => None
}
}
+ def isClosure(tree: Tree) = closure.unapply(tree).isDefined
+
/** If tree is a closure, its body, otherwise tree itself */
def closureBody(tree: Tree)(implicit ctx: Context): Tree = tree match {
case Block((meth @ DefDef(nme.ANON_FUN, _, _, _, _)) :: Nil, Closure(_, _, _)) => meth.rhs
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index f04dac505..ff259f184 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -617,15 +617,16 @@ class Definitions {
sym.owner.linkedClass.typeRef
object FunctionOf {
- def apply(args: List[Type], resultType: Type)(implicit ctx: Context) =
- FunctionType(args.length).appliedTo(args ::: resultType :: Nil)
+ def apply(args: List[Type], resultType: Type, isImplicit: Boolean = false)(implicit ctx: Context) =
+ FunctionType(args.length, isImplicit).appliedTo(args ::: resultType :: Nil)
def unapply(ft: Type)(implicit ctx: Context) = {
val tsym = ft.typeSymbol
- if (isFunctionClass(tsym)) {
- lazy val targs = ft.argInfos
+ val isImplicitFun = isImplicitFunctionClass(tsym)
+ if (isImplicitFun || isFunctionClass(tsym)) {
+ val targs = ft.argInfos
val numArgs = targs.length - 1
- if (numArgs >= 0 && FunctionType(numArgs).symbol == tsym)
- Some(targs.init, targs.last)
+ if (numArgs >= 0 && FunctionType(numArgs, isImplicitFun).symbol == tsym)
+ Some(targs.init, targs.last, isImplicitFun)
else None
}
else None
@@ -689,8 +690,9 @@ class Definitions {
def ImplicitFunctionClass(n: Int)(implicit ctx: Context) =
ctx.requiredClass("scala.ImplicitFunction" + n.toString)
- def FunctionType(n: Int)(implicit ctx: Context): TypeRef =
- if (n < MaxImplementedFunctionArity) ImplementedFunctionType(n)
+ def FunctionType(n: Int, isImplicit: Boolean = false)(implicit ctx: Context): TypeRef =
+ if (isImplicit && !ctx.erasedTypes) ImplicitFunctionClass(n).typeRef
+ else if (n < MaxImplementedFunctionArity) ImplementedFunctionType(n)
else FunctionClass(n).typeRef
private lazy val TupleTypes: Set[TypeRef] = TupleType.toSet
@@ -776,11 +778,15 @@ class Definitions {
}
else -1
- def isFunctionType(tp: Type)(implicit ctx: Context) =
- isFunctionClass(tp.dealias.typeSymbol) && {
- val arity = functionArity(tp)
- arity >= 0 && tp.isRef(FunctionType(functionArity(tp)).typeSymbol)
- }
+ /** Is `tp` (an alias) of either a scala.FunctionN or a scala.ImplicitFunctionN ? */
+ def isFunctionType(tp: Type)(implicit ctx: Context) = {
+ val arity = functionArity(tp)
+ val sym = tp.dealias.typeSymbol
+ arity >= 0 && (
+ isFunctionClass(sym) && tp.isRef(FunctionType(arity, isImplicit = false).typeSymbol) ||
+ isImplicitFunctionClass(sym) && tp.isRef(FunctionType(arity, isImplicit = true).typeSymbol)
+ )
+ }
def functionArity(tp: Type)(implicit ctx: Context) = tp.dealias.argInfos.length - 1
diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 1ddf3cd6d..3085ad8fd 100644
--- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -113,20 +113,21 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
override def toText(tp: Type): Text = controlled {
def toTextTuple(args: List[Type]): Text =
"(" ~ Text(args.map(argText), ", ") ~ ")"
- def toTextFunction(args: List[Type]): Text =
+ def toTextFunction(args: List[Type], isImplicit: Boolean): Text =
changePrec(GlobalPrec) {
val argStr: Text =
if (args.length == 2 && !defn.isTupleType(args.head))
atPrec(InfixPrec) { argText(args.head) }
else
toTextTuple(args.init)
- argStr ~ " => " ~ argText(args.last)
+ ("implicit " provided isImplicit) ~ argStr ~ " => " ~ argText(args.last)
}
homogenize(tp) match {
case AppliedType(tycon, args) =>
val cls = tycon.typeSymbol
if (tycon.isRepeatedParam) return toTextLocal(args.head) ~ "*"
- if (defn.isFunctionClass(cls)) return toTextFunction(args)
+ if (defn.isFunctionClass(cls)) return toTextFunction(args, isImplicit = false)
+ if (defn.isImplicitFunctionClass(cls)) return toTextFunction(args, isImplicit = true)
if (defn.isTupleClass(cls)) return toTextTuple(args)
return (toTextLocal(tycon) ~ "[" ~ Text(args map argText, ", ") ~ "]").close
case tp: TypeRef =>
diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala
index 4203ab9b2..469d657a9 100644
--- a/compiler/src/dotty/tools/dotc/typer/Applications.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala
@@ -1294,7 +1294,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
val alts1 = alts filter pt.isMatchedBy
resolveOverloaded(alts1, pt1, targs1)
- case defn.FunctionOf(args, resultType) =>
+ case defn.FunctionOf(args, resultType, _) =>
narrowByTypes(alts, args, resultType)
case pt =>
@@ -1345,7 +1345,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
// (p_1_1, ..., p_m_1) => r_1
// ...
// (p_1_n, ..., p_m_n) => r_n
- val decomposedFormalsForArg: List[Option[(List[Type], Type)]] =
+ val decomposedFormalsForArg: List[Option[(List[Type], Type, Boolean)]] =
formalsForArg.map(defn.FunctionOf.unapply)
if (decomposedFormalsForArg.forall(_.isDefined)) {
val formalParamTypessForArg: List[List[Type]] =
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index 018a6064b..e016ba3a6 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -1880,8 +1880,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
missingArgs
case wtp: RefinedType
if defn.isImplicitFunctionClass(wtp.underlyingClassRef(refinementOK = false).classSymbol) &&
- !isApplyProto(pt) =>
- typr.println(i"insert apply on implicit $tree")
+ !isClosure(tree) &&
+ !isApplyProto(pt) &&
+ !ctx.isAfterTyper =>
+ typr.println("insert apply on implicit $tree")
typed(untpd.Select(untpd.TypedSplice(tree), nme.apply), pt)
case _ =>
ctx.typeComparer.GADTused = false