diff options
author | Martin Odersky <odersky@gmail.com> | 2016-01-09 14:39:44 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-02-19 14:00:00 +0100 |
commit | 5a8e87004f563feafbaf16e78bd0d6be26ee6e1c (patch) | |
tree | e81bb81e43922a24859aaab31986d5f256059788 /src | |
parent | 91ccb52bda344d74ba7a3e9859346e57051d2aff (diff) | |
download | dotty-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.scala | 40 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/TypeAssigner.scala | 26 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 38 |
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) } |