aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-01-09 14:39:44 +0100
committerMartin Odersky <odersky@gmail.com>2016-02-19 14:00:00 +0100
commit5a8e87004f563feafbaf16e78bd0d6be26ee6e1c (patch)
treee81bb81e43922a24859aaab31986d5f256059788 /src
parent91ccb52bda344d74ba7a3e9859346e57051d2aff (diff)
downloaddotty-5a8e87004f563feafbaf16e78bd0d6be26ee6e1c.tar.gz
dotty-5a8e87004f563feafbaf16e78bd0d6be26ee6e1c.tar.bz2
dotty-5a8e87004f563feafbaf16e78bd0d6be26ee6e1c.zip
First version of named type arguments
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala40
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala26
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala38
3 files changed, 81 insertions, 23 deletions
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index 983ee1ccf..58ec75605 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -740,7 +740,7 @@ object Parsers {
private def simpleTypeRest(t: Tree): Tree = in.token match {
case HASH => simpleTypeRest(typeProjection(t))
- case LBRACKET => simpleTypeRest(atPos(t.pos.start) { AppliedTypeTree(t, typeArgs()) })
+ case LBRACKET => simpleTypeRest(atPos(t.pos.start) { AppliedTypeTree(t, typeArgs(namedOK = true)) })
case _ => t
}
@@ -759,9 +759,38 @@ object Parsers {
}
else typ()
+ /** NamedTypeArg ::= id `=' ArgType
+ */
+ val namedTypeArg = () => {
+ val name = ident()
+ accept(EQUALS)
+ NamedArg(name.toTypeName, argType())
+ }
+
/** ArgTypes ::= ArgType {`,' ArgType}
+ * NamedTypeArg {`,' NamedTypeArg}
*/
- def argTypes() = commaSeparated(argType)
+ def argTypes(namedOK: Boolean = false) = {
+ def otherArgs(first: Tree, arg: () => Tree): List[Tree] = {
+ val rest =
+ if (in.token == COMMA) {
+ in.nextToken()
+ commaSeparated(arg)
+ }
+ else Nil
+ first :: rest
+ }
+ if (namedOK && in.token == IDENTIFIER)
+ argType() match {
+ case Ident(name) if in.token == EQUALS =>
+ in.nextToken()
+ otherArgs(NamedArg(name, argType()), namedTypeArg)
+ case firstArg =>
+ if (in.token == EQUALS) println(s"??? $firstArg")
+ otherArgs(firstArg, argType)
+ }
+ else commaSeparated(argType)
+ }
/** FunArgType ::= ArgType | `=>' ArgType
*/
@@ -785,9 +814,10 @@ object Parsers {
} else t
}
- /** TypeArgs ::= `[' ArgType {`,' ArgType} `]'
- */
- def typeArgs(): List[Tree] = inBrackets(argTypes())
+ /** TypeArgs ::= `[' ArgType {`,' ArgType} `]'
+ * NamedTypeArgs ::= `[' NamedTypeArg {`,' NamedTypeArg} `]'
+ */
+ def typeArgs(namedOK: Boolean = false): List[Tree] = inBrackets(argTypes(namedOK))
/** Refinement ::= `{' RefineStatSeq `}'
*/
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index ac46ee723..44ada642c 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -4,6 +4,7 @@ package typer
import core._
import ast._
+import ast.Trees._
import Scopes._, Contexts._, Constants._, Types._, Symbols._, Names._, Flags._, Decorators._
import ErrorReporting._, Annotations._, Denotations._, SymDenotations._, StdNames._, TypeErasure._
import util.Positions._
@@ -184,8 +185,11 @@ trait TypeAssigner {
ErrorType
}
}
- else if (d.symbol is TypeParamAccessor) // always dereference type param accessors
- ensureAccessible(d.info.bounds.hi, superAccess, pos)
+ else if (d.symbol is TypeParamAccessor)
+ if (d.info.isAlias)
+ ensureAccessible(d.info.bounds.hi, superAccess, pos)
+ else // It's a named parameter, use the non-symbolic representation to pick up inherited versions as well
+ d.symbol.owner.thisType.select(d.symbol.name)
else
ctx.makePackageObjPrefixExplicit(tpe withDenot d)
case _ =>
@@ -375,8 +379,24 @@ trait TypeAssigner {
def assignType(tree: untpd.AppliedTypeTree, tycon: Tree, args: List[Tree])(implicit ctx: Context) = {
val tparams = tycon.tpe.typeParams
+ def refineNamed(tycon: Type, arg: Tree) = arg match {
+ case NamedArg(name, argtpt) =>
+ val tparam = tparams.find(_.name == name) match {
+ case Some(tparam) => tparam
+ case none =>
+ val sym = tycon.member(name).symbol
+ if (sym.isAbstractType) sym
+ else if (sym.is(ParamAccessor)) sym.info.dealias.typeSymbol
+ else NoSymbol
+ }
+ if (tparam.exists) RefinedType(tycon, name, argtpt.tpe.toBounds(tparam))
+ else errorType(s"$tycon does not have a parameter or abstract type member named $name", arg.pos)
+ case _ =>
+ errorType(s"named and positional type arguments may not be mixed", arg.pos)
+ }
val ownType =
- if (sameLength(tparams, args)) tycon.tpe.appliedTo(args.tpes)
+ if (args.head.isInstanceOf[NamedArg]) (tycon.tpe /: args)(refineNamed)
+ else if (sameLength(tparams, args)) tycon.tpe.appliedTo(args.tpes)
else errorType(d"wrong number of type arguments for ${tycon.tpe}, should be ${tparams.length}", tree.pos)
tree.withType(ownType)
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index d39f2dd43..42b556fa0 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -885,26 +885,34 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedAppliedTypeTree(tree: untpd.AppliedTypeTree)(implicit ctx: Context): Tree = track("typedAppliedTypeTree") {
val tpt1 = typed(tree.tpt)(ctx retractMode Mode.Pattern)
val tparams = tpt1.tpe.typeParams
- var args = tree.args
if (tparams.isEmpty) {
ctx.error(d"${tpt1.tpe} does not take type parameters", tree.pos)
tpt1
}
else {
- if (args.length != tparams.length) {
- ctx.error(d"wrong number of type arguments for ${tpt1.tpe}, should be ${tparams.length}", tree.pos)
- args = args.take(tparams.length)
- }
- def typedArg(arg: untpd.Tree, tparam: Symbol) = {
- val (desugaredArg, argPt) =
- if (ctx.mode is Mode.Pattern)
- (if (isVarPattern(arg)) desugar.patternVar(arg) else arg, tparam.info)
- else
- (arg, WildcardType)
- val arg1 = typed(desugaredArg, argPt)
- adaptTypeArg(arg1, tparam.info)
- }
- val args1 = args.zipWithConserve(tparams)(typedArg(_, _)).asInstanceOf[List[Tree]]
+ var args = tree.args
+ val args1 =
+ if (args.head.isInstanceOf[untpd.NamedArg])
+ for (arg @ NamedArg(id, argtpt) <- args) yield {
+ val argtpt1 = typedType(argtpt)
+ cpy.NamedArg(arg)(id, argtpt1).withType(argtpt1.tpe)
+ }
+ else {
+ if (args.length != tparams.length) {
+ ctx.error(d"wrong number of type arguments for ${tpt1.tpe}, should be ${tparams.length}", tree.pos)
+ args = args.take(tparams.length)
+ }
+ def typedArg(arg: untpd.Tree, tparam: Symbol) = {
+ val (desugaredArg, argPt) =
+ if (ctx.mode is Mode.Pattern)
+ (if (isVarPattern(arg)) desugar.patternVar(arg) else arg, tparam.info)
+ else
+ (arg, WildcardType)
+ val arg1 = typed(desugaredArg, argPt)
+ adaptTypeArg(arg1, tparam.info)
+ }
+ args.zipWithConserve(tparams)(typedArg(_, _)).asInstanceOf[List[Tree]]
+ }
// check that arguments conform to bounds is done in phase PostTyper
assignType(cpy.AppliedTypeTree(tree)(tpt1, args1), tpt1, args1)
}