Skip to content

Commit ac41e8a

Browse files
committed
Make ExtensionMethods#extensionMethods an object method
This method will be needed to implement VCInline.
1 parent 089fe04 commit ac41e8a

File tree

3 files changed

+76
-68
lines changed

3 files changed

+76
-68
lines changed

src/dotty/tools/dotc/core/Phases.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ object Phases {
232232

233233
private val typerCache = new PhaseCache(classOf[FrontEnd])
234234
private val refChecksCache = new PhaseCache(classOf[RefChecks])
235+
private val extensionMethodsCache = new PhaseCache(classOf[ExtensionMethods])
235236
private val erasureCache = new PhaseCache(classOf[Erasure])
236237
private val patmatCache = new PhaseCache(classOf[PatternMatcher])
237238
private val flattenCache = new PhaseCache(classOf[Flatten])
@@ -241,6 +242,7 @@ object Phases {
241242

242243
def typerPhase = typerCache.phase
243244
def refchecksPhase = refChecksCache.phase
245+
def extensionMethodsPhase = extensionMethodsCache.phase
244246
def erasurePhase = erasureCache.phase
245247
def patmatPhase = patmatCache.phase
246248
def flattenPhase = flattenCache.phase

src/dotty/tools/dotc/transform/ExtensionMethods.scala

Lines changed: 62 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import SymUtils._
3636
class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with FullParameterization { thisTransformer =>
3737

3838
import tpd._
39+
import ExtensionMethods._
3940

4041
/** the following two members override abstract members in Transform */
4142
override def phaseName: String = "extmethods"
@@ -89,65 +90,6 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
8990
target.owner.linkedClass == derived.owner) extensionMethod(target)
9091
else NoSymbol
9192

92-
/** Generate stream of possible names for the extension version of given instance method `imeth`.
93-
* If the method is not overloaded, this stream consists of just "imeth$extension".
94-
* If the method is overloaded, the stream has as first element "imeth$extenionX", where X is the
95-
* index of imeth in the sequence of overloaded alternatives with the same name. This choice will
96-
* always be picked as the name of the generated extension method.
97-
* After this first choice, all other possible indices in the range of 0 until the number
98-
* of overloaded alternatives are returned. The secondary choices are used to find a matching method
99-
* in `extensionMethod` if the first name has the wrong type. We thereby gain a level of insensitivity
100-
* of how overloaded types are ordered between phases and picklings.
101-
*/
102-
private def extensionNames(imeth: Symbol)(implicit ctx: Context): Stream[Name] = {
103-
val decl = imeth.owner.info.decl(imeth.name)
104-
105-
/** No longer needed for Dotty, as we are more disciplined with scopes now.
106-
// Bridge generation is done at phase `erasure`, but new scopes are only generated
107-
// for the phase after that. So bridges are visible in earlier phases.
108-
//
109-
// `info.member(imeth.name)` filters these out, but we need to use `decl`
110-
// to restrict ourselves to members defined in the current class, so we
111-
// must do the filtering here.
112-
val declTypeNoBridge = decl.filter(sym => !sym.isBridge).tpe
113-
*/
114-
decl match {
115-
case decl: MultiDenotation =>
116-
val alts = decl.alternatives
117-
val index = alts indexOf imeth.denot
118-
assert(index >= 0, alts + " does not contain " + imeth)
119-
def altName(index: Int) = (imeth.name + "$extension" + index).toTermName
120-
altName(index) #:: ((0 until alts.length).toStream filter (index != _) map altName)
121-
case decl =>
122-
assert(decl.exists, imeth.name + " not found in " + imeth.owner + "'s decls: " + imeth.owner.info.decls)
123-
Stream((imeth.name + "$extension").toTermName)
124-
}
125-
}
126-
127-
/** Return the extension method that corresponds to given instance method `meth`. */
128-
def extensionMethod(imeth: Symbol)(implicit ctx: Context): TermSymbol =
129-
ctx.atPhase(thisTransformer.next) { implicit ctx =>
130-
// FIXME use toStatic instead?
131-
val companionInfo = imeth.owner.companionModule.info
132-
val candidates = extensionNames(imeth) map (companionInfo.decl(_).symbol) filter (_.exists)
133-
val matching = candidates filter (c => memberSignature(c.info) == imeth.signature)
134-
assert(matching.nonEmpty,
135-
sm"""|no extension method found for:
136-
|
137-
| $imeth:${imeth.info.show} with signature ${imeth.signature}
138-
|
139-
| Candidates:
140-
|
141-
| ${candidates.map(c => c.name + ":" + c.info.show).mkString("\n")}
142-
|
143-
| Candidates (signatures normalized):
144-
|
145-
| ${candidates.map(c => c.name + ":" + c.info.signature + ":" + memberSignature(c.info)).mkString("\n")}
146-
|
147-
| Eligible Names: ${extensionNames(imeth).mkString(",")}""")
148-
matching.head.asTerm
149-
}
150-
15193
private def createExtensionMethod(imeth: Symbol, staticClass: Symbol)(implicit ctx: Context): TermSymbol = {
15294
assert(ctx.phase == thisTransformer.next)
15395
val extensionName = extensionNames(imeth).head.toTermName
@@ -209,3 +151,64 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
209151
} else tree
210152
}
211153
}
154+
155+
object ExtensionMethods {
156+
/** Generate stream of possible names for the extension version of given instance method `imeth`.
157+
* If the method is not overloaded, this stream consists of just "imeth$extension".
158+
* If the method is overloaded, the stream has as first element "imeth$extenionX", where X is the
159+
* index of imeth in the sequence of overloaded alternatives with the same name. This choice will
160+
* always be picked as the name of the generated extension method.
161+
* After this first choice, all other possible indices in the range of 0 until the number
162+
* of overloaded alternatives are returned. The secondary choices are used to find a matching method
163+
* in `extensionMethod` if the first name has the wrong type. We thereby gain a level of insensitivity
164+
* of how overloaded types are ordered between phases and picklings.
165+
*/
166+
private def extensionNames(imeth: Symbol)(implicit ctx: Context): Stream[Name] = {
167+
val decl = imeth.owner.info.decl(imeth.name)
168+
169+
/** No longer needed for Dotty, as we are more disciplined with scopes now.
170+
// Bridge generation is done at phase `erasure`, but new scopes are only generated
171+
// for the phase after that. So bridges are visible in earlier phases.
172+
//
173+
// `info.member(imeth.name)` filters these out, but we need to use `decl`
174+
// to restrict ourselves to members defined in the current class, so we
175+
// must do the filtering here.
176+
val declTypeNoBridge = decl.filter(sym => !sym.isBridge).tpe
177+
*/
178+
decl match {
179+
case decl: MultiDenotation =>
180+
val alts = decl.alternatives
181+
val index = alts indexOf imeth.denot
182+
assert(index >= 0, alts + " does not contain " + imeth)
183+
def altName(index: Int) = (imeth.name + "$extension" + index).toTermName
184+
altName(index) #:: ((0 until alts.length).toStream filter (index != _) map altName)
185+
case decl =>
186+
assert(decl.exists, imeth.name + " not found in " + imeth.owner + "'s decls: " + imeth.owner.info.decls)
187+
Stream((imeth.name + "$extension").toTermName)
188+
}
189+
}
190+
191+
/** Return the extension method that corresponds to given instance method `meth`. */
192+
def extensionMethod(imeth: Symbol)(implicit ctx: Context): TermSymbol =
193+
ctx.atPhase(ctx.extensionMethodsPhase.next) { implicit ctx =>
194+
// FIXME use toStatic instead?
195+
val companionInfo = imeth.owner.companionModule.info
196+
val candidates = extensionNames(imeth) map (companionInfo.decl(_).symbol) filter (_.exists)
197+
val matching = candidates filter (c => FullParameterization.memberSignature(c.info) == imeth.signature)
198+
assert(matching.nonEmpty,
199+
sm"""|no extension method found for:
200+
|
201+
| $imeth:${imeth.info.show} with signature ${imeth.signature}
202+
|
203+
| Candidates:
204+
|
205+
| ${candidates.map(c => c.name + ":" + c.info.show).mkString("\n")}
206+
|
207+
| Candidates (signatures normalized):
208+
|
209+
| ${candidates.map(c => c.name + ":" + c.info.signature + ":" + FullParameterization.memberSignature(c.info)).mkString("\n")}
210+
|
211+
| Eligible Names: ${extensionNames(imeth).mkString(",")}""")
212+
matching.head.asTerm
213+
}
214+
}

src/dotty/tools/dotc/transform/FullParameterization.scala

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import ast.Trees._
5252
trait FullParameterization {
5353

5454
import tpd._
55+
import FullParameterization._
5556

5657
/** If references to original symbol `referenced` from within fully parameterized method
5758
* `derived` should be rewired to some fully parameterized method, the rewiring target symbol,
@@ -124,15 +125,6 @@ trait FullParameterization {
124125
}
125126
}
126127

127-
/** Assuming `info` is a result of a `fullyParameterizedType` call, the signature of the
128-
* original method type `X` such that `info = fullyParameterizedType(X, ...)`.
129-
*/
130-
def memberSignature(info: Type)(implicit ctx: Context): Signature = info match {
131-
case info: PolyType => memberSignature(info.resultType)
132-
case info @ MethodType(nme.SELF :: Nil, _) => info.resultType.ensureMethodic.signature
133-
case _ => Signature.NotAMethod
134-
}
135-
136128
/** The type parameters (skolems) of the method definition `originalDef`,
137129
* followed by the class parameters of its enclosing class.
138130
*/
@@ -230,3 +222,14 @@ trait FullParameterization {
230222
.appliedToArgss(originalDef.vparamss.nestedMap(vparam => ref(vparam.symbol)))
231223
.withPos(originalDef.rhs.pos)
232224
}
225+
226+
object FullParameterization {
227+
/** Assuming `info` is a result of a `fullyParameterizedType` call, the signature of the
228+
* original method type `X` such that `info = fullyParameterizedType(X, ...)`.
229+
*/
230+
def memberSignature(info: Type)(implicit ctx: Context): Signature = info match {
231+
case info: PolyType => memberSignature(info.resultType)
232+
case info @ MethodType(nme.SELF :: Nil, _) => info.resultType.ensureMethodic.signature
233+
case _ => Signature.NotAMethod
234+
}
235+
}

0 commit comments

Comments
 (0)