@@ -30,6 +30,7 @@ import config.Feature
3030import collection .mutable
3131import config .Printers .{overload , typr , unapp }
3232import TypeApplications ._
33+ import Annotations .Annotation
3334
3435import Constants .{Constant , IntTag }
3536import Denotations .SingleDenotation
@@ -210,63 +211,81 @@ object Applications {
210211 def wrapDefs (defs : mutable.ListBuffer [Tree ] | Null , tree : Tree )(using Context ): Tree =
211212 if (defs != null && defs.nonEmpty) tpd.Block (defs.toList, tree) else tree
212213
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+
213223 /** 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+ */
216229 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
218238 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))
246270 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)))
266287 else EmptyTree
267- }
268- }
269- else EmptyTree // structural applies don't have symbols or defaults
288+ else EmptyTree
270289 end findDefaultGetter
271290
272291 /** Splice new method reference `meth` into existing application `app` */
@@ -570,6 +589,7 @@ trait Applications extends Compatibility {
570589
571590 def tryDefault (n : Int , args1 : List [Arg ]): Unit = {
572591 val sym = methRef.symbol
592+ val testOnly = this .isInstanceOf [TestApplication [? ]]
573593
574594 val defaultArg =
575595 if (isJavaAnnotConstr(sym)) {
@@ -585,12 +605,14 @@ trait Applications extends Compatibility {
585605 else
586606 EmptyTree
587607 }
588- else defaultArgument(normalizedFun, n, this . isInstanceOf [ TestApplication [ ? ]] )
608+ else defaultArgument(normalizedFun, n, testOnly )
589609
590610 def implicitArg = implicitArgTree(formal, appPos.span)
591611
592612 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 )
594616 else if methodType.isContextualMethod && ctx.mode.is(Mode .ImplicitsEnabled ) then
595617 matchArgs(args1, addTyped(treeToArg(implicitArg)), n + 1 )
596618 else
@@ -1947,9 +1969,8 @@ trait Applications extends Compatibility {
19471969 def isVarArgs = ptypes.nonEmpty && ptypes.last.isRepeatedParam
19481970 def numDefaultParams =
19491971 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)
19531974 else 0
19541975 if numParams < numArgs then isVarArgs
19551976 else if numParams == numArgs then true
@@ -2098,13 +2119,22 @@ trait Applications extends Compatibility {
20982119 }
20992120 end resolveOverloaded1
21002121
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
21032126 case MethodType (Nil ) => trimParamss(t.resultType, paramss)
21042127 case t : MethodOrPoly =>
21052128 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 )
21082138
21092139 /** Resolve overloading by mapping to a different problem where each alternative's
21102140 * type is mapped with `f`, alternatives with non-existing types are dropped, and the
@@ -2114,8 +2144,19 @@ trait Applications extends Compatibility {
21142144 val reverseMapping = alts.flatMap { alt =>
21152145 val t = f(alt)
21162146 if t.exists then
2147+ val (trimmed, skipped) = trimParamss(t, alt.symbol.rawParamss)
21172148 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))))))
21192160 Some ((TermRef (NoPrefix , mappedSym), alt))
21202161 else
21212162 None
0 commit comments