aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-01-29 21:48:55 +0100
committerMartin Odersky <odersky@gmail.com>2016-02-19 14:02:17 +0100
commit8441de7a907996361a78d744d3364cee3d558f84 (patch)
treea553bc1c18466324d0f2898af5c9c4d48a4c5fe4 /src/dotty/tools/dotc/typer
parent1d585f1172d563051c0710008568b3b53728281f (diff)
downloaddotty-8441de7a907996361a78d744d3364cee3d558f84.tar.gz
dotty-8441de7a907996361a78d744d3364cee3d558f84.tar.bz2
dotty-8441de7a907996361a78d744d3364cee3d558f84.zip
Allow Named Arguments in TypeArgs
Lets one also pass named arguments to methods.
Diffstat (limited to 'src/dotty/tools/dotc/typer')
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala11
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala44
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala6
3 files changed, 50 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index c7acd3c1f..098385d4b 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -603,12 +603,19 @@ trait Applications extends Compatibility { self: Typer =>
protected def handleUnexpectedFunType(tree: untpd.Apply, fun: Tree)(implicit ctx: Context): Tree =
throw new Error(s"unexpected type.\n fun = $fun,\n methPart(fun) = ${methPart(fun)},\n methPart(fun).tpe = ${methPart(fun).tpe},\n tpe = ${fun.tpe}")
+ def typedNamedArgs(args: List[untpd.Tree])(implicit ctx: Context) =
+ for (arg @ NamedArg(id, argtpt) <- args) yield {
+ val argtpt1 = typedType(argtpt)
+ cpy.NamedArg(arg)(id, argtpt1).withType(argtpt1.tpe)
+ }
+
def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context): Tree = track("typedTypeApply") {
- var typedArgs = tree.args mapconserve (typedType(_))
+ val isNamed = hasNamedArg(tree.args)
+ var typedArgs = if (isNamed) typedNamedArgs(tree.args) else tree.args.mapconserve(typedType(_))
val typedFn = typedExpr(tree.fun, PolyProto(typedArgs.tpes, pt))
typedFn.tpe.widen match {
case pt: PolyType =>
- if (typedArgs.length <= pt.paramBounds.length)
+ if (typedArgs.length <= pt.paramBounds.length && !isNamed)
typedArgs = typedArgs.zipWithConserve(pt.paramBounds)(adaptTypeArg)
case _ =>
}
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 9ee67684d..1c66414a1 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -8,7 +8,8 @@ import Scopes._, Contexts._, Constants._, Types._, Symbols._, Names._, Flags._,
import ErrorReporting._, Annotations._, Denotations._, SymDenotations._, StdNames._, TypeErasure._
import util.Positions._
import config.Printers._
-import NameOps._
+import ast.Trees._
+import collection.mutable
trait TypeAssigner {
import tpd._
@@ -310,9 +311,44 @@ trait TypeAssigner {
def assignType(tree: untpd.TypeApply, fn: Tree, args: List[Tree])(implicit ctx: Context) = {
val ownType = fn.tpe.widen match {
case pt: PolyType =>
- val argTypes = args.tpes
- if (sameLength(argTypes, pt.paramNames)|| ctx.phase.prev.relaxedTyping) pt.instantiate(argTypes)
- else errorType(d"wrong number of type parameters for ${fn.tpe}; expected: ${pt.paramNames.length}", tree.pos)
+ val paramNames = pt.paramNames
+ if (hasNamedArg(args)) {
+ val argMap = new mutable.HashMap[Name, Type]
+ for (NamedArg(name, arg) <- args)
+ if (argMap.contains(name))
+ ctx.error("duplicate name", arg.pos)
+ else if (!paramNames.contains(name))
+ ctx.error(s"undefined parameter name, required: ${paramNames.mkString(" or ")}", arg.pos)
+ else
+ argMap(name) = arg.tpe
+ val gapBuf = new mutable.ListBuffer[Int]
+ def nextPoly = {
+ val idx = gapBuf.length
+ gapBuf += idx
+ PolyParam(pt, idx)
+ }
+ val normArgs = paramNames.map(pname => argMap.getOrElse(pname, nextPoly))
+ val transform = new TypeMap {
+ def apply(t: Type) = t match {
+ case PolyParam(`pt`, idx) => normArgs(idx)
+ case _ => mapOver(t)
+ }
+ }
+ val resultType1 = transform(pt.resultType)
+ if (gapBuf.isEmpty) resultType1
+ else {
+ val gaps = gapBuf.toList
+ pt.derivedPolyType(
+ gaps.map(paramNames.filterNot(argMap.contains)),
+ gaps.map(idx => transform(pt.paramBounds(idx)).bounds),
+ resultType1)
+ }
+ }
+ else {
+ val argTypes = args.tpes
+ if (sameLength(argTypes, paramNames)|| ctx.phase.prev.relaxedTyping) pt.instantiate(argTypes)
+ else errorType(d"wrong number of type parameters for ${fn.tpe}; expected: ${pt.paramNames.length}", tree.pos)
+ }
case _ =>
errorType(i"${err.exprStr(fn)} does not take type parameters", tree.pos)
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 0ff2241fb..fc2bf2381 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -893,11 +893,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
else {
var args = tree.args
val args1 =
- if (hasNamedArg(args))
- for (arg @ NamedArg(id, argtpt) <- args) yield {
- val argtpt1 = typedType(argtpt)
- cpy.NamedArg(arg)(id, argtpt1).withType(argtpt1.tpe)
- }
+ if (hasNamedArg(args)) typedNamedArgs(args)
else {
if (args.length != tparams.length) {
ctx.error(d"wrong number of type arguments for ${tpt1.tpe}, should be ${tparams.length}", tree.pos)