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

Fix module symbol recovery from NoClassDefFoundError #19645

Merged
merged 1 commit into from
Feb 8, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions compiler/src/dotty/tools/dotc/quoted/Interpreter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -353,11 +353,16 @@ object Interpreter:
if !ctx.compilationUnit.isSuspendable then None
else targetException match
case _: NoClassDefFoundError | _: ClassNotFoundException =>
val className = targetException.getMessage
if className eq null then None
val message = targetException.getMessage
if message eq null then None
else
val sym = staticRef(className.toTypeName).symbol
if (sym.isDefinedInCurrentRun) Some(sym) else None
val className = message.replace('/', '.')
val sym =
if className.endsWith(str.MODULE_SUFFIX) then staticRef(className.toTermName).symbol.moduleClass
else staticRef(className.toTypeName).symbol
// If the symbol does not a a position we assume that it came from the current run and it has an error
if sym.isDefinedInCurrentRun || (sym.exists && !sym.srcPos.span.exists) then Some(sym)
else None
case _ => None
}
}
Expand Down
42 changes: 42 additions & 0 deletions tests/neg-macros/i19601/Macro.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package prelude
import scala.quoted.*

object Macros {
def validateInlineImpl[A: Type](assertionExpr: Expr[Assertion[A]], a: Expr[A])(using
Quotes
): Expr[Unit] = {
import quotes.reflect.*
val crashRoot = assertionExpr.value
'{ () }

}
given [A](using Type[A]): FromExpr[Assertion[A]] with {
def unapply(assertion: Expr[Assertion[A]])(using Quotes): Option[Assertion[A]] = {
import quotes.reflect.*

assertion match {
case '{ Assertion.greaterThanOrEqualTo[A](${ LiteralUnlift(value) })($_) } =>
Some(Assertion.greaterThanOrEqualTo(value)(orderingForValue(value)))
case _ => None
}
}
}

object LiteralUnlift {
def unapply[A: Type](expr: Expr[A])(using Quotes): Option[A] = expr match {
case '{ ${ Expr(int) }: Int } => Some(int)
case '{ Int.MaxValue } => Some(Int.MaxValue.asInstanceOf[A])
case '{ Int.MinValue } => Some(Int.MinValue.asInstanceOf[A])
case '{ ${ Expr(string) }: String } => Some(string)
case '{ ${ Expr(double) }: Double } => Some(double)
case '{ ${ Expr(float) }: Float } => Some(float)
case '{ ${ Expr(long) }: Long } => Some(long)
case '{ ${ Expr(short) }: Short } => Some(short)
case '{ ${ Expr(byte) }: Byte } => Some(byte)
case '{ ${ Expr(char) }: Char } => Some(char)
case _ => None
}
}

private def orderingForValue(any: Any)(using Quotes): Ordering[Any] = null.asInstanceOf[Ordering[Any]]
}
44 changes: 44 additions & 0 deletions tests/neg-macros/i19601/Test.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package prelude

sealed trait Assertion[-A]:
def unary_! : Assertion[A] = ???
def apply(a: A): Either[AssertionError, Unit] = ???
object Assertion:
val anything: Assertion[Any] = ???
def greaterThanOrEqualTo[A](value: A)(implicit ordering: Ordering[A]): Assertion[A] = ???

sealed trait AssertionError

abstract class NewtypeCustom[A] {
type Type
protected inline def validateInline(inline value: A): Unit

inline def apply(inline a1: A): Type = {
validateInline(a1)
a1.asInstanceOf[Type]
}
}
abstract class Newtype[A] extends NewtypeCustom[A] {
def assertion: Assertion[A] = Assertion.anything
protected inline def validateInline(inline value: A): Unit = ${
Macros.validateInlineImpl[A]('assertion, 'value)
}
}


abstract class Subtype[A] extends Newtype[A] {
type Type <: A
}


package object newtypes {
type Natural = Natural.Type
object Natural extends Subtype[Int] {

override inline def assertion = Assertion.greaterThanOrEqualTo(0)

val one: Natural = Natural(1) // triggers macro
}
}

// nopos-error: Cyclic macro dependencies in tests/pos-macros/i19601/Test.scala. Compilation stopped since no further progress can be made.
Loading