Skip to content

Commit db5919a

Browse files
committed
Merge pull request scala#2100 from paulp/pr/fix-super-varargs-saved
Fixing binary compat for $super regression
2 parents 23b69c1 + 13caa49 commit db5919a

File tree

6 files changed

+121
-4
lines changed

6 files changed

+121
-4
lines changed

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2037,7 +2037,7 @@ trait Typers extends Modes with Adaptations with Tags {
20372037
val alias = (
20382038
superAcc.initialize.alias
20392039
orElse (superAcc getter superAcc.owner)
2040-
filter (alias => superClazz.info.nonPrivateMember(alias.name) != alias)
2040+
filter (alias => superClazz.info.nonPrivateMember(alias.name) == alias)
20412041
)
20422042
if (alias.exists && !alias.accessed.isVariable) {
20432043
val ownAcc = clazz.info decl name suchThat (_.isParamAccessor) match {
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package scala.tools.partest
2+
3+
import scala.collection.JavaConverters._
4+
import scala.tools.asm
5+
import asm._
6+
import asm.tree._
7+
import java.lang.reflect.Modifier
8+
9+
sealed trait AsmNode[+T] {
10+
def node: T
11+
def access: Int
12+
def desc: String
13+
def name: String
14+
def signature: String
15+
def attrs: List[Attribute]
16+
def visibleAnnotations: List[AnnotationNode]
17+
def invisibleAnnotations: List[AnnotationNode]
18+
def characteristics = f"$name%15s $desc%-30s$accessString$sigString"
19+
20+
private def accessString = if (access == 0) "" else " " + Modifier.toString(access)
21+
private def sigString = if (signature == null) "" else " " + signature
22+
override def toString = characteristics
23+
}
24+
25+
object AsmNode {
26+
type AsmMethod = AsmNode[MethodNode]
27+
type AsmField = AsmNode[FieldNode]
28+
type AsmMember = AsmNode[_]
29+
30+
implicit class ClassNodeOps(val node: ClassNode) {
31+
def fieldsAndMethods: List[AsmMember] = {
32+
val xs: List[AsmMember] = (
33+
node.methods.asScala.toList.map(x => (x: AsmMethod))
34+
++ node.fields.asScala.toList.map(x => (x: AsmField))
35+
)
36+
xs sortBy (_.characteristics)
37+
}
38+
}
39+
implicit class AsmMethodNode(val node: MethodNode) extends AsmNode[MethodNode] {
40+
def access: Int = node.access
41+
def desc: String = node.desc
42+
def name: String = node.name
43+
def signature: String = node.signature
44+
def attrs: List[Attribute] = node.attrs.asScala.toList
45+
def visibleAnnotations: List[AnnotationNode] = node.visibleAnnotations.asScala.toList
46+
def invisibleAnnotations: List[AnnotationNode] = node.invisibleAnnotations.asScala.toList
47+
}
48+
implicit class AsmFieldNode(val node: FieldNode) extends AsmNode[FieldNode] {
49+
def access: Int = node.access
50+
def desc: String = node.desc
51+
def name: String = node.name
52+
def signature: String = node.signature
53+
def attrs: List[Attribute] = node.attrs.asScala.toList
54+
def visibleAnnotations: List[AnnotationNode] = node.visibleAnnotations.asScala.toList
55+
def invisibleAnnotations: List[AnnotationNode] = node.invisibleAnnotations.asScala.toList
56+
}
57+
58+
def apply(node: MethodNode): AsmMethodNode = new AsmMethodNode(node)
59+
def apply(node: FieldNode): AsmFieldNode = new AsmFieldNode(node)
60+
}

src/partest/scala/tools/partest/BytecodeTest.scala

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ package scala.tools.partest
33
import scala.tools.nsc.util.JavaClassPath
44
import scala.collection.JavaConverters._
55
import scala.tools.asm
6-
import asm.ClassReader
6+
import asm.{ ClassReader }
77
import asm.tree.{ClassNode, MethodNode, InsnList}
88
import java.io.InputStream
9+
import AsmNode._
910

1011
/**
1112
* Provides utilities for inspecting bytecode using ASM library.
@@ -29,21 +30,47 @@ import java.io.InputStream
2930
*
3031
*/
3132
abstract class BytecodeTest extends ASMConverters {
33+
import instructions._
3234

3335
/** produce the output to be compared against a checkfile */
3436
protected def show(): Unit
3537

3638
def main(args: Array[String]): Unit = show
3739

38-
// asserts
40+
// asserts
3941
def sameBytecode(methA: MethodNode, methB: MethodNode) = {
4042
val isa = instructions.fromMethod(methA)
4143
val isb = instructions.fromMethod(methB)
4244
if (isa == isb) println("bytecode identical")
4345
else diffInstructions(isa, isb)
4446
}
4547

46-
import instructions._
48+
// Do these classes have all the same methods, with the same names, access,
49+
// descriptors and generic signatures? Method bodies are not considered, and
50+
// the names of the classes containing the methods are substituted so they do
51+
// not appear as differences.
52+
def sameMethodAndFieldSignatures(clazzA: ClassNode, clazzB: ClassNode): Boolean = {
53+
val ms1 = clazzA.fieldsAndMethods.toIndexedSeq
54+
val ms2 = clazzB.fieldsAndMethods.toIndexedSeq
55+
val name1 = clazzA.name
56+
val name2 = clazzB.name
57+
58+
if (ms1.length != ms2.length) {
59+
println("Different member counts in $name1 and $name2")
60+
false
61+
}
62+
else (ms1, ms2).zipped forall { (m1, m2) =>
63+
val c1 = m1.characteristics
64+
val c2 = m2.characteristics.replaceAllLiterally(name2, name1)
65+
if (c1 == c2)
66+
println(s"[ok] $m1")
67+
else
68+
println(s"[fail]\n in $name1: $c1\n in $name2: $c2")
69+
70+
c1 == c2
71+
}
72+
}
73+
4774
// bytecode is equal modulo local variable numbering
4875
def equalsModuloVar(a: Instruction, b: Instruction) = (a, b) match {
4976
case _ if a == b => true

test/files/run/t7106.check

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[ok] q1 I private final
2+
[ok] q3 I private final
3+
[ok] <init> (III)V public
4+
[ok] bippy1 ()I public
5+
[ok] bippy2 ()I public
6+
[ok] bippy3 ()I public
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
abstract class Base0 { def p2: Int }
3+
class Base(p1: Int, override val p2: Int) extends Base0
4+
5+
abstract class Sub1(q1: Int, q2: Int, q3: Int) extends Base(q1, q2) {
6+
def bippy1 = q1
7+
def bippy2 = q2
8+
def bippy3 = q3
9+
}
10+
abstract class Sub2(q1: Int, q2: Int, q3: Int) extends Base(q1, q2) {
11+
def bippy1 = q1
12+
def bippy2 = p2
13+
def bippy3 = q3
14+
}

test/files/run/t7106/test.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import scala.tools.partest.BytecodeTest
2+
3+
object Test extends BytecodeTest {
4+
def show {
5+
val node1 = loadClassNode("Sub1")
6+
val node2 = loadClassNode("Sub2")
7+
8+
sameMethodAndFieldSignatures(node1, node2)
9+
}
10+
}

0 commit comments

Comments
 (0)