Skip to content
This repository was archived by the owner on Sep 1, 2020. It is now read-only.

Commit aca8f96

Browse files
committed
SI-9286 Check subclass privates for "same type after erasure"
The overriding pairs cursor used to detect erased signature clashes was turning a blind eye to any pair that contained a private method. However, this could lead to a `VerifyError` or `IllegalAccessError`. Checking against javac's behaviour in both directions: ``` % cat sandbox/Test.java public abstract class Test { class C { int foo() { return 0; } } class D extends C { private <A> int foo() { return 1; } } } % javac sandbox/Test.java sandbox/Test.java:3: error: name clash: <A>foo() in Test.D and foo() in Test.C have the same erasure, yet neither overrides the other class D extends C { private <A> int foo() { return 1; } } ^ where A is a type-variable: A extends Object declared in method <A>foo() 1 error ``` ``` % cat sandbox/Test.java public abstract class Test { class C { private int foo() { return 0; } } class D extends C { <A> int foo() { return 1; } } } % javac sandbox/Test.java % ``` This commit only the exludes private symbols from the superclass from the checks by moving the test from `excludes` to `matches`.
1 parent 2f1b525 commit aca8f96

File tree

7 files changed

+54
-2
lines changed

7 files changed

+54
-2
lines changed

src/compiler/scala/tools/nsc/transform/Erasure.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -814,11 +814,10 @@ abstract class Erasure extends AddInterfaces
814814
// specialized members have no type history before 'specialize', causing double def errors for curried defs
815815
override def exclude(sym: Symbol): Boolean = (
816816
sym.isType
817-
|| sym.isPrivate
818817
|| super.exclude(sym)
819818
|| !sym.hasTypeAt(currentRun.refchecksPhase.id)
820819
)
821-
override def matches(lo: Symbol, high: Symbol) = true
820+
override def matches(lo: Symbol, high: Symbol) = !high.isPrivate
822821
}
823822
def isErasureDoubleDef(pair: SymbolPair) = {
824823
import pair._

test/files/neg/t9286a.check

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
t9286a.scala:6: error: name clash between defined and inherited member:
2+
def foo(o: (String,)): Unit in class T and
3+
private def foo(o: (Any,)): Unit at line 6
4+
have same type after erasure: (o: Tuple1)Unit
5+
private def foo(o: Tuple1[Any]) = ()
6+
^
7+
one error found

test/files/neg/t9286a.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class T {
2+
def foo(o: Tuple1[String]) = ()
3+
}
4+
5+
class U extends T {
6+
private def foo(o: Tuple1[Any]) = ()
7+
}
8+
9+
object Test {
10+
def main(args: Array[String]): Unit = {
11+
new U().foo(null) // IllegalAccessError: tried to access method U.foo(Lscala/Tuple1;)V from class Test$
12+
}
13+
}

test/files/neg/t9286b.check

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
t9286b.scala:2: error: name clash between defined and inherited member:
2+
def foo: Int in class C and
3+
private def foo[A]: Int at line 2
4+
have same type after erasure: ()Int
5+
class D extends C { private def foo[A] = 0 }
6+
^
7+
one error found

test/files/neg/t9286b.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class C { def foo = 0 }
2+
class D extends C { private def foo[A] = 0 }
3+
4+
class E { private def foo = 0 }
5+
class F extends E { def foo[A] = 0 } // okay

test/files/neg/t9286c.check

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
t9286c.scala:8: error: name clash between defined and inherited member:
2+
def foo(m: M[_ >: String]): Int in trait T and
3+
private def foo(m: M[_ >: Any]): Int at line 8
4+
have same type after erasure: (m: M)Int
5+
def foo(m: M[_ >: Any]) = 0 // Expected: "same type after erasure"
6+
^
7+
one error found

test/files/neg/t9286c.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class M[_]
2+
trait T {
3+
def foo(m: M[_ >: String]) = 42
4+
}
5+
6+
object Test {
7+
def t: T = new T {
8+
def foo(m: M[_ >: Any]) = 0 // Expected: "same type after erasure"
9+
}
10+
def main(args: Array[String]): Unit = {
11+
val m: M[String] = null
12+
t.foo(m) // VeriyError: Duplicate method name&signature
13+
}
14+
}

0 commit comments

Comments
 (0)