Skip to content

Commit 6e58d25

Browse files
committed
Avoid using the current denotation in NamedType.disambiguate
While recalculating denotation in NamedType we 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.
1 parent ac28899 commit 6e58d25

File tree

7 files changed

+53
-4
lines changed

7 files changed

+53
-4
lines changed

Diff for: compiler/src/dotty/tools/dotc/core/Denotations.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,7 @@ object Denotations {
961961
}
962962

963963
def staleSymbolError(using Context): Nothing =
964-
if symbol.isPackageObject && ctx.run != null && ctx.run.nn.isCompilingSuspended
964+
if symbol.lastKnownDenotation.isPackageObject && ctx.run != null && ctx.run.nn.isCompilingSuspended
965965
then throw StaleSymbolTypeError(symbol)
966966
else throw StaleSymbolException(staleSymbolMsg)
967967

Diff for: compiler/src/dotty/tools/dotc/core/TypeErasure.scala

+7-2
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,16 @@ enum SourceLanguage:
2424
object SourceLanguage:
2525
/** The language in which `sym` was defined. */
2626
def apply(sym: Symbol)(using Context): SourceLanguage =
27-
if sym.is(JavaDefined) then
27+
// We might be using this method while recalculating the denotation,
28+
// so let's use `lastKnownDenotation`.
29+
// This is ok as the source of the symbol and whether it is inline should
30+
// not change between runs/phases.
31+
val denot = sym.lastKnownDenotation
32+
if denot.is(JavaDefined) then
2833
SourceLanguage.Java
2934
// Scala 2 methods don't have Inline set, except for the ones injected with `patchStdlibClass`
3035
// which are really Scala 3 methods.
31-
else if sym.isClass && sym.is(Scala2x) || (sym.maybeOwner.is(Scala2x) && !sym.is(Inline)) then
36+
else if denot.isClass && denot.is(Scala2x) || (denot.maybeOwner.lastKnownDenotation.is(Scala2x) && !denot.is(Inline)) then
3237
SourceLanguage.Scala2
3338
else
3439
SourceLanguage.Scala3

Diff for: compiler/src/dotty/tools/dotc/core/Types.scala

+4-1
Original file line numberDiff line numberDiff line change
@@ -2491,7 +2491,10 @@ object Types extends TypeUtils {
24912491
}
24922492

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

24962499
private def disambiguate(d: Denotation, sig: Signature | Null, target: Name)(using Context): Denotation =
24972500
if (sig != null)

Diff for: tests/pos-macros/i20574/Exports.scala

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object Exports{
2+
export OverloadedInline.*
3+
}

Diff for: tests/pos-macros/i20574/Macros.scala

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import scala.quoted.*
2+
3+
object Macros{
4+
5+
inline def A() : String = {
6+
${ A_impl }
7+
}
8+
9+
def A_impl(using Quotes): Expr[String] = {
10+
Expr("Whatever")
11+
}
12+
13+
inline def B[T]: Int = {
14+
${ B_Impl[T] }
15+
}
16+
17+
def B_Impl[T](using Quotes): Expr[Int] = {
18+
Expr(0)
19+
}
20+
}

Diff for: tests/pos-macros/i20574/OverloadedInline.scala

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import Macros.*
2+
3+
object OverloadedInline{
4+
5+
A()
6+
inline def overloaded_inline[T]: Unit = {
7+
overloaded_inline[T](0)
8+
}
9+
10+
inline def overloaded_inline[T](dummy: Int): Unit = {
11+
val crash = B[T]
12+
}
13+
}

Diff for: tests/pos-macros/i20574/Test.scala

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import Exports.*
2+
3+
object Test {
4+
overloaded_inline[Unit]
5+
}

0 commit comments

Comments
 (0)