scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
232 stars 21 forks source link

AbstractMethodError when override using macro #8949

Open scabug opened 9 years ago

scabug commented 9 years ago
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_67).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :paste
// Entering paste mode (ctrl-D to finish)

import scala.language.experimental.macros
import scala.reflect.macros.Context

trait A{
  def x: Int = 1
}

object B {
  def impl(c: Context): c.Expr[Int] = {
    import c.universe._
    c.Expr[Int](Literal(Constant(2)))
  }
}

class B extends A {
  override def x: Int = macro B.impl
}

// Exiting paste mode, now interpreting.

import scala.language.experimental.macros
import scala.reflect.macros.Context
defined trait A
defined module B
defined class B

scala> val b = new B
b: B = B@47825164

scala> b.x
res0: Int = 2

scala> (b: A).x
java.lang.AbstractMethodError: B.x()I
        at .<init>(<console>:14)
        at .<clinit>(<console>)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at $print(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734)
        at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:983)
        at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:573)
        at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:604)
        at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:568)
        at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:760)
        at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:805)
        at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:717)
        at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:581)
        at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:588)
        at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:591)
        at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:882)
        at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:837)
        at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:837)
        at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135)
        at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:837)
        at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:83)
        at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96)
        at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:105)
        at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
Welcome to Scala version 2.11.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_67).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :paste
// Entering paste mode (ctrl-D to finish)

import scala.language.experimental.macros
import scala.reflect.macros.Context

trait A{
  def x: Int = 1
}

object B {
  def impl(c: Context): c.Expr[Int] = {
    import c.universe._
    c.Expr[Int](Literal(Constant(2)))
  }
}

class B extends A {
  override def x: Int = macro B.impl
}

// Exiting paste mode, now interpreting.

warning: there was one deprecation warning; re-run with -deprecation for details
import scala.language.experimental.macros
import scala.reflect.macros.Context
defined trait A
defined object B
defined class B

scala> val b = new B
b: B = B@a7d060f

scala> b.x
res0: Int = 2

scala> (b: A).x
java.lang.AbstractMethodError: B.x()I
  ... 33 elided
scabug commented 9 years ago

Imported From: https://issues.scala-lang.org/browse/SI-8949?orig=1 Reporter: kenji yoshida Affected Versions: 2.10.4, 2.11.4

scabug commented 9 years ago

@retronym said: As recently discussed https://groups.google.com/forum/#!msg/scala-user/lo_OXRluQEQ/PTY87UGwJKgJ we might consider restricting macro declarations so that they can't override an existing method. There are use cases for this, however, so we have to be careful.

scabug commented 9 years ago

kenji yoshida said: similar example


Welcome to Scala version 2.11.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_67).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :paste
// Entering paste mode (ctrl-D to finish)

import scala.language.experimental.macros
import scala.reflect.macros.Context

object A {
  def impl(c: Context): c.Expr[Int] = {
    import c.universe._
    c.Expr[Int](Literal(Constant(2)))
  }
}

class A {
  def x: Int = macro A.impl
}

// Exiting paste mode, now interpreting.

warning: there was one deprecation warning; re-run with -deprecation for details
import scala.language.experimental.macros
import scala.reflect.macros.Context
defined object A
defined class A

scala> val a0 = new A
a0: A = A@34aad3ab

scala> a0.x
res0: Int = 2

scala> val a1: {def x: Int} = a0
a1: AnyRef{def x: Int} = A@34aad3ab

scala> a1.x
warning: there was one feature warning; re-run with -feature for details
java.lang.NoSuchMethodException: A.x()
  at java.lang.Class.getMethod(Class.java:1665)
  at .reflMethod$Method1(<console>:16)
  ... 33 elided
scabug commented 7 years ago

kenji yoshida said: in Scala 2.12.0

Welcome to Scala 2.12.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_112).
Type in expressions for evaluation. Or try :help.

scala> :paste
// Entering paste mode (ctrl-D to finish)

import scala.language.experimental.macros
import scala.reflect.macros.Context

trait A{
  def x: Int = 1
}

object B {
  def impl(c: Context): c.Expr[Int] = {
    import c.universe._
    c.Expr[Int](Literal(Constant(2)))
  }
}

class B extends A {
  override def x: Int = macro B.impl
}

// Exiting paste mode, now interpreting.

<console>:20: warning: type Context in package macros is deprecated (since 2.11.0): use blackbox.Context or whitebox.Context instead
         def impl(c: Context): c.Expr[Int] = {
                     ^
import scala.language.experimental.macros
import scala.reflect.macros.Context
defined trait A
defined object B
defined class B

scala> val b = new B
b: B = B@552cede7

scala> b.x
res0: Int = 2

scala> (b: A).x
res1: Int = 1