@@ -30,6 +30,7 @@ import config.Feature
30
30
import collection .mutable
31
31
import config .Printers .{overload , typr , unapp }
32
32
import TypeApplications ._
33
+ import Annotations .Annotation
33
34
34
35
import Constants .{Constant , IntTag }
35
36
import Denotations .SingleDenotation
@@ -210,63 +211,81 @@ object Applications {
210
211
def wrapDefs (defs : mutable.ListBuffer [Tree ] | Null , tree : Tree )(using Context ): Tree =
211
212
if (defs != null && defs.nonEmpty) tpd.Block (defs.toList, tree) else tree
212
213
214
+ /** Optionally, if `sym` is a symbol created by `resolveMapped`, i.e. representing
215
+ * a mapped alternative, the original prefix of the alternative and the number of
216
+ * skipped term parameters.
217
+ */
218
+ private def mappedAltInfo (sym : Symbol )(using Context ): Option [(Type , Int )] =
219
+ for ann <- sym.getAnnotation(defn.MappedAlternativeAnnot ) yield
220
+ val AppliedType (_, pre :: ConstantType (c) :: Nil ) = ann.tree.tpe: @ unchecked
221
+ (pre, c.intValue)
222
+
213
223
/** Find reference to default parameter getter for parameter #n in current
214
- * parameter list, or NoType if none was found
215
- */
224
+ * parameter list, or EmptyTree if none was found.
225
+ * @param fn the tree referring to the function part of this call
226
+ * @param n the index of the parameter in the parameter list of the call
227
+ * @param testOnly true iff we just to find out whether a getter exists
228
+ */
216
229
def findDefaultGetter (fn : Tree , n : Int , testOnly : Boolean )(using Context ): Tree =
217
- if fn.symbol.isTerm then
230
+ def reifyPrefix (pre : Type ): Tree = pre match
231
+ case pre : SingletonType => singleton(pre, needLoad = ! testOnly)
232
+ case pre if testOnly =>
233
+ // In this case it is safe to skolemize now; we will produce a stable prefix for the actual call.
234
+ ref(pre.narrow)
235
+ case _ => EmptyTree
236
+
237
+ if fn.symbol.hasDefaultParams then
218
238
val meth = fn.symbol.asTerm
219
- val receiver : Tree = methPart(fn) match {
220
- case Select (receiver, _) => receiver
221
- case mr => mr.tpe.normalizedPrefix match {
222
- case mr : TermRef => ref(mr)
223
- case mr : ThisType => singleton(mr)
224
- case mr =>
225
- if testOnly then
226
- // In this case it is safe to skolemize now; we will produce a stable prefix for the actual call.
227
- ref(mr.narrow)
228
- else
229
- EmptyTree
230
- }
231
- }
232
- val getterPrefix =
233
- if (meth.is(Synthetic ) && meth.name == nme.apply) nme.CONSTRUCTOR else meth.name
234
- def getterName = DefaultGetterName (getterPrefix, n + numArgs(fn))
235
- if ! meth.hasDefaultParams then
236
- EmptyTree
237
- else if (receiver.isEmpty) {
238
- def findGetter (cx : Context ): Tree =
239
- if (cx eq NoContext ) EmptyTree
240
- else if (cx.scope != cx.outer.scope &&
241
- cx.denotNamed(meth.name).hasAltWith(_.symbol == meth)) {
242
- val denot = cx.denotNamed(getterName)
243
- if (denot.exists) ref(TermRef (cx.owner.thisType, getterName, denot))
244
- else findGetter(cx.outer)
245
- }
239
+ val idx = n + numArgs(fn)
240
+ methPart(fn) match
241
+ case Select (receiver, _) =>
242
+ findDefaultGetter(meth, receiver, idx)
243
+ case mr => mappedAltInfo(meth) match
244
+ case Some ((pre, skipped)) =>
245
+ findDefaultGetter(meth, reifyPrefix(pre), idx + skipped)
246
+ case None =>
247
+ findDefaultGetter(meth, reifyPrefix(mr.tpe.normalizedPrefix), idx)
248
+ else EmptyTree // structural applies don't have symbols or defaults
249
+ end findDefaultGetter
250
+
251
+ /** Find reference to default parameter getter for method `meth` numbered `idx`
252
+ * selected from given `receiver`, or EmptyTree if none was found.
253
+ * @param meth the called method (can be mapped by resolveMapped)
254
+ * @param receiver the receiver of the original method call, which determines
255
+ * where default getters are found
256
+ * @param idx the index of the searched for default getter, as encoded in its name
257
+ */
258
+ def findDefaultGetter (meth : TermSymbol , receiver : Tree , idx : Int )(using Context ): Tree =
259
+ val getterPrefix =
260
+ if (meth.is(Synthetic ) && meth.name == nme.apply) nme.CONSTRUCTOR else meth.name
261
+ val getterName = DefaultGetterName (getterPrefix, idx)
262
+
263
+ if receiver.isEmpty then
264
+ def findGetter (cx : Context ): Tree =
265
+ if cx eq NoContext then EmptyTree
266
+ else if cx.scope != cx.outer.scope
267
+ && cx.denotNamed(meth.name).hasAltWith(_.symbol == meth) then
268
+ val denot = cx.denotNamed(getterName)
269
+ if denot.exists then ref(TermRef (cx.owner.thisType, getterName, denot))
246
270
else findGetter(cx.outer)
247
- findGetter(ctx)
248
- }
249
- else {
250
- def selectGetter (qual : Tree ): Tree = {
251
- val getterDenot = qual.tpe.member(getterName)
252
- if (getterDenot.exists) qual.select(TermRef (qual.tpe, getterName, getterDenot))
253
- else EmptyTree
254
- }
255
- if (! meth.isClassConstructor)
256
- selectGetter(receiver)
257
- else {
258
- // default getters for class constructors are found in the companion object
259
- val cls = meth.owner
260
- val companion = cls.companionModule
261
- if (companion.isTerm) {
262
- val prefix = receiver.tpe.baseType(cls).normalizedPrefix
263
- if (prefix.exists) selectGetter(ref(TermRef (prefix, companion.asTerm)))
264
- else EmptyTree
265
- }
271
+ else findGetter(cx.outer)
272
+ findGetter(ctx)
273
+ else
274
+ def selectGetter (qual : Tree ): Tree =
275
+ val getterDenot = qual.tpe.member(getterName)
276
+ if (getterDenot.exists) qual.select(TermRef (qual.tpe, getterName, getterDenot))
277
+ else EmptyTree
278
+ if ! meth.isClassConstructor then
279
+ selectGetter(receiver)
280
+ else
281
+ // default getters for class constructors are found in the companion object
282
+ val cls = meth.owner
283
+ val companion = cls.companionModule
284
+ if companion.isTerm then
285
+ val prefix = receiver.tpe.baseType(cls).normalizedPrefix
286
+ if prefix.exists then selectGetter(ref(TermRef (prefix, companion.asTerm)))
266
287
else EmptyTree
267
- }
268
- }
269
- else EmptyTree // structural applies don't have symbols or defaults
288
+ else EmptyTree
270
289
end findDefaultGetter
271
290
272
291
/** Splice new method reference `meth` into existing application `app` */
@@ -570,6 +589,7 @@ trait Applications extends Compatibility {
570
589
571
590
def tryDefault (n : Int , args1 : List [Arg ]): Unit = {
572
591
val sym = methRef.symbol
592
+ val testOnly = this .isInstanceOf [TestApplication [? ]]
573
593
574
594
val defaultArg =
575
595
if (isJavaAnnotConstr(sym)) {
@@ -585,12 +605,14 @@ trait Applications extends Compatibility {
585
605
else
586
606
EmptyTree
587
607
}
588
- else defaultArgument(normalizedFun, n, this . isInstanceOf [ TestApplication [ ? ]] )
608
+ else defaultArgument(normalizedFun, n, testOnly )
589
609
590
610
def implicitArg = implicitArgTree(formal, appPos.span)
591
611
592
612
if ! defaultArg.isEmpty then
593
- matchArgs(args1, addTyped(treeToArg(defaultArg)), n + 1 )
613
+ defaultArg.tpe.widen match
614
+ case _ : MethodOrPoly if testOnly => matchArgs(args1, formals1, n + 1 )
615
+ case _ => matchArgs(args1, addTyped(treeToArg(defaultArg)), n + 1 )
594
616
else if methodType.isContextualMethod && ctx.mode.is(Mode .ImplicitsEnabled ) then
595
617
matchArgs(args1, addTyped(treeToArg(implicitArg)), n + 1 )
596
618
else
@@ -1947,9 +1969,8 @@ trait Applications extends Compatibility {
1947
1969
def isVarArgs = ptypes.nonEmpty && ptypes.last.isRepeatedParam
1948
1970
def numDefaultParams =
1949
1971
if alt.symbol.hasDefaultParams then
1950
- trimParamss(tp, alt.symbol.rawParamss) match
1951
- case params :: _ => params.count(_.is(HasDefault ))
1952
- case _ => 0
1972
+ val fn = ref(alt, needLoad = false )
1973
+ ptypes.indices.count(n => ! findDefaultGetter(fn, n, testOnly = true ).isEmpty)
1953
1974
else 0
1954
1975
if numParams < numArgs then isVarArgs
1955
1976
else if numParams == numArgs then true
@@ -2098,13 +2119,22 @@ trait Applications extends Compatibility {
2098
2119
}
2099
2120
end resolveOverloaded1
2100
2121
2101
- /** The largest suffix of `paramss` that has the same first parameter name as `t` */
2102
- def trimParamss (t : Type , paramss : List [List [Symbol ]])(using Context ): List [List [Symbol ]] = t match
2122
+ /** The largest suffix of `paramss` that has the same first parameter name as `t`,
2123
+ * plus the number of term parameters in `paramss` that come before that suffix.
2124
+ */
2125
+ def trimParamss (t : Type , paramss : List [List [Symbol ]])(using Context ): (List [List [Symbol ]], Int ) = t match
2103
2126
case MethodType (Nil ) => trimParamss(t.resultType, paramss)
2104
2127
case t : MethodOrPoly =>
2105
2128
val firstParamName = t.paramNames.head
2106
- paramss.dropWhile(_.head.name != firstParamName)
2107
- case _ => Nil
2129
+ def recur (pss : List [List [Symbol ]], skipped : Int ): (List [List [Symbol ]], Int ) =
2130
+ (pss : @ unchecked) match
2131
+ case (ps @ (p :: _)) :: pss1 =>
2132
+ if p.name == firstParamName then (pss, skipped)
2133
+ else recur(pss1, if p.name.isTermName then skipped + ps.length else skipped)
2134
+ case Nil =>
2135
+ (pss, skipped)
2136
+ recur(paramss, 0 )
2137
+ case _ => (Nil , 0 )
2108
2138
2109
2139
/** Resolve overloading by mapping to a different problem where each alternative's
2110
2140
* type is mapped with `f`, alternatives with non-existing types are dropped, and the
@@ -2114,8 +2144,19 @@ trait Applications extends Compatibility {
2114
2144
val reverseMapping = alts.flatMap { alt =>
2115
2145
val t = f(alt)
2116
2146
if t.exists then
2147
+ val (trimmed, skipped) = trimParamss(t, alt.symbol.rawParamss)
2117
2148
val mappedSym = alt.symbol.asTerm.copy(info = t)
2118
- mappedSym.rawParamss = trimParamss(t, alt.symbol.rawParamss)
2149
+ mappedSym.rawParamss = trimmed
2150
+ val (pre, totalSkipped) = mappedAltInfo(alt.symbol) match
2151
+ case Some ((pre, prevSkipped)) =>
2152
+ mappedSym.removeAnnotation(defn.MappedAlternativeAnnot )
2153
+ (pre, skipped + prevSkipped)
2154
+ case None =>
2155
+ (alt.prefix, skipped)
2156
+ mappedSym.addAnnotation(
2157
+ Annotation (TypeTree (
2158
+ defn.MappedAlternativeAnnot .typeRef.appliedTo(
2159
+ pre, ConstantType (Constant (totalSkipped))))))
2119
2160
Some ((TermRef (NoPrefix , mappedSym), alt))
2120
2161
else
2121
2162
None
0 commit comments