aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-12-03 12:53:10 +0100
committerMartin Odersky <odersky@gmail.com>2016-12-17 18:34:27 +0100
commitfd2c24c3159cefa583889a176f31d1e2325fe7e6 (patch)
tree2291e9ecee03b130f50e3c3a4d9660d95bca2723
parent8450556080c5fd8f8553bec4f39ea08fbb05c9d2 (diff)
downloaddotty-fd2c24c3159cefa583889a176f31d1e2325fe7e6.tar.gz
dotty-fd2c24c3159cefa583889a176f31d1e2325fe7e6.tar.bz2
dotty-fd2c24c3159cefa583889a176f31d1e2325fe7e6.zip
Add syntax for implicit functions
-rw-r--r--compiler/src/dotty/tools/dotc/ast/untpd.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Parsers.scala16
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala8
-rw-r--r--docs/syntax-summary.txt4
-rw-r--r--tests/pos/implicitFuns.scala30
5 files changed, 53 insertions, 9 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala
index 6c5210287..25b69b1f5 100644
--- a/compiler/src/dotty/tools/dotc/ast/untpd.scala
+++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala
@@ -53,6 +53,10 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
override def isTerm = body.isTerm
override def isType = body.isType
}
+
+ /** An implicit function type */
+ class ImplicitFunction(args: List[Tree], body: Tree) extends Function(args, body)
+
/** A function created from a wildcard expression
* @param placeHolderParams a list of definitions of synthetic parameters
* @param body the function body where wildcards are replaced by
diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
index 704f399ca..dabd8d2b0 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -681,7 +681,7 @@ object Parsers {
}
}
- /** Type ::= FunArgTypes `=>' Type
+ /** Type ::= [`implicit'] FunArgTypes `=>' Type
* | HkTypeParamClause `->' Type
* | InfixType
* FunArgTypes ::= InfixType
@@ -689,20 +689,26 @@ object Parsers {
*/
def typ(): Tree = {
val start = in.offset
+ val isImplicit = in.token == IMPLICIT
+ if (isImplicit) in.nextToken()
+ def functionRest(params: List[Tree]): Tree =
+ atPos(start, accept(ARROW)) {
+ val t = typ()
+ if (isImplicit) new ImplicitFunction(params, t) else Function(params, t)
+ }
val t =
if (in.token == LPAREN) {
in.nextToken()
if (in.token == RPAREN) {
in.nextToken()
- atPos(start, accept(ARROW)) { Function(Nil, typ()) }
+ functionRest(Nil)
}
else {
openParens.change(LPAREN, 1)
val ts = commaSeparated(funArgType)
openParens.change(LPAREN, -1)
accept(RPAREN)
- if (in.token == ARROW)
- atPos(start, in.skipToken()) { Function(ts, typ()) }
+ if (isImplicit || in.token == ARROW) functionRest(ts)
else {
for (t <- ts)
if (t.isInstanceOf[ByNameTypeTree])
@@ -722,7 +728,7 @@ object Parsers {
else infixType()
in.token match {
- case ARROW => atPos(start, in.skipToken()) { Function(List(t), typ()) }
+ case ARROW => functionRest(t :: Nil)
case FORSOME => syntaxError("existential types no longer supported; use a wildcard type or dependent type instead"); t
case _ => t
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index eec3859f9..c8deda4bc 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -660,9 +660,13 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedFunction(tree: untpd.Function, pt: Type)(implicit ctx: Context) = track("typedFunction") {
val untpd.Function(args, body) = tree
- if (ctx.mode is Mode.Type)
+ if (ctx.mode is Mode.Type) {
+ val funCls =
+ if (tree.isInstanceOf[untpd.ImplicitFunction]) defn.ImplicitFunctionClass(args.length)
+ else defn.FunctionClass(args.length)
typed(cpy.AppliedTypeTree(tree)(
- untpd.TypeTree(defn.FunctionClass(args.length).typeRef), args :+ body), pt)
+ untpd.TypeTree(funCls.typeRef), args :+ body), pt)
+ }
else {
val params = args.asInstanceOf[List[untpd.ValDef]]
diff --git a/docs/syntax-summary.txt b/docs/syntax-summary.txt
index 04e149de6..fe0ebc89c 100644
--- a/docs/syntax-summary.txt
+++ b/docs/syntax-summary.txt
@@ -95,8 +95,8 @@ grammar.
| [id '.'] `super' [ClassQualifier] `.' id
ClassQualifier ::= `[' id `]'
- Type ::= FunArgTypes `=>' Type Function(ts, t)
- | HkTypeParamClause `=>' Type TypeLambda(ps, t)
+ Type ::= [`implicit'] FunArgTypes `=>' Type Function(ts, t)
+ | HkTypeParamClause `=>' Type TypeLambda(ps, t)
| InfixType
FunArgTypes ::= InfixType
| `(' [ FunArgType {`,' FunArgType } ] `)'
diff --git a/tests/pos/implicitFuns.scala b/tests/pos/implicitFuns.scala
new file mode 100644
index 000000000..e62682546
--- /dev/null
+++ b/tests/pos/implicitFuns.scala
@@ -0,0 +1,30 @@
+object Test {
+
+ val x: ImplicitFunction1[String, Boolean] = ???
+
+ val y: String => Boolean = x
+
+ val b = x("hello")
+
+ val b1: Boolean = b
+
+}
+object Test2 {
+
+ val x: implicit String => Boolean = ???
+
+ val xx: implicit (String, Int) => Int = ???
+
+ val y: String => Boolean = x
+
+ val yy: (String, Int) => Any = xx
+
+ val b = x("hello")
+
+ val b1: Boolean = b
+
+ val c = xx("hh", 22)
+
+ val c1: Int = c
+
+}