From a8fe8292956f73db3b185bf29d6349f2eb1c3df8 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Mon, 14 Jan 2013 23:29:51 -0800 Subject: 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. --- .../scala/tools/nsc/typechecker/Infer.scala | 2 + src/reflect/scala/reflect/internal/Types.scala | 14 +++--- test/files/pos/kinds.scala | 13 ++++++ test/pending/pos/those-kinds-are-high.scala | 53 ++++++++++++++++++++-- 4 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 test/files/pos/kinds.scala 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]) // :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: + // 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: + // 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 + } +} -- cgit v1.2.3