Skip to content

Commit

Permalink
Backport "Refine handling of StaleSymbol type errors" to LTS (#20898)
Browse files Browse the repository at this point in the history
Backports #19605 to the LTS branch.

PR submitted by the release tooling.
  • Loading branch information
WojciechMazur authored Jul 1, 2024
2 parents 9cd3bf0 + cc0041b commit f2428bd
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 5 deletions.
20 changes: 15 additions & 5 deletions compiler/src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import config.Config
import config.Printers.overload
import util.common.*
import typer.ProtoTypes.NoViewsAllowed
import reporting.Message
import collection.mutable.ListBuffer

/** Denotations represent the meaning of symbols and named types.
Expand Down Expand Up @@ -945,10 +946,9 @@ object Denotations {
}

def staleSymbolError(using Context): Nothing =
if symbol.isPackageObject && ctx.run != null && ctx.run.nn.isCompilingSuspended then
throw TypeError(em"Cyclic macro dependency; macro refers to a toplevel symbol in ${symbol.source} from which the macro is called")
else
throw new StaleSymbol(staleSymbolMsg)
if symbol.isPackageObject && ctx.run != null && ctx.run.nn.isCompilingSuspended
then throw StaleSymbolTypeError(symbol)
else throw StaleSymbolException(staleSymbolMsg)

def staleSymbolMsg(using Context): String = {
def ownerMsg = this match {
Expand Down Expand Up @@ -1356,9 +1356,19 @@ object Denotations {
else
NoSymbol

trait StaleSymbol extends Exception

/** An exception for accessing symbols that are no longer valid in current run */
class StaleSymbol(msg: => String) extends Exception {
class StaleSymbolException(msg: => String) extends Exception, StaleSymbol {
util.Stats.record("stale symbol")
override def getMessage(): String = msg
}

/** An exception that is at the same type a StaleSymbol and a TypeError.
* Sine it is a TypeError it can be reported as a nroaml error instead of crashing
* the compiler.
*/
class StaleSymbolTypeError(symbol: Symbol)(using Context) extends TypeError, StaleSymbol:
def toMessage(using Context) =
em"Cyclic macro dependency; macro refers to a toplevel symbol in ${symbol.source} from which the macro is called"
}
11 changes: 11 additions & 0 deletions tests/pos/i19604/ZSet.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// ZSet.scala
// moving it to core.scala would lead to Recursion limit exceeded: find-member prelude.ZSetSyntax
package prelude

import prelude.newtypes._

class ZSet[+A, +B]
object ZSet
trait ZSetSyntax {
implicit final class ZSetMapOps[+A](self: Map[A, Natural])
}
37 changes: 37 additions & 0 deletions tests/pos/i19604/core.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// core.scala
package prelude

sealed trait Assertion[-A]
object Assertion:
def greaterThanOrEqualTo[A](value: 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] = ???
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
}
}
8 changes: 8 additions & 0 deletions tests/pos/i19604/macro.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// macro.scala
package prelude
import scala.quoted.*

object Macros {
def validateInlineImpl[A: Type](assertionExpr: Expr[Assertion[A]], a: Expr[A])(using Quotes): Expr[Unit] =
'{ () }
}
8 changes: 8 additions & 0 deletions tests/pos/i19604/prelude.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// prelude.scala

import prelude.newtypes.Natural

package object prelude extends ZSetSyntax {
type MultiSet[+A] = ZSet[A, Natural]
val MultiSet: ZSet.type = ZSet
}

0 comments on commit f2428bd

Please sign in to comment.