summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-08-31 17:40:58 -0700
committerPaul Phillips <paulp@improving.org>2012-08-31 23:34:16 -0700
commit34893e5d77b683dfd442162f7a5a28b6901c7080 (patch)
tree62f68aedf5c9d4f6812ade5ad9589c885baf378e
parent78401c8220fb56ed077b99a5ffb4205c14fee736 (diff)
downloadscala-34893e5d77b683dfd442162f7a5a28b6901c7080.tar.gz
scala-34893e5d77b683dfd442162f7a5a28b6901c7080.tar.bz2
scala-34893e5d77b683dfd442162f7a5a28b6901c7080.zip
Fix for SI-6034, covariant value classes.
My summary in the ticket was incorrect. The problem was that the class type parameters were being cloned for the method and being allowed to keep their variance. I threw in an assertion for anyone attempting to create a method type with variant type parameters, because hey, why should we allow such madness.
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala1
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala9
-rw-r--r--test/files/pos/t6034.scala1
4 files changed, 11 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
index 2831afc48e..0820d3e714 100644
--- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
@@ -111,7 +111,8 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
}
def extensionMethInfo(extensionMeth: Symbol, origInfo: Type, clazz: Symbol): Type = {
- var newTypeParams = cloneSymbolsAtOwner(clazz.typeParams, extensionMeth)
+ // No variance for method type parameters
+ var newTypeParams = cloneSymbolsAtOwner(clazz.typeParams, extensionMeth) map (_ resetFlag COVARIANT | CONTRAVARIANT)
val thisParamType = appliedType(clazz.typeConstructor, newTypeParams map (_.tpeHK))
val thisParam = extensionMeth.newValueParameter(nme.SELF, extensionMeth.pos) setInfo thisParamType
def transform(clonedType: Type): Type = clonedType match {
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 37f41e2868..2e045b08b9 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -516,6 +516,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def isTypeParameterOrSkolem = false
def isTypeSkolem = false
def isTypeMacro = false
+ def isInvariant = !isCovariant && !isContravariant
/** Qualities of Terms, always false for TypeSymbols.
*/
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 01f615c5cc..b13b893635 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -3712,10 +3712,15 @@ trait Types extends api.Types { self: SymbolTable =>
* may or may not be poly? (It filched the standard "canonical creator" name.)
*/
object GenPolyType {
- def apply(tparams: List[Symbol], tpe: Type): Type = (
+ def apply(tparams: List[Symbol], tpe: Type): Type = {
+ tpe match {
+ case MethodType(_, _) =>
+ assert(tparams forall (_.isInvariant), "Trying to create a method with variant type parameters: " + ((tparams, tpe)))
+ case _ =>
+ }
if (tparams.nonEmpty) typeFun(tparams, tpe)
else tpe // it's okay to be forgiving here
- )
+ }
def unapply(tpe: Type): Option[(List[Symbol], Type)] = tpe match {
case PolyType(tparams, restpe) => Some((tparams, restpe))
case _ => Some((Nil, tpe))
diff --git a/test/files/pos/t6034.scala b/test/files/pos/t6034.scala
new file mode 100644
index 0000000000..3558d7ff0b
--- /dev/null
+++ b/test/files/pos/t6034.scala
@@ -0,0 +1 @@
+final class OptPlus[+A](val x: A) extends AnyVal { }