summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2010-07-08 15:59:00 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2010-07-08 15:59:00 +0000
commitbc5ac3dc9a03553072f69d1117ea2389473acd4a (patch)
tree8861152bae068e9630c176c331763fbbd76cbe0e
parent0cbeaf17d85d4925939d51938826c318db667c50 (diff)
downloadscala-bc5ac3dc9a03553072f69d1117ea2389473acd4a.tar.gz
scala-bc5ac3dc9a03553072f69d1117ea2389473acd4a.tar.bz2
scala-bc5ac3dc9a03553072f69d1117ea2389473acd4a.zip
closes #3374.
review by odersky
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala26
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala19
-rw-r--r--test/files/neg/bug1275.check8
-rw-r--r--test/files/neg/bug1275.scala26
-rw-r--r--test/files/pos/t3374.scala6
5 files changed, 44 insertions, 41 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index ba0b8317b5..1993a8c23f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -1040,12 +1040,20 @@ trait Infer {
*/
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
+ def transformedBounds(p: Symbol, o: Symbol) = transform(p.info.instantiateTypeParams(tparams, targs).bounds, o)
// 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], arg: Symbol, param: Symbol, paramowner: Symbol): (List[(Symbol, Symbol)], List[(Symbol, Symbol)], List[(Symbol, Symbol)]) = {
+ def checkKindBoundsHK(hkargs: List[Symbol], arg: Symbol, param: Symbol, paramowner: Symbol, underHKParams: List[Symbol], withHKArgs: List[Symbol]): (List[(Symbol, Symbol)], List[(Symbol, Symbol)], List[(Symbol, Symbol)]) = {
+ def bindHKParams(tp: Type) = tp.substSym(underHKParams, withHKArgs)
// @M sometimes hkargs != arg.typeParams, the symbol and the type may have very different type parameters
val hkparams = param.typeParams
+ if(printTypings) {
+ println("checkKindBoundsHK expected: "+ param +" with params "+ hkparams +" by definition in "+ paramowner)
+ println("checkKindBoundsHK supplied: "+ arg +" with params "+ hkargs +" from "+ owner)
+ println("checkKindBoundsHK under params: "+ underHKParams +" with args "+ withHKArgs)
+ }
+
if(hkargs.length != hkparams.length) {
if(arg == AnyClass || arg == NothingClass) (Nil, Nil, Nil) // Any and Nothing are kind-overloaded
else (List((arg, param)), Nil, Nil)
@@ -1068,10 +1076,16 @@ 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 (!(transform(hkparam.info.instantiateTypeParams(tparams, targs).bounds.substSym(hkparams, hkargs), paramowner) <:< transform(hkarg.info.bounds, owner)))
+ if (!(bindHKParams(transformedBounds(hkparam, paramowner)) <:< transform(hkarg.info.bounds, owner)))
stricterBound(hkarg, hkparam)
+
+ if(printTypings) {
+ println("checkKindBoundsHK base case: "+ hkparam +" declared bounds: "+ transformedBounds(hkparam, paramowner) +" after instantiating earlier hkparams: "+ bindHKParams(transformedBounds(hkparam, paramowner)))
+ println("checkKindBoundsHK base case: "+ hkarg +" has bounds: "+ transform(hkarg.info.bounds, owner))
+ }
} else {
- val (am, vm, sb) = checkKindBoundsHK(hkarg.typeParams, hkarg, hkparam, paramowner)
+ if(printTypings) println("checkKindBoundsHK recursing to compare params of "+ hkparam +" with "+ hkarg)
+ val (am, vm, sb) = checkKindBoundsHK(hkarg.typeParams, hkarg, hkparam, paramowner, underHKParams ++ hkparam.typeParams, withHKArgs ++ hkarg.typeParams)
arityMismatches(am)
varianceMismatches(vm)
stricterBounds(sb)
@@ -1099,11 +1113,11 @@ trait Infer {
val errors = new ListBuffer[String]
(tparams zip targs).foreach{ case (tparam, targ) if (targ.isHigherKinded || !tparam.typeParams.isEmpty) =>
- // @M must use the typeParams of the type targ, not the typeParams of the symbol of targ!!
- val tparamsHO = targ.typeParams
+ // @M must use the typeParams of the type targ, not the typeParams of the symbol of targ!!
+ val tparamsHO = targ.typeParams
val (arityMismatches, varianceMismatches, stricterBounds) =
- checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner) // NOTE: *not* targ.typeSymbol, which normalizes
+ checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO) // NOTE: *not* targ.typeSymbol, which normalizes
if (!(arityMismatches.isEmpty && varianceMismatches.isEmpty && stricterBounds.isEmpty)){
errors += (targ+"'s type parameters do not match "+tparam+"'s expected parameters: "+
(for ((a, p) <- arityMismatches)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 2123a00550..53fb15dbeb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1065,24 +1065,7 @@ trait Namers { self: Analyzer =>
case tp =>
tp
}
-
- def verifyOverriding(other: Symbol): Boolean = {
- if(other.unsafeTypeParams.length != tparamSyms.length) {
- context.error(tpsym.pos,
- "The kind of "+tpsym.keyString+" "+tpsym.varianceString + tpsym.nameString+
- " does not conform to the expected kind of " + other.defString + other.locationString + ".")
- false
- } else true
- }
-
- // @M: make sure overriding in refinements respects rudimentary kinding
- // have to do this early, as otherwise we might get crashes: (see neg/bug1275.scala)
- // suppose some parameterized type member is overridden by a type member w/o params,
- // then appliedType will be called on a type that does not expect type args --> crash
- if (tpsym.owner.isRefinementClass && // only needed in refinements
- !tpsym.allOverriddenSymbols.forall{verifyOverriding(_)})
- ErrorType
- else polyType(tparamSyms, tp)
+ polyType(tparamSyms, tp)
}
/** Given a case class
diff --git a/test/files/neg/bug1275.check b/test/files/neg/bug1275.check
index 9f806c0689..40c5d79d27 100644
--- a/test/files/neg/bug1275.check
+++ b/test/files/neg/bug1275.check
@@ -1,4 +1,6 @@
-bug1275.scala:13: error: The kind of type MyType does not conform to the expected kind of type MyType[+t] <: TestCovariance.Seq[t] in trait Seq.
- def span[a, s <: Seq[a] { type MyType <: s } ](xs: s): s = xs f
- ^
+bug1275.scala:8: error: type mismatch;
+ found : xs.MyType[a]
+ required: s
+ = xs f // xs: s <: Seq[a]{type MyType <: s }
+ ^
one error found
diff --git a/test/files/neg/bug1275.scala b/test/files/neg/bug1275.scala
index e9be13c763..769156fff2 100644
--- a/test/files/neg/bug1275.scala
+++ b/test/files/neg/bug1275.scala
@@ -1,14 +1,12 @@
-// tested using Scala compiler version 2.6.0-RC1 -- (c) 2002-2010 LAMP/EPFL
-
-// prompted by "Covariant return types" mailing list question
-object TestCovariance {
-
- // see Type constructor polymorphism in http://www.scala-lang.org/docu/changelog.html
- trait Seq[+t] {
- type MyType[+t] <: Seq[t]
-
- def f: MyType[t]
- }
-
- def span[a, s <: Seq[a] { type MyType <: s } ](xs: s): s = xs f
-}
+object Test {
+ trait Seq[+t] {
+ type MyType[+t] <: Seq[t]
+ def f: MyType[t]
+ }
+
+ def span[a, s <: Seq[a] { type MyType <: s } ](xs: s): s
+ = xs f // xs: s <: Seq[a]{type MyType <: s }
+ // xs.f : xs.MyType[a] <: Seq[a]
+ // ill-formed type in bound for s: Seq[a] { type MyType <: s }
+ // refinements aren't checked -- should they?
+} \ No newline at end of file
diff --git a/test/files/pos/t3374.scala b/test/files/pos/t3374.scala
new file mode 100644
index 0000000000..4c0293181d
--- /dev/null
+++ b/test/files/pos/t3374.scala
@@ -0,0 +1,6 @@
+trait Parent {
+ type Test[A, H[B <: A]]
+}
+trait Sub extends Parent {
+ type Test[AS, HS[B <: AS]] = AS
+} \ No newline at end of file