@@ -36,6 +36,7 @@ import SymUtils._
36
36
class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with FullParameterization { thisTransformer =>
37
37
38
38
import tpd ._
39
+ import ExtensionMethods ._
39
40
40
41
/** the following two members override abstract members in Transform */
41
42
override def phaseName : String = " extmethods"
@@ -89,65 +90,6 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
89
90
target.owner.linkedClass == derived.owner) extensionMethod(target)
90
91
else NoSymbol
91
92
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
-
151
93
private def createExtensionMethod (imeth : Symbol , staticClass : Symbol )(implicit ctx : Context ): TermSymbol = {
152
94
assert(ctx.phase == thisTransformer.next)
153
95
val extensionName = extensionNames(imeth).head.toTermName
@@ -209,3 +151,64 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
209
151
} else tree
210
152
}
211
153
}
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
+ }
0 commit comments