aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/ast
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-12-05 10:34:58 +0100
committerMartin Odersky <odersky@gmail.com>2016-12-17 18:34:27 +0100
commitbcc80ad1343a3ed01bef55f494d9658cf02226c6 (patch)
tree5fb2feecdf0df524128c72d14a6402fd6c547291 /compiler/src/dotty/tools/dotc/ast
parent0336785a2280a4a1e51e739e9aac3d5015f7c16f (diff)
downloaddotty-bcc80ad1343a3ed01bef55f494d9658cf02226c6.tar.gz
dotty-bcc80ad1343a3ed01bef55f494d9658cf02226c6.tar.bz2
dotty-bcc80ad1343a3ed01bef55f494d9658cf02226c6.zip
Create implicit closures to math expected implicit functions
When the expected type is an implicit function, create an implicit closure to match it.
Diffstat (limited to 'compiler/src/dotty/tools/dotc/ast')
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Desugar.scala23
-rw-r--r--compiler/src/dotty/tools/dotc/ast/TreeInfo.scala12
-rw-r--r--compiler/src/dotty/tools/dotc/ast/untpd.scala6
3 files changed, 29 insertions, 12 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala
index 11f8b81eb..def2caabf 100644
--- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala
@@ -123,6 +123,13 @@ object desugar {
else vdef
}
+ def makeImplicitParameters(tpts: List[Tree], forPrimaryConstructor: Boolean)(implicit ctx: Context) =
+ for (tpt <- tpts) yield {
+ val paramFlags: FlagSet = if (forPrimaryConstructor) PrivateLocalParamAccessor else Param
+ val epname = ctx.freshName(nme.EVIDENCE_PARAM_PREFIX).toTermName
+ ValDef(epname, tpt, EmptyTree).withFlags(paramFlags | Implicit)
+ }
+
/** Expand context bounds to evidence params. E.g.,
*
* def f[T >: L <: H : B](params)
@@ -143,19 +150,16 @@ object desugar {
val epbuf = new ListBuffer[ValDef]
def desugarContextBounds(rhs: Tree): Tree = rhs match {
case ContextBounds(tbounds, cxbounds) =>
- for (cxbound <- cxbounds) {
- val paramFlags: FlagSet = if (isPrimaryConstructor) PrivateLocalParamAccessor else Param
- val epname = ctx.freshName(nme.EVIDENCE_PARAM_PREFIX).toTermName
- epbuf += ValDef(epname, cxbound, EmptyTree).withFlags(paramFlags | Implicit)
- }
+ for (cxbound <- cxbounds)
+ epbuf ++= makeImplicitParameters(cxbounds, isPrimaryConstructor)
tbounds
case PolyTypeTree(tparams, body) =>
cpy.PolyTypeTree(rhs)(tparams, desugarContextBounds(body))
case _ =>
rhs
}
- val tparams1 = tparams mapConserve { tdef =>
- cpy.TypeDef(tdef)(rhs = desugarContextBounds(tdef.rhs))
+ val tparams1 = tparams mapConserve { tparam =>
+ cpy.TypeDef(tparam)(rhs = desugarContextBounds(tparam))
}
val meth1 = addEvidenceParams(cpy.DefDef(meth)(tparams = tparams1), epbuf.toList)
@@ -679,6 +683,11 @@ object desugar {
Function(param :: Nil, Block(vdefs, body))
}
+ def makeImplicitFunction(formals: List[Type], body: Tree)(implicit ctx: Context): Tree = {
+ val params = makeImplicitParameters(formals.map(TypeTree), forPrimaryConstructor = false)
+ new ImplicitFunction(params, body)
+ }
+
/** Add annotation with class `cls` to tree:
* tree @cls
*/
diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
index ae7c93784..da83d0644 100644
--- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -290,6 +290,16 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped]
case _ => false
}
+ /** Is `tree` an implicit function or closure, possibly nested in a block? */
+ def isImplicitClosure(tree: Tree)(implicit ctx: Context): Boolean = unsplice(tree) match {
+ case Function((param: untpd.ValDef) :: _, _) => param.mods.is(Implicit)
+ case Closure(_, meth, _) => true
+ case Block(Nil, expr) => isImplicitClosure(expr)
+ case Block(DefDef(nme.ANON_FUN, _, (param :: _) :: _, _, _) :: Nil, _: Closure) =>
+ param.mods.is(Implicit)
+ case _ => false
+ }
+
// todo: fill with other methods from TreeInfo that only apply to untpd.Tree's
}
@@ -507,8 +517,6 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
}
}
- 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/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala
index 9707770d5..77755da81 100644
--- a/compiler/src/dotty/tools/dotc/ast/untpd.scala
+++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala
@@ -55,7 +55,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
}
/** An implicit function type */
- class ImplicitFunction(args: List[Tree], body: Tree) extends Function(args, body)
+ class ImplicitFunction(args: List[Tree], body: Tree) extends Function(args, body) {
+ override def toString = s"ImplicitFunction($args, $body"
+ }
/** A function created from a wildcard expression
* @param placeHolderParams a list of definitions of synthetic parameters
@@ -274,8 +276,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
// ------ Additional creation methods for untyped only -----------------
- // def TypeTree(tpe: Type): TypeTree = TypeTree().withType(tpe) todo: move to untpd/tpd
-
/** new pre.C[Ts](args1)...(args_n)
* ==>
* (new pre.C).<init>[Ts](args1)...(args_n)