diff options
author | Martin Odersky <odersky@gmail.com> | 2016-12-05 10:34:58 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-12-17 18:34:27 +0100 |
commit | bcc80ad1343a3ed01bef55f494d9658cf02226c6 (patch) | |
tree | 5fb2feecdf0df524128c72d14a6402fd6c547291 /compiler/src/dotty/tools/dotc/ast | |
parent | 0336785a2280a4a1e51e739e9aac3d5015f7c16f (diff) | |
download | dotty-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.scala | 23 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/ast/TreeInfo.scala | 12 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/ast/untpd.scala | 6 |
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) |