Java类调用Scala 3宏得到“bad class file”,“undeclared type variable:B”

kx7yvsdv  于 6个月前  发布在  Scala
关注(0)|答案(1)|浏览(65)

我遇到了一个Java-17函数调用Scala 3.3.0内联/宏代码的问题,并得到了这个错误:

[error] /testDir/scala3-test/src/main/scala/csw/params/Test.java:7:1: cannot access io.bullet.borer.Encoder
[error]   bad class file: /home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/io/bullet/borer-core_3/1.11.0/borer-core_3-1.11.0.jar(/io/bullet/borer/Encoder.class)
[error]     undeclared type variable: B
[error]     Please remove or make sure it appears in the correct subdirectory of the classpath.

字符串
我创建了一个简单的测试代码库来演示这个问题:https://github.com/abrighton/scala3-test
Scala类:

import java.nio.charset.StandardCharsets
import io.bullet.borer.*
import io.bullet.borer.derivation.CompactMapBasedCodecs.deriveCodec
import play.api.libs.json.{Json => PJson, _}

object JsonSupport extends JsonSupport

trait JsonSupport {
  def writes[T: Encoder](x: T): JsValue = PJson.parse(Json.encode(x).toUtf8String)
  def reads[T: Decoder](x: JsValue): T  = Json.decode(x.toString().getBytes(StandardCharsets.UTF_8)).to[T].value
}

case class ProperMotion(pmx: Double, pmy: Double)

object ProperMotion {
  implicit val properMotionCodec: Codec[ProperMotion] = deriveCodec
}


Java类:

public class Test {

    public void shouldConvertPmToFromJSON() {
        var pm = new ProperMotion(0.5, 2.33);
        var pmjs = JsonSupport.writes(pm, ProperMotion.properMotionCodec().encoder());
    }
}


deriveCodec(来自borer)看起来像这样:

inline def deriveCodec[T]: Codec[T] = Codec(deriveEncoder[T], deriveDecoder[T])


类文件没有损坏(我已经测试了多个版本)。这似乎是Java调用内联Scala函数的问题。
Scala版本编译:

class TestX {

  def shouldConvertPmToFromJSON(): Unit = {
    val pm = ProperMotion(0.5, 2.33)
    val pmjs = JsonSupport.writes(pm)
  }
}


这类代码以前在Scala-2.13下编译过。

iyfjxgzm

iyfjxgzm1#

Scala宏不能从Java调用。
当你有:

// Scala 2
def method: Foo = macro Macros.methodImpl

字符串

// Scala 3
inline def method = ${ Macros.metodImpl }


基本上,编译器会在字节码中创建一个不能被调用的空体method。但是该方法会有一些额外的字节码属性,这些属性会告诉Scala编译器哪个方法可以将其参数转换为Expr类型,其类型参数为Type/WeakTypeTag,并返回带有体AST的Expr。
对于javac来说,它是一个格式错误的方法(或者是实现throw new NotYetImplemented的方法),带有未知的属性。
我不知道它在Scala 2.13中应该如何工作。上次我检查宏方法时,宏方法有一些宏属性,并被实现为throw new NotYetImplemented,可以调用(从Java或通过运行时反射),但不会返回任何有意义的东西。

相关问题