summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-01-14 23:29:51 -0800
committerPaul Phillips <paulp@improving.org>2013-01-26 11:19:37 -0800
commita8fe8292956f73db3b185bf29d6349f2eb1c3df8 (patch)
tree69a99d5db027bd8eccbe25ae0db003058f30e2ee
parent46e8eceecc5b5f6b49075550e54f035126fc256a (diff)
downloadscala-a8fe8292956f73db3b185bf29d6349f2eb1c3df8.tar.gz
scala-a8fe8292956f73db3b185bf29d6349f2eb1c3df8.tar.bz2
scala-a8fe8292956f73db3b185bf29d6349f2eb1c3df8.zip
Add PolyType to Infer#normalize.
It arises when inferring the type of an overloaded call: def g(s: String): String = s def f: String = ??? def f[C](c: C): String = g(f) Also refined warning when isHKSubType is called with arguments which very likely were never meant to be compared.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala14
-rw-r--r--test/files/pos/kinds.scala13
-rw-r--r--test/pending/pos/those-kinds-are-high.scala53
4 files changed, 69 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index e9f3ad7ff8..e652b68b14 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -244,6 +244,8 @@ trait Infer extends Checkable {
* This method seems to be performance critical.
*/
def normalize(tp: Type): Type = tp match {
+ case pt @ PolyType(tparams, restpe) =>
+ logResult(s"Normalizing $tp in infer")(normalize(restpe))
case mt @ MethodType(params, restpe) if mt.isImplicit =>
normalize(restpe)
case mt @ MethodType(_, restpe) if !mt.isDependentMethodType =>
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index dd73dbe6f6..6fc99874ed 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -5626,10 +5626,12 @@ trait Types extends api.Types { self: SymbolTable =>
// for (tpFresh <- tpsFresh) tpFresh.setInfo(tpFresh.info.substSym(tparams1, tpsFresh))
}
} && annotationsConform(tp1.normalize, tp2.normalize)
+
+ case (PolyType(_, _), MethodType(params, _)) if params exists (_.tpe.isWildcard) =>
+ false // don't warn on HasMethodMatching on right hand side
+
case (ntp1, ntp2) =>
- if (isDummyAppliedType(ntp1) || isDummyAppliedType(ntp2)) {
- devWarning(s"isHKSubType0($tp1, $tp2, _) contains dummy typeref: ($ntp1, $ntp2)")
- }
+ devWarning(s"isHKSubType0($tp1, $tp2, _) is ${tp1.getClass}, ${tp2.getClass}: ($ntp1, $ntp2)")
false // @assume !tp1.isHigherKinded || !tp2.isHigherKinded
// --> thus, cannot be subtypes (Any/Nothing has already been checked)
}))
@@ -5650,11 +5652,7 @@ trait Types extends api.Types { self: SymbolTable =>
if (tp1 eq NoPrefix) return (tp2 eq NoPrefix) || tp2.typeSymbol.isPackageClass // !! I do not see how the "isPackageClass" would be warranted by the spec
if (tp2 eq NoPrefix) return tp1.typeSymbol.isPackageClass
if (isSingleType(tp1) && isSingleType(tp2) || isConstantType(tp1) && isConstantType(tp2)) return tp1 =:= tp2
- if (tp1.isHigherKinded && tp2.isHigherKinded) return isHKSubType0(tp1, tp2, depth)
- if (tp1.isHigherKinded || tp2.isHigherKinded) {
- devWarning(s"isSubType2($tp1, $tp2, _) compares HK type with proper type")
- return isHKSubType0(tp1, tp2, depth)
- }
+ if (tp1.isHigherKinded || tp2.isHigherKinded) return isHKSubType0(tp1, tp2, depth)
/** First try, on the right:
* - unwrap Annotated types, BoundedWildcardTypes,
diff --git a/test/files/pos/kinds.scala b/test/files/pos/kinds.scala
new file mode 100644
index 0000000000..6d6da0c8b6
--- /dev/null
+++ b/test/files/pos/kinds.scala
@@ -0,0 +1,13 @@
+trait IllKind1 {
+ def g(s: String): String = s
+ def f: String = ???
+ def f[C](c: C): String = g(f)
+}
+
+trait IllKind2 {
+ def b1: Char = ???
+ def b2: Byte = ???
+
+ def f1 = "abc" contains b1
+ def f2 = "abc" contains b2
+}
diff --git a/test/pending/pos/those-kinds-are-high.scala b/test/pending/pos/those-kinds-are-high.scala
index 434e64cefb..78367cb746 100644
--- a/test/pending/pos/those-kinds-are-high.scala
+++ b/test/pending/pos/those-kinds-are-high.scala
@@ -4,18 +4,18 @@ class A {
class C1[T] extends Template[C1] with Container[T]
class C2[T] extends Template[C2] with Container[T]
-
+
/** Target expression:
* List(new C1[String], new C2[String])
*/
-
+
// Here's what would ideally be inferred.
//
// scala> :type List[Template[Container] with Container[String]](new C1[String], new C2[String])
// List[Template[Container] with Container[java.lang.String]]
//
// Here's what it does infer.
- //
+ //
// scala> :type List(new C1[String], new C2[String])
// <console>:8: error: type mismatch;
// found : C1[String]
@@ -43,11 +43,54 @@ class A {
// def fFail = List(new C1[String], new C2[String])
// ^
// two errors found
-
+
/** Working version explicitly typed.
*/
def fExplicit = List[Template[Container] with Container[String]](new C1[String], new C2[String])
-
+
// nope
def fFail = List(new C1[String], new C2[String])
}
+
+
+trait Other {
+ trait GenBar[+A]
+ trait Bar[+A] extends GenBar[A]
+ trait Templ[+A, +CC[X] <: GenBar[X]]
+
+ abstract class CC1[+A] extends Templ[A, CC1] with Bar[A]
+ abstract class CC2[+A] extends Templ[A, CC2] with Bar[A]
+
+ // Compiles
+ class A1 {
+ abstract class BarFactory[CC[X] <: Bar[X]]
+
+ def f(x: Boolean) = if (x) (null: BarFactory[CC1]) else (null: BarFactory[CC2])
+ }
+
+ // Fails - only difference is CC covariant.
+ class A2 {
+ abstract class BarFactory[+CC[X] <: Bar[X]]
+
+ def f(x: Boolean) = if (x) (null: BarFactory[CC1]) else (null: BarFactory[CC2])
+ // c.scala:23: error: kinds of the type arguments (Bar with Templ[Any,Bar]) do not conform to the expected kinds of the type parameters (type CC) in class BarFactory.
+ // Bar with Templ[Any,Bar]'s type parameters do not match type CC's expected parameters:
+ // <empty> has no type parameters, but type CC has one
+ // def f(x: Boolean) = if (x) (null: BarFactory[CC1]) else (null: BarFactory[CC2])
+ // ^
+ // one error found
+ }
+
+ // Compiles - CC contravariant.
+ class A3 {
+ abstract class BarFactory[-CC[X] <: Bar[X]] // with Templ[X, CC]]
+
+ def f(x: Boolean) = if (x) (null: BarFactory[CC1]) else (null: BarFactory[CC2])
+ // c.scala:23: error: kinds of the type arguments (Bar with Templ[Any,Bar]) do not conform to the expected kinds of the type parameters (type CC) in class BarFactory.
+ // Bar with Templ[Any,Bar]'s type parameters do not match type CC's expected parameters:
+ // <empty> has no type parameters, but type CC has one
+ // def f(x: Boolean) = if (x) (null: BarFactory[CC1]) else (null: BarFactory[CC2])
+ // ^
+ // one error found
+ }
+}