scala / bug

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

cannot eval value classes #8390

Closed scabug closed 6 years ago

scabug commented 10 years ago
import scala.reflect.runtime.{currentMirror => cm}
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox
val tb = cm.mkToolBox()
tb.eval(tb.parse("class Meter(val value: Double) extends AnyVal"))

scala.tools.reflect.ToolBoxError: reflective compilation has failed:

value class may not be a local class

look like the class is wrapped in a block or something

scabug commented 10 years ago

Imported From: https://issues.scala-lang.org/browse/SI-8390?orig=1 Reporter: Guillaume Massé (masgui) Affected Versions: 2.11.0-RC1 Attachments:

scabug commented 10 years ago

@xeno-by said: Try tb.compile

scabug commented 10 years ago

Guillaume Massé (masgui) said:

scala> val tree = tb.parse("class Meter(val value: Double) extends AnyVal")
tree: tb.u.Tree =
class Meter extends AnyVal {
  <paramaccessor> val value: Double = _;
  def <init>(value: Double) = {
    super.<init>();
    ()
  }
}

scala> val program =  tb.compile(tree)
scala.tools.reflect.ToolBoxError: reflective compilation has failed:

value class may not be a local class
scabug commented 10 years ago

@xeno-by said: Omg sorry, I meant tb.define.

scabug commented 10 years ago

Guillaume Massé (masgui) said: hum, but I instrument a tree, I dont have a quasiquote. (It's for codebrew.io)

scabug commented 10 years ago

@xeno-by said: What do you mean? Is your tree incompatible with define?

scabug commented 10 years ago

Guillaume Massé (masgui) said:

scala>  val tree = tb.parse("class Meter(val value: Double) extends AnyVal")
tree: tb.u.Tree =
class Meter extends AnyVal {
  <paramaccessor> val value: Double = _;
  def <init>(value: Double) = {
    super.<init>();
    ()
  }
}

scala> tb.define(tree)
<console>:15: error: type mismatch;
 found   : tb.u.Tree
 required: tb.u.ImplDef
              tb.define(tree)
                        ^
scabug commented 10 years ago

@xeno-by said: Well, you'll have to cast here to either ClassDef or ModuleDef.

scabug commented 10 years ago

Guillaume Massé (masgui) said: Ok Thanks :-)

Once I collected class values and defined them I got a List[tb.u.Symbol]

Do i need to remove the class values from the parsed tree and add the Symbols ?

scabug commented 10 years ago

@xeno-by said: What do you want to do next after defining those classes?

scabug commented 10 years ago

Guillaume Massé (masgui) said (edited on Mar 10, 2014 11:23:03 PM UTC): I want to allow user writing value classes so they can use it in their code.

class Meter(val value: Double) extends AnyVal {
  def +(other: Meter) = new Meter(value + other.value)
}

val t = new Meter(1.0) + new Meter(2.0)

should instrument to {code}List((4, Meter(3)){code} where 4 is the line #

see attachement :P

scabug commented 10 years ago

@xeno-by said: Hmm, from what I can the class that's processed by define gets wrapped in a package with an autogenerated sort of unique name.

Therefore you'll need to replace all references to Meter with a symbol that you get as a result from tb.define. No idea how to do this in a robust manner to be honest. In order to resolve bindings robustly you need to typecheck, but in order to typecheck you need to have Meter's qualified with a correct package name :(

Theoretically, I could expose a package name in define, so that one could specify the exact package where Meter would go (could be an empty package if necessary). If people are fine with that, I could even submit a fix in 2.11.0-RC2. WDYT, Jason, Adriaan?

SethTisue commented 6 years ago

closing since this seems unlikely to progress, but comment and/or reopen if you disagree