diff options
author | Olivier Blanvillain <olivier.blanvillain@gmail.com> | 2016-09-15 16:59:40 +0200 |
---|---|---|
committer | Olivier Blanvillain <olivier.blanvillain@gmail.com> | 2016-09-15 17:03:09 +0200 |
commit | 5450507c663bca565b2b61b8afb1073c991c9827 (patch) | |
tree | 034fa122e9ef517626a5b54e3a9f954a08bd9a97 /src/dotty/tools/dotc/typer/TypeAssigner.scala | |
parent | 3f3df3d8f7638eb5cca9ae8162f8388373c912c6 (diff) | |
download | dotty-5450507c663bca565b2b61b8afb1073c991c9827.tar.gz dotty-5450507c663bca565b2b61b8afb1073c991c9827.tar.bz2 dotty-5450507c663bca565b2b61b8afb1073c991c9827.zip |
Fix #1513: misaligned by name type parameter type bounds
Diffstat (limited to 'src/dotty/tools/dotc/typer/TypeAssigner.scala')
-rw-r--r-- | src/dotty/tools/dotc/typer/TypeAssigner.scala | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala index 36404a68f..3266a38d1 100644 --- a/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -321,21 +321,30 @@ trait TypeAssigner { case pt: PolyType => val paramNames = pt.paramNames if (hasNamedArg(args)) { - val argMap = new mutable.HashMap[Name, Type] + // Type arguments which are specified by name (immutable after this first loop) + val namedArgMap = new mutable.HashMap[Name, Type] for (NamedArg(name, arg) <- args) - if (argMap.contains(name)) + if (namedArgMap.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 + namedArgMap(name) = arg.tpe + + // Holds indexes of non-named typed arguments in paramNames val gapBuf = new mutable.ListBuffer[Int] - def nextPoly = { - val idx = gapBuf.length + def nextPoly(idx: Int) = { + val newIndex = gapBuf.length gapBuf += idx - PolyParam(pt, idx) + // Re-index unassigned type arguments that remain after transformation + PolyParam(pt, newIndex) + } + + // Type parameters after naming assignment, conserving paramNames order + val normArgs: List[Type] = paramNames.zipWithIndex.map { case (pname, idx) => + namedArgMap.getOrElse(pname, nextPoly(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) @@ -347,19 +356,20 @@ trait TypeAssigner { else { val gaps = gapBuf.toList pt.derivedPolyType( - gaps.map(paramNames.filterNot(argMap.contains)), + gaps.map(paramNames), 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) + if (sameLength(argTypes, paramNames) || ctx.phase.prev.relaxedTyping) pt.instantiate(argTypes) else wrongNumberOfArgs(fn.tpe, "type ", pt.paramNames.length, tree.pos) } case _ => errorType(i"${err.exprStr(fn)} does not take type parameters", tree.pos) } + tree.withType(ownType) } @@ -383,8 +393,8 @@ trait TypeAssigner { def assignType(tree: untpd.Closure, meth: Tree, target: Tree)(implicit ctx: Context) = tree.withType( - if (target.isEmpty) meth.tpe.widen.toFunctionType(tree.env.length) - else target.tpe) + if (target.isEmpty) meth.tpe.widen.toFunctionType(tree.env.length) + else target.tpe) def assignType(tree: untpd.CaseDef, body: Tree)(implicit ctx: Context) = tree.withType(body.tpe) |