From 34893e5d77b683dfd442162f7a5a28b6901c7080 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 31 Aug 2012 17:40:58 -0700 Subject: 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. --- src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala | 3 ++- src/reflect/scala/reflect/internal/Symbols.scala | 1 + src/reflect/scala/reflect/internal/Types.scala | 9 +++++++-- test/files/pos/t6034.scala | 1 + 4 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 test/files/pos/t6034.scala 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 { } -- cgit v1.2.3