Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AbstractMethodError caused by bad signature on bridge methods #7535

Open
scabug opened this issue May 30, 2013 · 7 comments
Open

AbstractMethodError caused by bad signature on bridge methods #7535

scabug opened this issue May 30, 2013 · 7 comments
Milestone

Comments

@scabug
Copy link

scabug commented May 30, 2013

This one is from the mailing list

object XXXXX {
  
  trait Def {
    type Element >: Null <: Elt
    type Info
    trait Elt { self:Element=>
      def foo():Int
    }
    trait EltBuilder {
      def apply(i: Info): Element
    }
    trait Impl {
      val core:Def.this.type = Def.this
      type Elt        = core.Elt
      type Element    = core.Element
      type Info       = core.Info
      type EltBuilder = core.EltBuilder
      type Elt0 <: Element
      def builder:EltBuilder
    }
    trait Motor extends Impl with DefMotor
  }
  trait DefMotor { self:Def#Impl=>
    def foo(m:Element):Int
    trait Proc { this:Element=>
      def foo():Int = self.foo(this)
    }
  }
  
  class Info1(val name:String)
  trait Def1 extends Def {
    type Info <: Info1
    trait Elt extends super.Elt { this:Element=>
      def name:String
    }
    trait Element extends Elt
    trait Motor extends super.Motor with Def1Motor
  }
  trait Def1Motor extends DefMotor { this:Def1#Impl=>
    class Elt0(val name: String) extends core.Element with Proc
  }
  
  trait Def2[+Data] extends Def1 {
    trait Elt extends super.Elt { this:Element=>
      def data:Data
      def getData(i:Info):Data
    }
    trait Element extends super.Element with Elt
    trait Motor extends super.Motor with Def2Motor[Data]
  }
  trait Def2Motor[+Data] extends Def1Motor { self:Def2[Data]#Impl=>
    def getData(parent:Element,i:Info):Data
    class Elt0(name: String, val data:Data) extends super.Elt0(name) with core.Element {
      def getData(i:Info):Data = self.getData(this,i)
    }
  }
  
  class Info3(name:String,val length:Int) extends Info1(name)
  trait Def3[+Data] extends Def2[Data] {
    type Info <: Info3
    trait Elt extends super.Elt { this:Element=>
      def get:Int
    }
    trait Element extends super.Element with Elt
    trait Motor extends super.Motor with Def3Motor[Data]
  }
  trait Def3Motor[+Data] extends Def2Motor[Data] { self:Def3[Data]#Impl=>
    class Elt0(name: String, data:Data) extends super.Elt0(name, data) with core.Element {
      def get:Int = name.length
    }
    val builder = new EltBuilder {
      def apply(i:Info) = new Elt0(i.name,null.asInstanceOf[Data])
    }
  }
  
  object App extends Def3[String] {
    type Info = Info3
  }
  class App extends App.Motor {
    def foo(e:Element)                   = e.data.length+e.name.length
    def getData(e:Element,i:Info):String = e.name+i.length
  }
  
  def main(args:Array[String]) {
    val app = new App
    val t0 = new app.Elt0("coucou","abc")
    val t1 = new app.Elt0("hello","def")
    println(t0.getData(new Info3("azerty",7)))
  }

}

It compiles without error but running causes

java.lang.AbstractMethodError: XXXXX$App.getData(LXXXXX$Def2$Element;LXXXXX$Info1;)Ljava/lang/Object;
	at XXXXX$Def2Motor$Elt0.getData(<console>:60)
	at XXXXX$.main(<console>:94)

I haven't made any attempt to minify yet.

@scabug
Copy link
Author

scabug commented May 30, 2013

Imported From: https://issues.scala-lang.org/browse/SI-7535?orig=1
Reporter: @JamesIry
Assignee: @JamesIry
Affected Versions: 2.10.0
See #7278, #3452

@scabug
Copy link
Author

scabug commented May 31, 2013

@retronym said:
Not sure it if its quite the same, but do take a look at #7278.

@scabug
Copy link
Author

scabug commented May 31, 2013

@retronym said (edited on May 31, 2013 5:06:37 PM UTC):
Here's a smaller example:

trait Def {
  type Element >: Null
  trait Motor {
    type Element = Def.this.Element
  }
}

trait Def2 extends Def {
  trait Element
  trait Motor extends super.Motor {
    def foo(parent: Element): Any
    foo(null)
  }
}

trait Def3 extends Def2 {
  trait Element
  new super.Motor {
    def foo(e:Element): Any = null
  }
}

new Def3 {} // java.lang.AbstractMethodError: Main$$anon$3$Def3$$anon$2.foo(LMain$$anon$3$Def2$Element;)Ljava/lang/Object;

@scabug
Copy link
Author

scabug commented May 31, 2013

@retronym said:
And a safer way to reformulate your code to avoid these problems:

trait Def {
  type Element >: Null
  trait Motor {
    type Element = Def.this.Element
  }
}

trait Def2 extends Def {
  type Element >: Null <: Element2 
  trait Element2
  trait Motor extends super.Motor {
    def foo(parent: Element): Any
    foo(null)
  }
}

trait Def3 extends Def2 {
  type Element >: Null <: Element3
  trait Element3 extends super.Element2
  new super.Motor {
    def foo(e:Element): Any = null
  }
}

new Def3 {}

@scabug
Copy link
Author

scabug commented May 31, 2013

@retronym said:
Marking as a duplicate of #7278; I've added this examples to that ticket.

@som-snytt
Copy link

som-snytt commented Aug 27, 2023

Reopening as one guise (or one guy's) from the umbrella ticket.

Exception in thread "main" java.lang.AbstractMethodError: Receiver class Def3$$anon$1 does not define or inherit an implementation of the resolved method 'abstract java.lang.Object foo(Def2$Element)' of interface Def2$Motor.
        at Def2$Motor.$init$(t7535.scala:15)
        at Def3$$anon$1.<init>(t7535.scala:21)
        at Def3.$init$(t7535.scala:21)

Retronym's example just passed its ten-year best-by date, but it's still fresh.

Repeating in case I pasted it wrong:

// 7278 or 7535

trait Def {
  type Element >: Null
  trait Motor {
    type Element = Def.this.Element
  }
}

trait Def2 extends Def {
  trait Element
  trait Motor extends super.Motor {
    def foo(parent: Element): Any
    foo(null)
  }
}

trait Def3 extends Def2 {
  trait Element // or extends super.Element2, same result.
  new super.Motor {
    def foo(e:Element): Any = null
  }
}

object Test extends App {
  println {
    new Def3 {}
  }
}

@som-snytt som-snytt reopened this Aug 27, 2023
@SethTisue SethTisue added this to the Backlog milestone Aug 27, 2023
@lrytz
Copy link
Member

lrytz commented Aug 28, 2023

It should be an error, probably at trait Def3 which defines type Element to be Def3.Element, different to type Element defined in Def2.

scala> trait A
trait A

scala> trait B extends A
trait B

scala> trait U { type T }
trait U

scala> trait V extends U { type T = A }
trait V

scala> trait W extends V { override type T = A }
trait W

scala> trait W extends V { override type T = B }
                                         ^
       error: incompatible type in overriding
       type T = A (defined in trait V)
          (Equivalent type required when overriding a type alias.)

scala> trait W extends V { override type T = Object }
                                         ^
       error: incompatible type in overriding
       type T = A (defined in trait V)
          (Equivalent type required when overriding a type alias.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants