diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 13 | ||||
-rw-r--r-- | test/files/neg/t5060.check | 7 | ||||
-rw-r--r-- | test/files/neg/t5060.scala | 19 |
3 files changed, 37 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 3b9cf88a00..b3e1e3feb8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -762,6 +762,9 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R /** Validate variance of info of symbol `base` */ private def validateVariance(base: Symbol) { + // A flag for when we're in a refinement, meaning method parameter types + // need to be checked. + var inRefinement = false def varianceString(variance: Int): String = if (variance == 1) "covariant" @@ -845,12 +848,17 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R validateVariances(parents, variance) case RefinedType(parents, decls) => validateVariances(parents, variance) + val saved = inRefinement + inRefinement = true for (sym <- decls) validateVariance(sym.info, if (sym.isAliasType) NoVariance else variance) + inRefinement = saved case TypeBounds(lo, hi) => validateVariance(lo, -variance) validateVariance(hi, variance) case MethodType(formals, result) => + if (inRefinement) + validateVariances(formals map (_.tpe), -variance) validateVariance(result, variance) case NullaryMethodType(result) => validateVariance(result, variance) @@ -887,9 +895,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R // ModuleDefs need not be considered because they have been eliminated already case ValDef(_, _, _, _) => validateVariance(tree.symbol) - case DefDef(_, _, tparams, vparamss, tpt, rhs) => + case DefDef(_, _, tparams, vparamss, _, _) => validateVariance(tree.symbol) - traverseTrees(tparams); traverseTreess(vparamss) + traverseTrees(tparams) + traverseTreess(vparamss) case Template(_, _, _) => super.traverse(tree) case _ => diff --git a/test/files/neg/t5060.check b/test/files/neg/t5060.check new file mode 100644 index 0000000000..ab860c9d5b --- /dev/null +++ b/test/files/neg/t5060.check @@ -0,0 +1,7 @@ +t5060.scala:2: error: covariant type T occurs in contravariant position in type => Object with ScalaObject{def contains(x: T): Unit} of value foo0 + val foo0 = { + ^ +t5060.scala:6: error: covariant type T occurs in contravariant position in type => Object with ScalaObject{def contains(x: T): Unit} of method foo1 + def foo1 = { + ^ +two errors found diff --git a/test/files/neg/t5060.scala b/test/files/neg/t5060.scala new file mode 100644 index 0000000000..4d934a9a16 --- /dev/null +++ b/test/files/neg/t5060.scala @@ -0,0 +1,19 @@ +class A[+T] { + val foo0 = { + class AsVariantAsIWantToBe { def contains(x: T) = () } + new AsVariantAsIWantToBe + } + def foo1 = { + class VarianceIsTheSpiceOfTypes { def contains(x: T) = () } + new VarianceIsTheSpiceOfTypes + } +} + +object Test { + def main(args: Array[String]): Unit = { + val xs: A[String] = new A[String] + println(xs.foo0 contains "abc") + println((xs: A[Any]).foo0 contains 5) + // java.lang.NoSuchMethodException: A$AsVariantAsIWantToBe$1.contains(java.lang.String) + } +} |