bug icon indicating copy to clipboard operation
bug copied to clipboard

ClassFormatError with local definitions

Open scabug opened this issue 14 years ago • 10 comments

The following produces a bad classfile, both with 2.9.1 and latest nightly.

object test {
  def main(args: Array[String]): Unit = {
    var out = 1
    trait Trait {
      def foo(): Unit = {
        out += 1
      }
    }
    case class C(parent: Trait) extends Trait {}
    C(null)
  }
} 

test.main(Array())

Error is: java.lang.ClassFormatError: Duplicate field name&signature in class file test$C$2

scabug avatar Nov 30 '11 07:11 scabug

Imported From: https://issues.scala-lang.org/browse/SI-5252?orig=1 Reporter: @lrytz Affected Versions: 2.11.0-M8, 2.12.0 See #1960, #3994

scabug avatar Nov 30 '11 07:11 scabug

@lrytz said: that's the only other ticket that has the same error message

scabug avatar Nov 30 '11 07:11 scabug

@retronym said: Reduced a step or two:


object Test {

  {
    val out = 0
    trait Trait {
      def foo {
        out
      }
    }

    class C extends Trait {
      def copy { new C }
    }

    new C
  }

  def main(args: Array[String]) {
  }
}

scabug avatar May 20 '12 08:05 scabug

@retronym said: Seems to be a regression fro 2.7.7 to 2.8.0.

scabug avatar May 20 '12 09:05 scabug

@magarciaEPFL said: Right after flatten there are two field declarations with the same name and type (val out$1: Int = _; ), one each in the following classes:

  • class Test$C$1 extends Object with Test$Trait$1
  • abstract trait Test$Trait$1$class extends Object with Test$Trait$1
  class Test$C$1 extends Object with Test$Trait$1 {
    def copy(): Unit = {
      new Test$C$1(Test$C$1.this.out$1);
      ()
    };
    <synthetic> <paramaccessor> private[this] val out$1: Int = _; /* <---------------- in the composed class */
    def <init>(out$1: Int): Test$C$1 = {
      Test$C$1.this.out$1 = out$1;
      Test$C$1.super.<init>();
      Test$C$1.this.$asInstanceOf[Test$Trait$1$class]()./*Test$Trait$1$class*/$init$(out$1);
      ()
    }
  };
  abstract trait Test$Trait$1$class extends Object with Test$Trait$1 {
    def foo(): Unit = {
      Test$Trait$1$class.this.out$1;
      ()
    };
    <synthetic> <paramaccessor> private[this] val out$1: Int = _; /* <---------------- in the implementation class */
    def /*Test$Trait$1$class*/$init$(out$1: Int): Unit = {
      Test$Trait$1$class.this.out$1 = out$1;
      ()
    }
  }

The Mixin phase lumps both fields in class Test$C$1

  class Test$C$1 extends Object with Test$Trait$1 {

    <synthetic> <stable> <accessor> <paramaccessor> def out$1(): Int = Test$C$1.this.out$1;  /* <---------------- (1 of 2)  */

    private[this] val out$1: Int = _;
    <synthetic> <accessor> <paramaccessor> def Test$Trait$1$_setter_$out$1_=(x$1: Int): Unit = Test$C$1.this.out$1 = x$1;
    def foo(): Unit = Test$Trait$1$class.foo(Test$C$1.this);
    def copy(): Unit = {
      new Test$C$1(Test$C$1.this.out$1);
      ()
    };

    <synthetic> <paramaccessor> private[this] val out$1: Int = _;                            /* <---------------- (2 of 2)  */

    def <init>(out$1: Int): Test$C$1 = {
      Test$C$1.this.out$1 = out$1;
      Test$C$1.super.<init>();
      Test$Trait$1$class./*Test$Trait$1$class*/$init$(Test$C$1.this, out$1);
      ()
    }
  }

That's why javap -private Test\$C\$1 shows:

public class Test$C$1 extends java.lang.Object implements Test$Trait$1{
    private final int out$1;
    private final int out$1;
    public int out$1();
    public void Test$Trait$1$_setter_$out$1_$eq(int);
    public void foo();
    public void copy();
    public Test$C$1(int);
}

scabug avatar Jun 05 '12 13:06 scabug

@retronym said: More mangling seems to be called for here. Might be worth considering #3994 at the same time.

scabug avatar Jun 11 '12 06:06 scabug

@lrytz said: 2.12.0-RC1 gives an error message:

A.scala:60: error: parameter 'out$1' requires field but conflicts with value out$1 in trait Trait$1
    var out = 1
        ^
one error found

scabug avatar Sep 26 '16 09:09 scabug

@lrytz said: Another test case: http://stackoverflow.com/questions/39635543/method-in-sealed-trait-gives-duplicate-field-name-signature-in-class-file

scabug avatar Sep 26 '16 09:09 scabug

Just want to chime in that I am getting the "duplicate field name&signature" issue in Scala 2.12.x with code that has worked flawlessly for a long time in Scala 2.11.x. Things seems to be worse in 2.12 than they were in 2.11.

sarahgerweck avatar Apr 18 '17 23:04 sarahgerweck

#8984 has an additional reproduction

SethTisue avatar Mar 25 '24 14:03 SethTisue