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

Tasty Reader: test APPLYsigpoly, fail in forced annotations #10299

Merged
merged 1 commit into from Feb 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/compiler/scala/tools/nsc/tasty/TreeUnpickler.scala
Expand Up @@ -1148,6 +1148,9 @@ class TreeUnpickler[Tasty <: TastyUniverse](
tpd.Apply(fn, until(end)(readTerm()(argsCtx)))
}
case TYPEAPPLY => tpd.TypeApply(readTerm(), until(end)(readTpt()))
case APPLYsigpoly =>
// this is skipped if it appears in parents, so only affects forced annotation trees
signaturePolymorphicIsUnsupported
case TYPED => tpd.Typed(readTerm(), readTpt())
case IF =>
if (nextByte === INLINE) unsupportedTermTreeError("inline conditional expression")
Expand Down Expand Up @@ -1241,6 +1244,9 @@ class TreeUnpickler[Tasty <: TastyUniverse](
*/
private def abortMacroHole[T]: T = abortWith(msg = "Scala 3 macro hole in pickled TASTy")

private def signaturePolymorphicIsUnsupported[T](implicit ctx: Context): T =
unsupportedTermTreeError("signature polymorphic application")

private def metaprogrammingIsUnsupported[T](implicit ctx: Context): T =
unsupportedError("Scala 3 metaprogramming features")

Expand Down
2 changes: 2 additions & 0 deletions src/compiler/scala/tools/tasty/TastyFormat.scala
Expand Up @@ -325,6 +325,7 @@ object TastyFormat {
// final val ??? = 178
// final val ??? = 179
final val METHODtype = 180
final val APPLYsigpoly = 181

final val MATCHtype = 190
final val MATCHtpt = 191
Expand Down Expand Up @@ -491,6 +492,7 @@ object TastyFormat {
case BOUNDED => "BOUNDED"
case APPLY => "APPLY"
case TYPEAPPLY => "TYPEAPPLY"
case APPLYsigpoly => "APPLYsigpoly"
case NEW => "NEW"
case THROW => "THROW"
case TYPED => "TYPED"
Expand Down
4 changes: 4 additions & 0 deletions test/tasty/neg/src-2/TestApplySigPoly.check
@@ -0,0 +1,4 @@
TestApplySigPoly_fail.scala:6: error: Unsupported Scala 3 signature polymorphic application in an annotation of method annotatedMethod; note that complex trees are not yet supported for Annotations; found in method annotatedMethod in object tastytest.ApplySigPoly.
def test = TestApplySigPolyPre.forceAnnots[ApplySigPoly.type, ApplySigPoly.boxAnnot]
^
1 error
8 changes: 8 additions & 0 deletions test/tasty/neg/src-2/TestApplySigPoly_fail.scala
@@ -0,0 +1,8 @@
package tastytest

object TestApplySigPoly {

// force an annotation tree with an APPLYsigpoly node
def test = TestApplySigPolyPre.forceAnnots[ApplySigPoly.type, ApplySigPoly.boxAnnot]

}
25 changes: 25 additions & 0 deletions test/tasty/neg/src-2/TestApplySigPoly_pre.scala
@@ -0,0 +1,25 @@
package tastytest

import scala.language.experimental.macros

import scala.reflect.macros.blackbox.Context

object TestApplySigPolyPre {

/** forces annotations of type `A` on methods from class `T` */
def forceAnnots[T, A]: Unit = macro Macros.forceAnnotsImpl[T, A]

object Macros {
def forceAnnotsImpl[T, A](c: Context)(implicit T: c.WeakTypeTag[T], A: c.WeakTypeTag[A]): c.Expr[Unit] = {
import c.universe._
for {
method <- weakTypeOf[T].members.filter(_.isMethod)
annot <- method.annotations.find(_.tree.tpe =:= weakTypeOf[A])
} {
annot.tree
}
c.Expr[Unit](q"()")
}
}

}
20 changes: 20 additions & 0 deletions test/tasty/neg/src-3/ApplySigPoly.scala
@@ -0,0 +1,20 @@
package tastytest

object ApplySigPoly {

class Foo {
def foo(x: Int): Int = x
}

private val lookup = java.lang.invoke.MethodHandles.lookup()
private val mt = java.lang.invoke.MethodType.methodType(classOf[Int], classOf[Int]);

val mh = lookup.findVirtual(classOf[Foo], "foo", mt)

val self = new Foo()

class boxAnnot(val value: Int) extends scala.annotation.Annotation

@boxAnnot(mh.invokeExact(self, 23): Int)
def annotatedMethod: Int = 23
}
14 changes: 14 additions & 0 deletions test/tasty/run/src-2/tastytest/TestApplySigPoly.scala
@@ -0,0 +1,14 @@
package tastytest

object TestApplySigPoly extends Suite("TestApplySigPoly") {

test("construct class with APPLYsigpoly in parent") {
val subbox = new ApplySigPoly.SubBox()
assert(subbox.value == 23)
}

test("call method with APPLYsigpoly in annotation") {
assert(ApplySigPoly.annotatedMethod == 23)
}

}
25 changes: 25 additions & 0 deletions test/tasty/run/src-3/tastytest/ApplySigPoly.scala
@@ -0,0 +1,25 @@
package tastytest

object ApplySigPoly {

class Foo {
def foo(x: Int): Int = x
}

private val lookup = java.lang.invoke.MethodHandles.lookup()
private val mt = java.lang.invoke.MethodType.methodType(classOf[Int], classOf[Int]);

val mh = lookup.findVirtual(classOf[Foo], "foo", mt)

class IntBox(val value: Int)

val self = new Foo()

// There should appear a APPLYsigpoly node in the parent of SubBox
class SubBox extends IntBox(mh.invokeExact(self, 23): Int)

class boxAnnot(val value: Int) extends scala.annotation.Annotation

@boxAnnot(mh.invokeExact(self, 23): Int)
def annotatedMethod: Int = 23
}