summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2007-04-16 11:23:30 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2007-04-16 11:23:30 +0000
commit24eb581d805653215fce5f931f78789e31924800 (patch)
tree3c0690df90110449a36a10461cae0260fca7ca74
parent3d9d369b7147f3933cce9932d2914f68d39418c3 (diff)
downloadscala-24eb581d805653215fce5f931f78789e31924800.tar.gz
scala-24eb581d805653215fce5f931f78789e31924800.tar.bz2
scala-24eb581d805653215fce5f931f78789e31924800.zip
implementing Martin's suggestions for tcpoly
- prefixString in SingleType suppresses scala.Predef prefixes - (sym.isPredefModule) better handling of double defs of `_' in type - params (now in enterInScope in Namers) introduced HKmode to indicate - we're typing a higher-kinded type, instead of reusing POLYmode | - TAPPmode - Typers.typedTypeConstructor does not normalize the result anymore -- now in GenICode generatedType = toTypeKind(tpt.tpe.normalize)
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala8
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala35
-rw-r--r--test/files/neg/accesses.check8
-rw-r--r--test/files/neg/bug521.check6
-rw-r--r--test/files/neg/bug588.check4
-rw-r--r--test/files/neg/bug752.check2
-rw-r--r--test/files/neg/bug856.check2
-rw-r--r--test/files/neg/bug900.check2
-rw-r--r--test/files/neg/bug910.check2
-rw-r--r--test/files/neg/implicits.check2
-rw-r--r--test/files/neg/overload.check2
-rw-r--r--test/files/neg/tcpoly_typealias.check2
-rw-r--r--test/files/neg/tcpoly_variance.check2
-rw-r--r--test/files/neg/tcpoly_variance_enforce.check10
17 files changed, 52 insertions, 42 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 1cb38f79e1..0a2e024a57 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -624,7 +624,7 @@ abstract class GenICode extends SubComponent {
assert(ctor.isClassConstructor,
"'new' call to non-constructor: " + tree)
- generatedType = toTypeKind(tpt.tpe)
+ generatedType = toTypeKind(tpt.tpe.normalize) // @M: because typedTypeConstructor doesn't normalize anymore
assert(generatedType.isReferenceType || generatedType.isArrayType,
"Non reference type cannot be instantiated: " + generatedType)
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 63c502db84..e9b62f1b99 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -209,6 +209,7 @@ trait Symbols requires SymbolTable {
final def isRootPackage = isPackage && name == nme.ROOTPKG
final def isEmptyPackage = isPackage && name == nme.EMPTY_PACKAGE_NAME
final def isEmptyPackageClass = isPackageClass && name == nme.EMPTY_PACKAGE_NAME.toTypeName
+ final def isPredefModule = isModule && name == nme.Predef
def isDeprecated =
attributes exists (attr => attr.atp.symbol == DeprecatedAttr)
@@ -1120,12 +1121,7 @@ trait Symbols requires SymbolTable {
* of this class. Classes are instances of a subclass.
*/
class TypeSymbol(initOwner: Symbol, initPos: PositionType, initName: Name)
- extends Symbol(initOwner, initPos,
-// @M type params with name "_" implicitly get unique name @M TODO: the name generation is a bit hacky...
- if(initName.length==1 && initName(0)=='_') // faster equality test than first converting to string
- newTypeName("_$" + (ids+1))
- else initName) {
- override def nameString: String = if(name.startsWith("_$")) "_"+idString else super.nameString // @M: undo underscore-mangling
+ extends Symbol(initOwner, initPos, initName) {
override def isType = true
privateWithin = NoSymbol
private var tyconCache: Type = null
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index c27cf02811..71c97bef15 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -670,7 +670,7 @@ trait Types requires SymbolTable {
override def symbol = sym
override def prefix: Type = pre
override def prefixString: String =
- if ((sym.isEmptyPackage || sym.isInterpreterWrapper) && !settings.debug.value) ""
+ if ((sym.isEmptyPackage || sym.isInterpreterWrapper || sym.isPredefModule) && !settings.debug.value) ""
else pre.prefixString + sym.nameString + "."
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index fb3e7931cc..4bbd881cb5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -126,7 +126,8 @@ trait Namers requires Analyzer {
if ((prev ne null) && prev.owner == context.scope &&
(!prev.sym.isSourceMethod ||
nme.isSetterName(sym.name) ||
- sym.owner.isPackageClass)) {
+ sym.owner.isPackageClass) &&
+ !(sym.owner.isTypeParameter && sym.name.length==1 && sym.name(0)=='_')) { //@M: allow repeated use of `_' for higher-order type params
doubleDefError(sym.pos, prev.sym)
sym setInfo ErrorType
} else context.scope enter sym
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index e52fc84523..7534df9bbb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -123,6 +123,12 @@ trait Typers requires Analyzer {
/** The mode <code>ALTmode</code> is set when we are under a pattern alternative */
val ALTmode = 0x2000
+ /** The mode <code>HKmode</code> is set when we are typing a higher-kinded type
+ * adapt should then check kind-arity based on the prototypical type's kind arity
+ * type arguments should not be inferred
+ */
+ val HKmode = 0x4000 // @M: could also use POLYmode | TAPPmode
+
private val stickyModes: int = EXPRmode | PATTERNmode | TYPEmode | CONSTmode | ALTmode
private def funMode(mode: int) = mode & (stickyModes | SCCmode) | FUNmode | POLYmode
@@ -541,8 +547,8 @@ trait Typers requires Analyzer {
* unapply or unapplySeq method.
*
* (6) Convert all other types to TypeTree nodes.
- * (7) When in TYPEmode but not FUNmode, check that types are fully parameterized
- * (7.1) @M! when in POLYmode | TAPPmode, check that types have the expected kind
+ * (7) When in TYPEmode but not FUNmode or HKmode, check that types are fully parameterized
+ * (7.1) In HKmode, higher-kinded types are allowed, but they must have the expected kind-arity
* (8) When in both EXPRmode and FUNmode, add apply method calls to values of object type.
* (9) If there are undetermined type variables and not POLYmode, infer expression instance
* Then, if tree's type is not a subtype of expected type, try the following adaptations:
@@ -565,6 +571,7 @@ trait Typers requires Analyzer {
if ((mode & EXPRmode) != 0 && sym == ByNameParamClass) => // (2)
adapt(tree setType arg, mode, pt)
case PolyType(tparams, restpe) if ((mode & (TAPPmode | PATTERNmode)) == 0) => // (3)
+ assert((mode & HKmode) == 0) //@M
val tparams1 = cloneSymbols(tparams)
val tree1 = if (tree.isType) tree
else TypeApply(tree, tparams1 map (tparam =>
@@ -605,15 +612,19 @@ trait Typers requires Analyzer {
if (tree.isType) {
if ((mode & FUNmode) != 0) {
tree
- } else if (tree.hasSymbol && !tree.symbol.typeParams.isEmpty && (mode & (POLYmode | TAPPmode)) == 0) { // (7)
- // @M higher-kinded types are allowed in (POLYmode | TAPPmode) -- see (7.1)
+ } else if (tree.hasSymbol && !tree.symbol.typeParams.isEmpty && (mode & HKmode) == 0) { // (7)
+ // @M When not typing a higher-kinded type ((mode & HKmode) == 0), types must be of kind *,
+ // and thus parameterised types must be applied to their type arguments
errorTree(tree, tree.symbol+" takes type parameters")
tree setType tree.tpe
- } else if (tree.hasSymbol && ((mode & (POLYmode | TAPPmode)) == (POLYmode | TAPPmode)) && // (7.1) @M: check kind-arity (full checks are done in checkKindBounds in Infer)
+ } else if (tree.hasSymbol && ((mode & HKmode) != 0) && // (7.1) @M: check kind-arity
tree.symbol.typeParams.length != pt.typeParams.length &&
- !(tree.symbol==AnyClass || tree.symbol==AllClass || pt == WildcardType )) { //@M Any and Nothing are kind-polymorphic
- // WildcardType is only used when typing type arguments to an overloaded method, before the overload is resolved
- // (or in the case of an error type) -- see case TypeApply in typed1
+ !(tree.symbol==AnyClass || tree.symbol==AllClass || pt == WildcardType )) {
+ // Check that the actual kind arity (tree.symbol.typeParams.length) conforms to the expected
+ // kind-arity (pt.typeParams.length). Full checks are done in checkKindBounds in Infer.
+ // Note that we treat Any and Nothing as kind-polymorphic.
+ // We can't perform this check when typing type arguments to an overloaded method before the overload is resolved
+ // (or in the case of an error type) -- this is indicated by pt == WildcardType (see case TypeApply in typed1).
errorTree(tree, tree.symbol+" takes "+reporter.countElementsAsString(tree.symbol.typeParams.length, "type parameter")+
", expected: "+reporter.countAsString(pt.typeParams.length))
tree setType tree.tpe
@@ -651,6 +662,7 @@ trait Typers requires Analyzer {
((mode & TAPPmode) == 0 || tree.tpe.typeParams.isEmpty) &&
member(adaptToName(tree, nme.apply), nme.apply)
.filter(m => m.tpe.paramSectionCount > 0) != NoSymbol) { // (8)
+ assert((mode & HKmode) == 0) //@M
val qual = adaptToName(tree, nme.apply) match {
case id @ Ident(_) =>
val pre = if (id.symbol.owner.isPackageClass) id.symbol.owner.thisType
@@ -665,6 +677,7 @@ trait Typers requires Analyzer {
}
typed(atPos(tree.pos)(Select(qual, nme.apply)), mode, pt)
} else if (!context.undetparams.isEmpty && (mode & POLYmode) == 0) { // (9)
+ assert((mode & HKmode) == 0) //@M
instantiate(tree, mode, pt)
} else if (tree.tpe <:< pt) {
tree
@@ -2669,17 +2682,17 @@ trait Typers requires Analyzer {
/** Types a higher-kinded type tree -- pt denotes the expected kind*/
def typedHigherKindedType(tree: Tree, pt: Type): Tree =
if(pt.typeParams.isEmpty) typedType(tree) // kind is known and it's *
- else withNoGlobalVariance{ typed(tree, POLYmode | TAPPmode, pt) }
+ else withNoGlobalVariance{ typed(tree, HKmode, pt) }
def typedHigherKindedType(tree: Tree): Tree =
- withNoGlobalVariance{ typed(tree, POLYmode | TAPPmode, WildcardType) }
+ withNoGlobalVariance{ typed(tree, HKmode, WildcardType) }
/** Types a type constructor tree used in a new or supertype */
def typedTypeConstructor(tree: Tree): Tree = {
val result = withNoGlobalVariance{ typed(tree, TYPEmode | FUNmode, WildcardType) }
if (!phase.erasedTypes && result.tpe.isInstanceOf[TypeRef] && !result.tpe.prefix.isStable)
error(tree.pos, result.tpe.prefix+" is not a legal prefix for a constructor")
- result setType(result.tpe.normalize) // @MAT remove aliases when instantiating
+ result setType(result.tpe) // @M: no need to normalize here, see GenICode line 627: generatedType = toTypeKind(tpt.tpe.normalize)
}
def computeType(tree: Tree, pt: Type): Type = {
diff --git a/test/files/neg/accesses.check b/test/files/neg/accesses.check
index 8b8856370b..2fa78ffc50 100644
--- a/test/files/neg/accesses.check
+++ b/test/files/neg/accesses.check
@@ -1,16 +1,16 @@
-accesses.scala:23: error: error overriding method f2 in class A of type => scala.Predef.unit;
+accesses.scala:23: error: error overriding method f2 in class A of type => unit;
method f2 has weaker access privileges; it should not be private
private def f2: unit = ()
^
-accesses.scala:24: error: error overriding method f3 in class A of type => scala.Predef.unit;
+accesses.scala:24: error: error overriding method f3 in class A of type => unit;
method f3 has weaker access privileges; it should be at least protected
private[p2] def f3: unit = ()
^
-accesses.scala:25: error: error overriding method f4 in class A of type => scala.Predef.unit;
+accesses.scala:25: error: error overriding method f4 in class A of type => unit;
method f4 has weaker access privileges; it should be at least private[p1]
private[p2] def f4: unit
^
-accesses.scala:26: error: error overriding method f5 in class A of type => scala.Predef.unit;
+accesses.scala:26: error: error overriding method f5 in class A of type => unit;
method f5 has weaker access privileges; it should be at least protected[p1]
protected[p2] def f5: unit
^
diff --git a/test/files/neg/bug521.check b/test/files/neg/bug521.check
index d058d2971e..80a1931231 100644
--- a/test/files/neg/bug521.check
+++ b/test/files/neg/bug521.check
@@ -1,14 +1,14 @@
-bug521.scala:10: error: class PlainFile needs to be abstract, since method path in class AbstractFile of type => scala.Predef.String is not defined
+bug521.scala:10: error: class PlainFile needs to be abstract, since method path in class AbstractFile of type => String is not defined
class PlainFile(val file : File) extends AbstractFile {}
^
bug521.scala:13: error: error overriding value file in class PlainFile of type java.io.File;
value file needs `override' modifier
final class ZipArchive(val file : File, archive : ZipFile) extends PlainFile(file) {
^
-bug521.scala:13: error: class ZipArchive needs to be abstract, since method path in class AbstractFile of type => scala.Predef.String is not defined
+bug521.scala:13: error: class ZipArchive needs to be abstract, since method path in class AbstractFile of type => String is not defined
final class ZipArchive(val file : File, archive : ZipFile) extends PlainFile(file) {
^
-bug521.scala:15: error: error overriding value path in class VirtualFile of type scala.Predef.String;
+bug521.scala:15: error: error overriding value path in class VirtualFile of type String;
method path needs to be an immutable value
override def path = "";
^
diff --git a/test/files/neg/bug588.check b/test/files/neg/bug588.check
index 648484176e..f652292a2c 100644
--- a/test/files/neg/bug588.check
+++ b/test/files/neg/bug588.check
@@ -1,6 +1,6 @@
bug588.scala:3: error: double definition:
-method visit:((scala.Predef.int) => scala.Predef.String)scala.Predef.boolean and
-method visit:((scala.Predef.int) => scala.Predef.unit)scala.Predef.boolean at line 2
+method visit:((int) => String)boolean and
+method visit:((int) => unit)boolean at line 2
have same type after erasure: (scala.Function1)scala.Boolean
def visit(f: int => String): boolean
^
diff --git a/test/files/neg/bug752.check b/test/files/neg/bug752.check
index e240dbdfe2..5eddaf2a20 100644
--- a/test/files/neg/bug752.check
+++ b/test/files/neg/bug752.check
@@ -1,5 +1,5 @@
bug752.scala:6: error: type mismatch;
- found : (scala.Predef.String) => scala.Unit
+ found : (String) => scala.Unit
required: (scala.Int) => scala.Unit
f(&g)
^
diff --git a/test/files/neg/bug856.check b/test/files/neg/bug856.check
index e78077f437..80c4deeea2 100644
--- a/test/files/neg/bug856.check
+++ b/test/files/neg/bug856.check
@@ -1,4 +1,4 @@
-bug856.scala:3: error: class ComplexRect needs to be abstract, since method _2 in trait Product2 of type => scala.Predef.double is not defined
+bug856.scala:3: error: class ComplexRect needs to be abstract, since method _2 in trait Product2 of type => double is not defined
class ComplexRect(val _1:double, _2:double) extends Complex {
^
one error found
diff --git a/test/files/neg/bug900.check b/test/files/neg/bug900.check
index 0bb5edad80..3345255231 100644
--- a/test/files/neg/bug900.check
+++ b/test/files/neg/bug900.check
@@ -3,7 +3,7 @@ bug900.scala:4: error: type mismatch;
required: scala.AnyRef
Note that implicit conversions are not applicable because they are ambiguous:
both method any2stringadd in object Predef of type (scala.Any)scala.runtime.StringAdd
- and method any2ArrowAssoc in object Predef of type [a](a)scala.Predef.ArrowAssoc[a]
+ and method any2ArrowAssoc in object Predef of type [a](a)ArrowAssoc[a]
are possible conversion functions from Foo.this.x.type to scala.AnyRef
def break(): x.type
^
diff --git a/test/files/neg/bug910.check b/test/files/neg/bug910.check
index 855793d412..bf761eb04d 100644
--- a/test/files/neg/bug910.check
+++ b/test/files/neg/bug910.check
@@ -1,6 +1,6 @@
bug910.scala:4: error: type mismatch;
found : scala.Seq[scala.Char]
- required: scala.Seq[scala.Predef.int]
+ required: scala.Seq[int]
val y: Seq[int] = rest
^
one error found
diff --git a/test/files/neg/implicits.check b/test/files/neg/implicits.check
index 1af86e6c05..079764df42 100644
--- a/test/files/neg/implicits.check
+++ b/test/files/neg/implicits.check
@@ -2,7 +2,7 @@ implicits.scala:21: error: type mismatch;
found : Pos
required: ?{val +: ?}
Note that implicit conversions are not applicable because they are ambiguous:
- most specific definition is: method pos2int in object Super of type (Pos)scala.Predef.int
+ most specific definition is: method pos2int in object Super of type (Pos)int
yet alternative definition method any2plus in object Sub of type (scala.Any)Sub.Plus
is defined in a subclass.
Both definitions are possible conversion functions from Pos to ?{val +: ?}
diff --git a/test/files/neg/overload.check b/test/files/neg/overload.check
index 70d292b349..62f61c2de9 100644
--- a/test/files/neg/overload.check
+++ b/test/files/neg/overload.check
@@ -1,5 +1,5 @@
overload.scala:10: error: erroneous reference to overloaded definition,
-most specific definition is: method f in class C of type (scala.Predef.int)scala.Unit,
+most specific definition is: method f in class C of type (int)scala.Unit,
yet alternative definition method f in class D of type (scala.Any)scala.Unit
is defined in a subclass
(new D).f(1)
diff --git a/test/files/neg/tcpoly_typealias.check b/test/files/neg/tcpoly_typealias.check
index 56912c49b7..8a2ae91f89 100644
--- a/test/files/neg/tcpoly_typealias.check
+++ b/test/files/neg/tcpoly_typealias.check
@@ -7,7 +7,7 @@ BCon.this.m's type parameters do not match type m's expected parameters: type x
type m[-x] = FooCon[x] // error: contravariant x
^
tcpoly_typealias.scala:45: error: The kind of type m does not conform to the expected kind of type m<: [+x]>: scala.Nothing <: scala.Any in trait A.
-BBound.this.m's type parameters do not match type m's expected parameters: type x (in trait BBound)'s bounds >: scala.Nothing <: scala.Predef.String are stricter than type x (in trait A)'s declared bounds >: scala.Nothing <: scala.Any
+BBound.this.m's type parameters do not match type m's expected parameters: type x (in trait BBound)'s bounds >: scala.Nothing <: String are stricter than type x (in trait A)'s declared bounds >: scala.Nothing <: scala.Any
type m[+x <: String] = FooBound[x] // error: x with stricter bound
^
three errors found
diff --git a/test/files/neg/tcpoly_variance.check b/test/files/neg/tcpoly_variance.check
index 5fd104d607..61d7094437 100644
--- a/test/files/neg/tcpoly_variance.check
+++ b/test/files/neg/tcpoly_variance.check
@@ -1,5 +1,5 @@
tcpoly_variance.scala:6: error: error overriding method str in class A of type => m[java.lang.Object];
- method str has incompatible type => m[scala.Predef.String]
+ method str has incompatible type => m[String]
override def str: m[String] = error("foo") // since x in m[x] is invariant, ! m[String] <: m[Object]
^
one error found
diff --git a/test/files/neg/tcpoly_variance_enforce.check b/test/files/neg/tcpoly_variance_enforce.check
index c66440434b..93b1c1fd51 100644
--- a/test/files/neg/tcpoly_variance_enforce.check
+++ b/test/files/neg/tcpoly_variance_enforce.check
@@ -7,7 +7,7 @@ FooContra's type parameters do not match type m's expected parameters: type x (i
object fcollcon extends coll[FooContra] // error
^
tcpoly_variance_enforce.scala:17: error: the kinds of the type arguments (FooString) do not conform to the expected kinds of the type parameters (type m) in trait coll.
-FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: scala.Nothing <: scala.Predef.String are stricter than type x's declared bounds >: scala.Nothing <: scala.Any
+FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: scala.Nothing <: String are stricter than type x's declared bounds >: scala.Nothing <: scala.Any
object fcollwb extends coll[FooString] // error
^
tcpoly_variance_enforce.scala:19: error: the kinds of the type arguments (FooCov) do not conform to the expected kinds of the type parameters (type m) in trait coll2.
@@ -19,19 +19,19 @@ FooInvar's type parameters do not match type m's expected parameters: type x (in
object fcoll2inv extends coll2[FooInvar] // error
^
tcpoly_variance_enforce.scala:22: error: the kinds of the type arguments (FooString) do not conform to the expected kinds of the type parameters (type m) in trait coll2.
-FooString's type parameters do not match type m's expected parameters: type x (in class FooString) is covariant, but type x is declared contravarianttype x (in class FooString)'s bounds >: scala.Nothing <: scala.Predef.String are stricter than type x's declared bounds >: scala.Nothing <: scala.Any
+FooString's type parameters do not match type m's expected parameters: type x (in class FooString) is covariant, but type x is declared contravarianttype x (in class FooString)'s bounds >: scala.Nothing <: String are stricter than type x's declared bounds >: scala.Nothing <: scala.Any
object fcoll2wb extends coll2[FooString] // error
^
tcpoly_variance_enforce.scala:27: error: the kinds of the type arguments (FooString) do not conform to the expected kinds of the type parameters (type m) in trait coll3.
-FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: scala.Nothing <: scala.Predef.String are stricter than type x's declared bounds >: scala.Nothing <: scala.Any
+FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: scala.Nothing <: String are stricter than type x's declared bounds >: scala.Nothing <: scala.Any
object fcoll3wb extends coll3[FooString] // error
^
tcpoly_variance_enforce.scala:30: error: the kinds of the type arguments (FooString,scala.Int) do not conform to the expected kinds of the type parameters (type m,type y) in trait coll4.
-FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: scala.Nothing <: scala.Predef.String are stricter than type x's declared bounds >: scala.Nothing <: y
+FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: scala.Nothing <: String are stricter than type x's declared bounds >: scala.Nothing <: y
object fcoll4_1 extends coll4[FooString, Int] // error
^
tcpoly_variance_enforce.scala:31: error: the kinds of the type arguments (FooString,scala.Any) do not conform to the expected kinds of the type parameters (type m,type y) in trait coll4.
-FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: scala.Nothing <: scala.Predef.String are stricter than type x's declared bounds >: scala.Nothing <: y
+FooString's type parameters do not match type m's expected parameters: type x (in class FooString)'s bounds >: scala.Nothing <: String are stricter than type x's declared bounds >: scala.Nothing <: y
object fcoll4_2 extends coll4[FooString, Any] // error
^
tcpoly_variance_enforce.scala:37: error: the kinds of the type arguments (FooInvar) do not conform to the expected kinds of the type parameters (type m) in trait coll.