summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2009-11-12 16:56:33 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2009-11-12 16:56:33 +0000
commite7bc7737c72dff381cfc93d2387a66565de1968b (patch)
tree826301c369d46c08795daa0cdef9995d82b3e642
parentfe1d0c7052279ddf9cacfd1a7160cbee5829a4cc (diff)
downloadscala-e7bc7737c72dff381cfc93d2387a66565de1968b.tar.gz
scala-e7bc7737c72dff381cfc93d2387a66565de1968b.tar.bz2
scala-e7bc7737c72dff381cfc93d2387a66565de1968b.zip
fixed #2454
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala42
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala25
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
-rw-r--r--test/files/pos/t2305.scala26
-rw-r--r--test/files/pos/t2454.scala25
7 files changed, 105 insertions, 27 deletions
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index 0f59d9a3d9..5db78420ec 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -836,7 +836,6 @@ trait ScalacSettings {
val Ytyperdebug = BooleanSetting ("-Ytyper-debug", "Trace all type assignements")
val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.")
val Ytailrec = BooleanSetting ("-Ytailrecommend", "Alert methods which would be tail-recursive if private or final.")
- val YhigherKindedRaw = BooleanSetting ("-Yhigher-kinded-raw", "(temporary!) Treat raw Java types as higher-kinded types.")
val Yjenkins = BooleanSetting ("-Yjenkins-hashCodes", "Use jenkins hash algorithm for case class generated hashCodes.")
// Warnings
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 7e16d1dc9b..e4cbe159a1 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -885,6 +885,48 @@ trait Symbols {
infos ne null
}
+ /** Modify term symbol's type so that a raw type C is converted to an existential C[_]
+ *
+ * This is done in checkAccessible and overriding checks in refchecks
+ * We can't do this on class loading because it would result in infinite cycles.
+ */
+ private var triedCooking: Boolean = false
+ final def cookJavaRawInfo() {
+ require(isTerm)
+ // println("cookJavaRawInfo: "+(rawname, triedCooking))
+
+ if(triedCooking) return else triedCooking = true // only try once...
+
+ def cook(sym: Symbol) {
+ require(sym hasFlag JAVA)
+ // @M: I think this is more desirable, but Martin prefers to leave raw-types as-is as much as possible
+ // object rawToExistentialInJava extends TypeMap {
+ // def apply(tp: Type): Type = tp match {
+ // // any symbol that occurs in a java sig, not just java symbols
+ // // see http://lampsvn.epfl.ch/trac/scala/ticket/2454#comment:14
+ // case TypeRef(pre, sym, List()) if !sym.typeParams.isEmpty =>
+ // val eparams = typeParamsToExistentials(sym, sym.typeParams)
+ // existentialAbstraction(eparams, TypeRef(pre, sym, eparams map (_.tpe)))
+ // case _ =>
+ // mapOver(tp)
+ // }
+ // }
+ val tpe1 = rawToExistential(sym.tpe)
+ // println("cooking: "+ sym +": "+ sym.tpe +" to "+ tpe1)
+ if (tpe1 ne sym.tpe) {
+ sym.setInfo(tpe1)
+ }
+ }
+
+ if (hasFlag(JAVA))
+ cook(this)
+ else if (hasFlag(OVERLOADED))
+ for (sym2 <- alternatives)
+ if (sym2 hasFlag JAVA)
+ cook(sym2)
+ }
+
+
/** The type constructor of a symbol is:
* For a type symbol, the type corresponding to the symbol itself,
* excluding parameters.
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 9727f6aa5d..6145c4a0d7 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1600,12 +1600,11 @@ A type's typeSymbol should never be inspected directly.
override def typeConstructor = rawTypeRef(pre, sym, List())
- // (args.isEmpty && !typeParamsDirect.isEmpty) && !isRawType(this)
- // check for isRawType: otherwise raw types are considered higher-kinded types during subtyping:
- override def isHigherKinded
- = (args.isEmpty && !typeParamsDirect.isEmpty) && (settings.YhigherKindedRaw.value || !isRaw(sym, args))
- // (args.isEmpty && !typeParamsDirect.isEmpty) && (phase.erasedTypes || !sym.hasFlag(JAVA))
-
+ // a reference (in a Scala program) to a type that has type parameters, but where the reference does not include type arguments
+ // note that it doesn't matter whether the symbol refers to a java or scala symbol,
+ // it does matter whether it occurs in java or scala code
+ // typerefs w/o type params that occur in java signatures/code are considered raw types, and are represented as existential types
+ override def isHigherKinded = (args.isEmpty && !typeParamsDirect.isEmpty)
override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type =
if (isHigherKinded) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 898ad238a1..0c3e34f8c5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -356,6 +356,8 @@ trait Infer {
context.unit.depends += sym.toplevelClass
val sym1 = sym filter (alt => context.isAccessible(alt, pre, site.isInstanceOf[Super]))
+ // Console.println("check acc " + (sym, sym1) + ":" + (sym.tpe, sym1.tpe) + " from " + pre);//DEBUG
+
if (sym1 == NoSymbol) {
if (settings.debug.value) {
Console.println(context)
@@ -364,26 +366,9 @@ trait Infer {
}
accessError("")
} else {
- // Modify symbol's type so that raw types C
- // are converted to existentials C[T] forSome { type T }.
- // We can't do this on class loading because it would result
- // in infinite cycles.
- def cook(sym: Symbol) {
- val tpe1 = rawToExistential(sym.tpe)
- if (tpe1 ne sym.tpe) {
- if (settings.debug.value) println("cooked: "+sym+":"+sym.tpe)
- sym.setInfo(tpe1)
- }
- }
- if (sym1.isTerm) {
- if (sym1 hasFlag JAVA)
- cook(sym1)
- else if (sym1 hasFlag OVERLOADED)
- for (sym2 <- sym1.alternatives)
- if (sym2 hasFlag JAVA)
- cook(sym2)
- }
- //Console.println("check acc " + sym1 + ":" + sym1.tpe + " from " + pre);//DEBUG
+ if(sym1.isTerm)
+ sym1.cookJavaRawInfo() // xform java rawtypes into existentials
+
var owntype = try{
pre.memberType(sym1)
} catch {
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index aaefab1f74..9b8be2aaec 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -370,6 +370,8 @@ abstract class RefChecks extends InfoTransform {
kindErrors.toList.mkString("\n", ", ", ""))
}
} else if (other.isTerm) {
+ other.cookJavaRawInfo() // #2454
+
if (!overridesType(self.memberInfo(member), self.memberInfo(other))) { // 8
overrideTypeError()
explainTypes(self.memberInfo(member), self.memberInfo(other))
diff --git a/test/files/pos/t2305.scala b/test/files/pos/t2305.scala
new file mode 100644
index 0000000000..8b5abccbe0
--- /dev/null
+++ b/test/files/pos/t2305.scala
@@ -0,0 +1,26 @@
+import java.util.ArrayList
+
+trait Bind[Z[_]]
+
+class MySerializable[X] extends java.io.Serializable
+
+object Bind {
+ implicit val JavaArrayListBind: Bind[ArrayList] = new Bind[ArrayList] {}
+ implicit val MySerializableBind: Bind[MySerializable] = new Bind[MySerializable] {}
+}
+
+object works {
+ // this works fine:
+ def runbind(implicit bind: Bind[MySerializable]) {}
+ runbind
+}
+
+object breaks {
+ def runbind(implicit bind: Bind[ArrayList]) {}
+ runbind
+ /*java.lang.AssertionError: assertion failed: java.io.Serializable
+ at scala.Predef$.assert(Predef.scala:107)
+ at scala.tools.nsc.symtab.Types$TypeRef.transform(Types.scala:1417)
+ at scala.tools.nsc.symtab.Types$TypeRef.baseType(Types.scala:1559)
+ */
+}
diff --git a/test/files/pos/t2454.scala b/test/files/pos/t2454.scala
new file mode 100644
index 0000000000..00f2e6f677
--- /dev/null
+++ b/test/files/pos/t2454.scala
@@ -0,0 +1,25 @@
+package am;
+
+trait One[M[_]] {
+ val x : Int
+}
+
+trait Two[M[_,_]] {
+ val x : Int
+}
+
+object Test {
+ // Works.
+ val x = new Two[Map] {
+ val x = 5
+ }
+
+ val o = new One[java.util.List] {
+ val x = 1
+ }
+
+ // Does not work
+ val y = new Two[java.util.concurrent.ConcurrentHashMap] {
+ val x = 3
+ }
+}