From aac8bba0c25aef3c2e410d1f28818c8b1fe9266f Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Thu, 31 May 2007 07:59:38 +0000 Subject: fixed bug in checkKindBounds (type parameters d... fixed bug in checkKindBounds (type parameters defined outside the abstract type that was being checked, were not properly transformed using asSeenFrom) -- regression test included in commit --- src/compiler/scala/tools/nsc/typechecker/Infer.scala | 14 ++++++++------ src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 4 ++-- test/files/pos/tcpoly_checkkinds_mix.scala | 10 ++++++++++ 3 files changed, 20 insertions(+), 8 deletions(-) create mode 100644 test/files/pos/tcpoly_checkkinds_mix.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 80ba2c1df1..6ce9514f54 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -649,7 +649,7 @@ trait Infer { //@M validate variances & bounds of targs wrt variances & bounds of tparams //@M TODO: better place to check this? //@M TODO: errors for getters & setters are reported separately - val kindErrors = checkKindBounds(tparams, targs) + val kindErrors = checkKindBounds(tparams, targs, pre, owner) if(!kindErrors.isEmpty) error(pos, @@ -693,9 +693,11 @@ trait Infer { * e.g. class Iterable[t, m[+x <: t]] --> the application Iterable[Int, List] is okay, since * List's type parameter is also covariant and its bounds are weaker than <: Int */ - def checkKindBounds(tparams: List[Symbol], targs: List[Type]): List[String] = { + def checkKindBounds(tparams: List[Symbol], targs: List[Type], pre: Type, owner: Symbol): List[String] = { + def transform(tp: Type, clazz: Symbol): Type = tp.asSeenFrom(pre, clazz) // instantiate type params that come from outside the abstract type we're currently checking + // check that the type parameters hkargs to a higher-kinded type conform to the expected params hkparams - def checkKindBoundsHK(hkargs: List[Symbol], hkparams: List[Symbol]): (List[(Symbol, Symbol)], List[(Symbol, Symbol)]) = { + def checkKindBoundsHK(hkargs: List[Symbol], hkparams: List[Symbol], paramowner: Symbol): (List[(Symbol, Symbol)], List[(Symbol, Symbol)]) = { val _varianceMismatches = new ListBuffer[(Symbol, Symbol)] val _stricterBounds = new ListBuffer[(Symbol, Symbol)] def varianceMismatch(a: Symbol, p: Symbol): unit = _varianceMismatches += (a, p) @@ -712,10 +714,10 @@ trait Infer { // substSym(hkparams, hkargs) --> these types are going to be compared as types of kind * // --> their arguments use different symbols, but are conceptually the same // (could also replace the types by polytypes, but can't just strip the symbols, as ordering is lost then) - if (!(hkparam.info.instantiateTypeParams(tparams, targs).bounds.substSym(hkparams, hkargs) <:< hkarg.info.bounds)) + if (!(transform(hkparam.info.instantiateTypeParams(tparams, targs).bounds.substSym(hkparams, hkargs), paramowner) <:< transform(hkarg.info.bounds, owner))) stricterBound(hkarg, hkparam) } else { - val (vm, sb) = checkKindBoundsHK(hkarg.typeParams, hkparam.typeParams) + val (vm, sb) = checkKindBoundsHK(hkarg.typeParams, hkparam.typeParams, paramowner) varianceMismatches(vm) stricterBounds(sb) } @@ -739,7 +741,7 @@ trait Infer { val errors = new ListBuffer[String] (tparams zip targs).foreach{ case (tparam, targ) if(targ.isHigherKinded) => - val (varianceMismatches, stricterBounds) = checkKindBoundsHK(targ.typeParams, tparam.typeParams) + val (varianceMismatches, stricterBounds) = checkKindBoundsHK(targ.typeParams, tparam.typeParams, tparam.owner) if (!(varianceMismatches.isEmpty && stricterBounds.isEmpty)){ errors += (targ+"'s type parameters do not match "+tparam+"'s expected parameters: "+ diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 8aa83f3438..c16af6a066 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -206,7 +206,7 @@ abstract class RefChecks extends InfoTransform { // check overriding (abstract type --> abstract type or abstract type --> concrete type member (a type alias)) // making an abstract type member concrete is like passing a type argument - val kindErrors = typer.infer.checkKindBounds(List(other), List(memberTp)) // (1.7.2) + val kindErrors = typer.infer.checkKindBounds(List(other), List(memberTp), self, member.owner) // (1.7.2) if(!kindErrors.isEmpty) unit.error(member.pos, @@ -217,7 +217,7 @@ abstract class RefChecks extends InfoTransform { // check a type alias's RHS corresponds to its declaration // this overlaps somewhat with validateVariance if(member.isAliasType) { - val kindErrors = typer.infer.checkKindBounds(List(member), List(memberTp.normalize)) + val kindErrors = typer.infer.checkKindBounds(List(member), List(memberTp.normalize), self, member.owner) if(!kindErrors.isEmpty) unit.error(member.pos, diff --git a/test/files/pos/tcpoly_checkkinds_mix.scala b/test/files/pos/tcpoly_checkkinds_mix.scala new file mode 100644 index 0000000000..27bf11a2ef --- /dev/null +++ b/test/files/pos/tcpoly_checkkinds_mix.scala @@ -0,0 +1,10 @@ +trait Iterable[A <: Bound[A], Bound[_]] { + type MyType[x <: Bound[x]] <: Iterable[x, Bound] + def map[B <: Bound[B]](f: A => B): MyType[B] + def flatMap[B <: Bound[B]](f: A => MyType[B]): MyType[B] + def filter(p: A => Boolean): MyType[A] +} + +trait OrderedSet[T <: Ordered[T]] extends Iterable[T, Ordered] { + type MyType[x <: Ordered[x]] = OrderedSet[x] +} \ No newline at end of file -- cgit v1.2.3