Skip to content

Commit

Permalink
Avoid using the current denotation in NamedType.disambiguate (#21414)
Browse files Browse the repository at this point in the history
While recalculating denotation in NamedType (in `NamedType.memberDenot`,
which itself can be called from `NamedType.computeDenot` or
`NamedType.recomputeDenot`), it might call `NamedType.disambiguate`
which uses a denotation to decide about the correct overloaded method.
Using current denotation here might cause stale symbol errors, so
instead we use the `lastKnownDenotation`, which should be enough for the
use case here, as `targetName` should not change between phases/runs.

Later in the denotation recalculation a similar thing happens with
`SourceLanguage.apply`, where we also now avoid using currentDenotation,
as whether the symbol comes from java or Scala 2 should also not change
between phases/runs.
  • Loading branch information
jchyb authored Oct 14, 2024
2 parents 5e7ab15 + 6e58d25 commit fd0548e
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 4 deletions.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,7 @@ object Denotations {
}

def staleSymbolError(using Context): Nothing =
if symbol.isPackageObject && ctx.run != null && ctx.run.nn.isCompilingSuspended
if symbol.lastKnownDenotation.isPackageObject && ctx.run != null && ctx.run.nn.isCompilingSuspended
then throw StaleSymbolTypeError(symbol)
else throw StaleSymbolException(staleSymbolMsg)

Expand Down
9 changes: 7 additions & 2 deletions compiler/src/dotty/tools/dotc/core/TypeErasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ enum SourceLanguage:
object SourceLanguage:
/** The language in which `sym` was defined. */
def apply(sym: Symbol)(using Context): SourceLanguage =
if sym.is(JavaDefined) then
// We might be using this method while recalculating the denotation,
// so let's use `lastKnownDenotation`.
// This is ok as the source of the symbol and whether it is inline should
// not change between runs/phases.
val denot = sym.lastKnownDenotation
if denot.is(JavaDefined) then
SourceLanguage.Java
// Scala 2 methods don't have Inline set, except for the ones injected with `patchStdlibClass`
// which are really Scala 3 methods.
else if sym.isClass && sym.is(Scala2x) || (sym.maybeOwner.is(Scala2x) && !sym.is(Inline)) then
else if denot.isClass && denot.is(Scala2x) || (denot.maybeOwner.lastKnownDenotation.is(Scala2x) && !denot.is(Inline)) then
SourceLanguage.Scala2
else
SourceLanguage.Scala3
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2494,7 +2494,10 @@ object Types extends TypeUtils {
}

private def disambiguate(d: Denotation)(using Context): Denotation =
disambiguate(d, currentSignature, currentSymbol.targetName)
// this method might be triggered while the denotation is already being recomputed
// in NamedType, so it's better to use lastKnownDenotation instead, as targetName
// should not change between phases/runs
disambiguate(d, currentSignature, currentSymbol.lastKnownDenotation.targetName)

private def disambiguate(d: Denotation, sig: Signature | Null, target: Name)(using Context): Denotation =
if (sig != null)
Expand Down
3 changes: 3 additions & 0 deletions tests/pos-macros/i20574/Exports.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object Exports{
export OverloadedInline.*
}
20 changes: 20 additions & 0 deletions tests/pos-macros/i20574/Macros.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import scala.quoted.*

object Macros{

inline def A() : String = {
${ A_impl }
}

def A_impl(using Quotes): Expr[String] = {
Expr("Whatever")
}

inline def B[T]: Int = {
${ B_Impl[T] }
}

def B_Impl[T](using Quotes): Expr[Int] = {
Expr(0)
}
}
13 changes: 13 additions & 0 deletions tests/pos-macros/i20574/OverloadedInline.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Macros.*

object OverloadedInline{

A()
inline def overloaded_inline[T]: Unit = {
overloaded_inline[T](0)
}

inline def overloaded_inline[T](dummy: Int): Unit = {
val crash = B[T]
}
}
5 changes: 5 additions & 0 deletions tests/pos-macros/i20574/Test.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Exports.*

object Test {
overloaded_inline[Unit]
}

0 comments on commit fd0548e

Please sign in to comment.