Skip to content

Commit 463448f

Browse files
committed
Add MethodOrPoly#signature(isJava) overload
This makes it possible to compute the Java or Scala signature of a method, regardless of whether it was defined as a JavaMethod or not. Because there's nothing left that is shareable, this required removing SignatureCachingType and duplicating the signature caching logic between MethodOrPoly and NamedType. This commit itself does not change any semantics, but this new method will be useful for the next commit.
1 parent e79ca04 commit 463448f

File tree

2 files changed

+89
-66
lines changed

2 files changed

+89
-66
lines changed

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 84 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,7 +1999,7 @@ object Types {
19991999

20002000
// --- NamedTypes ------------------------------------------------------------------
20012001

2002-
abstract class NamedType extends CachedProxyType with ValueType with SignatureCachingType { self =>
2002+
abstract class NamedType extends CachedProxyType with ValueType { self =>
20032003

20042004
type ThisType >: this.type <: NamedType
20052005
type ThisName <: Name
@@ -2015,11 +2015,13 @@ object Types {
20152015
private var lastSymbol: Symbol = null
20162016
private var checkedPeriod: Period = Nowhere
20172017
private var myStableHash: Byte = 0
2018+
private var mySignature: Signature = _
2019+
private var mySignatureRunId: Int = NoRunId
20182020

20192021
// Invariants:
2020-
// (1) checkedPeriod != Nowhere => lastDenotation != null
2021-
// (2) lastDenotation != null => lastSymbol != null
2022-
// (3) mySigRunId != NoRunId => mySig != null
2022+
// (1) checkedPeriod != Nowhere => lastDenotation != null
2023+
// (2) lastDenotation != null => lastSymbol != null
2024+
// (3) mySignatureRunId != NoRunId => mySignature != null
20232025

20242026
def isType: Boolean = isInstanceOf[TypeRef]
20252027
def isTerm: Boolean = isInstanceOf[TermRef]
@@ -2037,15 +2039,22 @@ object Types {
20372039
case sym: Symbol => sym.originDenotation.name
20382040
}
20392041

2040-
/** The signature computed from the last known denotation with `sigFromDenot`,
2041-
* or if there is none, the signature of the symbol. Signatures are always
2042-
* computed before erasure, since some symbols change their signature at erasure.
2043-
*/
2044-
protected[dotc] def computeSignature(using Context): Signature =
2045-
val lastd = lastDenotation
2046-
if lastd != null then sigFromDenot(lastd)
2047-
else if ctx.erasedTypes then atPhase(erasurePhase)(computeSignature)
2048-
else symbol.asSeenFrom(prefix).signature
2042+
final override def signature(using Context): Signature =
2043+
/** The signature computed from the last known denotation with `sigFromDenot`,
2044+
* or if there is none, the signature of the symbol. Signatures are always
2045+
* computed before erasure, since some symbols change their signature at erasure.
2046+
*/
2047+
def computeSignature(using Context): Signature =
2048+
val lastd = lastDenotation
2049+
if lastd != null then sigFromDenot(lastd)
2050+
else if ctx.erasedTypes then atPhase(erasurePhase)(computeSignature)
2051+
else symbol.asSeenFrom(prefix).signature
2052+
2053+
if ctx.runId != mySignatureRunId then
2054+
mySignature = computeSignature
2055+
if !mySignature.isUnderDefined then mySignatureRunId = ctx.runId
2056+
mySignature
2057+
end signature
20492058

20502059
/** The signature computed from the current denotation with `sigFromDenot` if it is
20512060
* known without forcing.
@@ -3219,39 +3228,11 @@ object Types {
32193228
// is that most poly types are cyclic via poly params,
32203229
// and therefore two different poly types would never be equal.
32213230

3222-
/** A trait that mixes in functionality for signature caching */
3223-
trait SignatureCachingType extends TermType {
3224-
protected var mySignature: Signature = _
3225-
protected var mySignatureRunId: Int = NoRunId
3226-
3227-
protected[dotc] def computeSignature(using Context): Signature
3228-
3229-
final override def signature(using Context): Signature = {
3230-
if (ctx.runId != mySignatureRunId) {
3231-
mySignature = computeSignature
3232-
if (!mySignature.isUnderDefined) mySignatureRunId = ctx.runId
3233-
}
3234-
mySignature
3235-
}
3236-
}
3237-
3238-
trait MethodicType extends TermType {
3239-
protected def resultSignature(using Context): Signature = try resultType match {
3240-
case rtp: MethodicType => rtp.signature
3241-
case tp =>
3242-
if (tp.isRef(defn.UnitClass)) Signature(Nil, defn.UnitClass.fullName.asTypeName)
3243-
else Signature(tp, isJava = false)
3244-
}
3245-
catch {
3246-
case ex: AssertionError =>
3247-
println(i"failure while taking result signature of $this: $resultType")
3248-
throw ex
3249-
}
3250-
}
3231+
trait MethodicType extends TermType
32513232

32523233
/** A by-name parameter type of the form `=> T`, or the type of a method with no parameter list. */
32533234
abstract case class ExprType(resType: Type)
3254-
extends CachedProxyType with TermType with MethodicType {
3235+
extends CachedProxyType with MethodicType {
32553236
override def resultType(using Context): Type = resType
32563237
override def underlying(using Context): Type = resType
32573238

@@ -3371,7 +3352,66 @@ object Types {
33713352
final override def equals(that: Any): Boolean = equals(that, null)
33723353
}
33733354

3374-
abstract class MethodOrPoly extends UncachedGroundType with LambdaType with MethodicType with SignatureCachingType {
3355+
/** The superclass of MethodType and PolyType. */
3356+
sealed abstract class MethodOrPoly extends UncachedGroundType with LambdaType with MethodicType {
3357+
3358+
// Invariants:
3359+
// (1) mySignatureRunId != NoRunId => mySignature != null
3360+
// (2) myJavaSignatureRunId != NoRunId => myJavaSignature != null
3361+
3362+
private var mySignature: Signature = _
3363+
private var mySignatureRunId: Int = NoRunId
3364+
private var myJavaSignature: Signature = _
3365+
private var myJavaSignatureRunId: Int = NoRunId
3366+
3367+
/** If `isJava` is false, the Scala signature of this method. Otherwise, its Java signature.
3368+
*
3369+
* This distinction is needed because the same method type
3370+
* might be part of both a Java and Scala class and each language has
3371+
* different type erasure rules.
3372+
*
3373+
* Invariants:
3374+
* - Two distinct method overloads defined in the same _Scala_ class will
3375+
* have distinct _Scala_ signatures.
3376+
* - Two distinct methods overloads defined in the same _Java_ class will
3377+
* have distinct _Java_ signatures.
3378+
*
3379+
* @see SingleDenotation#signature
3380+
*/
3381+
def signature(isJava: Boolean)(using Context): Signature =
3382+
def computeSignature(isJava: Boolean)(using Context): Signature =
3383+
val resultSignature = resultType match
3384+
case tp: MethodOrPoly => tp.signature(isJava)
3385+
case tp: ExprType => tp.signature
3386+
case tp =>
3387+
if tp.isRef(defn.UnitClass) then Signature(Nil, defn.UnitClass.fullName.asTypeName)
3388+
else Signature(tp, isJava = false)
3389+
this match
3390+
case tp: MethodType =>
3391+
val params = if (isErasedMethod) Nil else tp.paramInfos
3392+
resultSignature.prependTermParams(params, isJava)
3393+
case tp: PolyType =>
3394+
resultSignature.prependTypeParams(tp.paramNames.length)
3395+
3396+
if isJava then
3397+
if ctx.runId != myJavaSignatureRunId then
3398+
myJavaSignature = computeSignature(isJava)
3399+
if !myJavaSignature.isUnderDefined then myJavaSignatureRunId = ctx.runId
3400+
myJavaSignature
3401+
else
3402+
if ctx.runId != mySignatureRunId then
3403+
mySignature = computeSignature(isJava)
3404+
if !mySignature.isUnderDefined then mySignatureRunId = ctx.runId
3405+
mySignature
3406+
end signature
3407+
3408+
final override def signature(using Context): Signature =
3409+
def isJava(tp: Type): Boolean = tp match
3410+
case tp: PolyType => isJava(tp.resultType)
3411+
case tp: MethodType => tp.isJavaMethod
3412+
case _ => false
3413+
signature(isJava = isJava(this))
3414+
33753415
final override def hashCode: Int = System.identityHashCode(this)
33763416

33773417
final override def equals(that: Any): Boolean = equals(that, null)
@@ -3531,11 +3571,6 @@ object Types {
35313571
companion.eq(ContextualMethodType) ||
35323572
companion.eq(ErasedContextualMethodType)
35333573

3534-
protected[dotc] def computeSignature(using Context): Signature = {
3535-
val params = if (isErasedMethod) Nil else paramInfos
3536-
resultSignature.prependTermParams(params, isJavaMethod)
3537-
}
3538-
35393574
protected def prefixString: String = companion.prefixString
35403575
}
35413576

@@ -3766,9 +3801,6 @@ object Types {
37663801
assert(resType.isInstanceOf[TermType], this)
37673802
assert(paramNames.nonEmpty)
37683803

3769-
protected[dotc] def computeSignature(using Context): Signature =
3770-
resultSignature.prependTypeParams(paramNames.length)
3771-
37723804
override def isContextualMethod = resType.isContextualMethod
37733805
override def isImplicitMethod = resType.isImplicitMethod
37743806

compiler/src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -90,22 +90,13 @@ class TreeChecker extends Phase with SymTransformer {
9090
// Signatures are used to disambiguate overloads and need to stay stable
9191
// until erasure, see the comment above `Compiler#phases`.
9292
if (ctx.phaseId <= erasurePhase.id) {
93-
val cur = symd.info
94-
val initial = symd.initial.info
95-
val curSig = cur match {
96-
case cur: SignatureCachingType =>
97-
// Bypass the signature cache, it might hide a signature change
98-
cur.computeSignature
99-
case _ =>
100-
cur.signature
101-
}
102-
assert(curSig == initial.signature,
93+
val initial = symd.initial
94+
assert(symd.signature == initial.signature,
10395
i"""Signature of ${sym.showLocated} changed at phase ${ctx.base.fusedContaining(ctx.phase.prev)}
104-
|Initial info: ${initial}
96+
|Initial info: ${initial.info}
10597
|Initial sig : ${initial.signature}
106-
|Current info: ${cur}
107-
|Current sig : ${curSig}
108-
|Current cached sig: ${cur.signature}""")
98+
|Current info: ${symd.info}
99+
|Current sig : ${symd.signature}""")
109100
}
110101

111102
symd

0 commit comments

Comments
 (0)