@@ -115,30 +115,34 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
115
115
* Also transform trees inside method annotation.
116
116
*/
117
117
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)
136
136
tree
137
+ else
138
+ // non-overrides cannot be synthetic otherwise javac refuses to call them
139
+ addVarArgsForwarder(tree, isBridge = isOverride)
137
140
else
138
- if hasAnnotation then
139
- ctx.error(" A method without repeated parameters cannot be annotated with @varargs" , sym.sourcePos)
140
141
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
142
146
143
147
/** Is there a repeated parameter in some parameter list? */
144
148
private def hasRepeatedParams (sym : Symbol )(using Context ): Boolean =
@@ -175,23 +179,30 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
175
179
* forwards it to `ddef`.
176
180
*/
177
181
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
183
183
184
184
// 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(
187
191
flags = if isBridge then flags | Artifact else flags,
188
192
info = toJavaVarArgs(ddef.symbol.info)
189
193
).asTerm
194
+ }
190
195
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
195
206
case Some (conflict) =>
196
207
ctx.error(s " @varargs produces a forwarder method that conflicts with ${conflict.showDcl}" , original.sourcePos)
197
208
ddef
@@ -201,15 +212,10 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
201
212
// Can't call `.argTypes` here because the underlying array type is of the
202
213
// form `Array[? <: SomeType]`, so we need `.argInfos` to get the `TypeBounds`.
203
214
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))
213
219
})
214
220
Thicket (ddef, bridgeDef)
215
221
0 commit comments