summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksandar Prokopec <axel22@gmail.com>2012-06-18 19:33:06 +0200
committerAleksandar Prokopec <axel22@gmail.com>2012-06-18 19:33:06 +0200
commita83586a4815acd35df0801ed0e9f067e113c8664 (patch)
treef0efc810997d6d4089dadd5c443a00c10a63d09d
parent9a28ee1ffc085bc680c48b12ad632b9133adf020 (diff)
downloadscala-a83586a4815acd35df0801ed0e9f067e113c8664.tar.gz
scala-a83586a4815acd35df0801ed0e9f067e113c8664.tar.bz2
scala-a83586a4815acd35df0801ed0e9f067e113c8664.zip
Fix SI-4541.
Catch type errors when duplicating trees. In this case, to access a protected member from a specialized class is an error, so we would have to make the member public anyway. Better it is then to report an error and have the user make the field public explicitly. Review by @dragos.
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala19
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Duplicators.scala2
-rw-r--r--test/files/neg/t4541.check7
-rw-r--r--test/files/neg/t4541.scala16
-rw-r--r--test/files/neg/t4541b.check7
-rw-r--r--test/files/neg/t4541b.scala16
6 files changed, 62 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 4b488a6437..c4c769d7cf 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -1448,20 +1448,29 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case ddef @ DefDef(_, _, _, vparamss, _, _) if info.isDefinedAt(symbol) =>
// log("--> method: " + ddef + " in " + ddef.symbol.owner + ", " + info(symbol))
+ def reportTypeError(body: =>Tree) =
+ try body
+ catch {
+ case te: TypeError =>
+ reporter.error(te.pos, te.toString)
+ ddef
+ }
if (symbol.isConstructor) {
val t = atOwner(symbol)(forwardCtorCall(tree.pos, gen.mkSuperSelect, vparamss, symbol.owner))
if (symbol.isPrimaryConstructor)
localTyper.typedPos(symbol.pos)(deriveDefDef(tree)(_ => Block(List(t), Literal(Constant()))))
- else // duplicate the original constructor
- duplicateBody(ddef, info(symbol).target)
+ else // duplicate the original constructor
+ reportTypeError(duplicateBody(ddef, info(symbol).target))
}
else info(symbol) match {
case Implementation(target) =>
assert(body.isDefinedAt(target), "sym: " + symbol.fullName + " target: " + target.fullName)
// we have an rhs, specialize it
- val tree1 = duplicateBody(ddef, target)
+ val tree1 = reportTypeError {
+ duplicateBody(ddef, target)
+ }
debuglog("implementation: " + tree1)
deriveDefDef(tree1)(transform)
@@ -1472,7 +1481,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
else {
// we have an rhs, specialize it
- val tree1 = duplicateBody(ddef, target)
+ val tree1 = reportTypeError {
+ duplicateBody(ddef, target)
+ }
debuglog("implementation: " + tree1)
deriveDefDef(tree1)(transform)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
index b7a6ea677e..6386273c9d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
@@ -360,7 +360,7 @@ abstract class Duplicators extends Analyzer {
tree
case _ =>
- debuglog("Duplicators default case: " + tree.summaryString)
+ // log("Duplicators default case: " + tree.summaryString + " -> " + tree)
if (tree.hasSymbol && tree.symbol != NoSymbol && (tree.symbol.owner == definitions.AnyClass)) {
tree.symbol = NoSymbol // maybe we can find a more specific member in a subclass of Any (see AnyVal members, like ==)
}
diff --git a/test/files/neg/t4541.check b/test/files/neg/t4541.check
new file mode 100644
index 0000000000..c01226685f
--- /dev/null
+++ b/test/files/neg/t4541.check
@@ -0,0 +1,7 @@
+t4541.scala:11: error: scala.reflect.internal.Types$TypeError: variable data in class Sparse cannot be accessed in Sparse[Int]
+ Access to protected method data not permitted because
+ prefix type Sparse[Int] does not conform to
+ class Sparse$mcI$sp where the access take place
+ that.data
+ ^
+one error found \ No newline at end of file
diff --git a/test/files/neg/t4541.scala b/test/files/neg/t4541.scala
new file mode 100644
index 0000000000..744af1c288
--- /dev/null
+++ b/test/files/neg/t4541.scala
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+@SerialVersionUID(1L)
+final class Sparse[@specialized(Int) T](d: Array[T]) extends Serializable {
+ protected var data: Array[T] = d
+ def set(that: Sparse[T]) = {
+ that.data
+ }
+}
+
+
+
diff --git a/test/files/neg/t4541b.check b/test/files/neg/t4541b.check
new file mode 100644
index 0000000000..54d9c3d1ee
--- /dev/null
+++ b/test/files/neg/t4541b.check
@@ -0,0 +1,7 @@
+t4541b.scala:13: error: scala.reflect.internal.Types$TypeError: variable data in class SparseArray cannot be accessed in SparseArray[Int]
+ Access to protected method data not permitted because
+ prefix type SparseArray[Int] does not conform to
+ class SparseArray$mcI$sp where the access take place
+ use(that.data.clone)
+ ^
+one error found \ No newline at end of file
diff --git a/test/files/neg/t4541b.scala b/test/files/neg/t4541b.scala
new file mode 100644
index 0000000000..7a21ffc156
--- /dev/null
+++ b/test/files/neg/t4541b.scala
@@ -0,0 +1,16 @@
+
+
+
+
+
+@SerialVersionUID(1L)
+final class SparseArray[@specialized(Int) T](private var data: Array[T]) extends Serializable {
+ def use(inData: Array[T]) = {
+ data = inData;
+ }
+
+ def set(that: SparseArray[T]) = {
+ use(that.data.clone)
+ }
+}
+