summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2007-05-31 07:59:38 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2007-05-31 07:59:38 +0000
commitaac8bba0c25aef3c2e410d1f28818c8b1fe9266f (patch)
treef734b86613821bedfb5c3aa048ada5b1c9c3f53d
parente78dcdc4c5b920d686f69aca8e9b9670054125bb (diff)
downloadscala-aac8bba0c25aef3c2e410d1f28818c8b1fe9266f.tar.gz
scala-aac8bba0c25aef3c2e410d1f28818c8b1fe9266f.tar.bz2
scala-aac8bba0c25aef3c2e410d1f28818c8b1fe9266f.zip
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
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala14
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala4
-rw-r--r--test/files/pos/tcpoly_checkkinds_mix.scala10
3 files changed, 20 insertions, 8 deletions
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 <arg>hkargs</arg> to a higher-kinded type conform to the expected params <arg>hkparams</arg>
- 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