@@ -115,30 +115,34 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
115115 * Also transform trees inside method annotation.
116116 */
117117 override def transformDefDef (tree : DefDef )(using Context ): Tree =
118- atPhase(thisPhase) {
119- val sym = tree.symbol
120- val hasAnnotation = hasVarargsAnnotation(sym)
121- if hasRepeatedParams(sym) then
122- val isOverride = overridesJava(sym)
123- if isOverride || hasAnnotation || parentHasAnnotation( sym) then
124- // java varargs are more restrictive than scala's
125- // see https://github.com/scala/bug/issues/11714
126- if ! isValidJavaVarArgs (sym.info ) then
127- ctx.error( """ To generate java-compatible varargs:
128- | - there must be a single repeated parameter
129- | - it must be the last argument in the last parameter list
130- | """ .stripMargin,
131- sym.sourcePos)
132- tree
133- else
134- addVarArgsForwarder(tree, isOverride)
135- else
118+ val sym = tree.symbol
119+ val hasAnnotation = hasVarargsAnnotation(sym)
120+
121+ // atPhase(thisPhase) is used where necessary to see the repeated
122+ // parameters before their elimination
123+ val hasRepeatedParam = atPhase(thisPhase)(hasRepeatedParams( sym))
124+ if hasRepeatedParam then
125+ val isOverride = atPhase(thisPhase)(overridesJava(sym))
126+ if isOverride || hasAnnotation || parentHasAnnotation (sym) then
127+ // java varargs are more restrictive than scala's
128+ // see https://github.com/scala/bug/issues/11714
129+ val validJava = atPhase(thisPhase)(isValidJavaVarArgs(sym.info))
130+ if ! validJava then
131+ ctx.error( """ To generate java-compatible varargs:
132+ | - there must be a single repeated parameter
133+ | - it must be the last argument in the last parameter list
134+ | """ .stripMargin,
135+ sym.sourcePos)
136136 tree
137+ else
138+ // non-overrides cannot be synthetic otherwise javac refuses to call them
139+ addVarArgsForwarder(tree, isBridge = isOverride)
137140 else
138- if hasAnnotation then
139- ctx.error(" A method without repeated parameters cannot be annotated with @varargs" , sym.sourcePos)
140141 tree
141- }
142+ else
143+ if hasAnnotation then
144+ ctx.error(" A method without repeated parameters cannot be annotated with @varargs" , sym.sourcePos)
145+ tree
142146
143147 /** Is there a repeated parameter in some parameter list? */
144148 private def hasRepeatedParams (sym : Symbol )(using Context ): Boolean =
@@ -175,23 +179,30 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
175179 * forwards it to `ddef`.
176180 */
177181 private def addVarArgsForwarder (ddef : DefDef , isBridge : Boolean )(using ctx : Context ): Tree =
178- val original = ddef.symbol.asTerm
179- // For simplicity we always set the varargs flag
180- // although it's not strictly necessary for overrides
181- // (but it is for non-overrides)
182- val flags = ddef.symbol.flags | JavaVarargs
182+ val original = ddef.symbol
183183
184184 // The java-compatible forwarder symbol
185- val sym = original.copy(
186- // non-overrides cannot be synthetic otherwise javac refuses to call them
185+ val sym = atPhase(thisPhase) {
186+ // Capture the flags before they get modified by #transform.
187+ // For simplicity we always set the varargs flag,
188+ // although it's not strictly necessary for overrides.
189+ val flags = original.flags | JavaVarargs
190+ original.copy(
187191 flags = if isBridge then flags | Artifact else flags,
188192 info = toJavaVarArgs(ddef.symbol.info)
189193 ).asTerm
194+ }
190195
191- currentClass.info.member(sym.name).alternatives.find { s =>
192- s.matches(sym) &&
193- ! (isBridge && s.asSymDenotation.is(JavaDefined ))
194- } match
196+ // Find a method that would conflict with the forwarder if the latter existed.
197+ // This needs to be done at thisPhase so that parent @varargs don't conflict.
198+ val conflict = atPhase(thisPhase) {
199+ currentClass.info.member(sym.name).alternatives.find { s =>
200+ s.matches(sym) &&
201+ ! (isBridge && s.asSymDenotation.is(JavaDefined ))
202+ }
203+ }
204+
205+ conflict match
195206 case Some (conflict) =>
196207 ctx.error(s " @varargs produces a forwarder method that conflicts with ${conflict.showDcl}" , original.sourcePos)
197208 ddef
@@ -201,15 +212,10 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
201212 // Can't call `.argTypes` here because the underlying array type is of the
202213 // form `Array[? <: SomeType]`, so we need `.argInfos` to get the `TypeBounds`.
203214 val elemtp = vararg.tpe.widen.argInfos.head
204-
205- // The generation of the forwarding call needs to be deferred, otherwise
206- // generic and curried methods won't pass the tree checker.
207- atNextPhase {
208- ref(original.termRef)
209- .appliedToTypes(trefs)
210- .appliedToArgss(init)
211- .appliedToArgs(last :+ tpd.wrapArray(vararg, elemtp))
212- }
215+ ref(original.termRef)
216+ .appliedToTypes(trefs)
217+ .appliedToArgss(init)
218+ .appliedToArgs(last :+ tpd.wrapArray(vararg, elemtp))
213219 })
214220 Thicket (ddef, bridgeDef)
215221
0 commit comments