@@ -26,6 +26,8 @@ import scala.reflect.internal.util.ListOfNil
26
26
* - for every repeated Scala parameter `x: T*' --> x: Seq[T].
27
27
* - for every repeated Java parameter `x: T...' --> x: Array[T], except:
28
28
* if T is an unbounded abstract type, replace --> x: Array[Object]
29
+ * - for every method defining repeated parameters annotated with @varargs, generate
30
+ * a synthetic Java-style vararg method
29
31
* - for every argument list that corresponds to a repeated Scala parameter
30
32
* (a_1, ..., a_n) => (Seq(a_1, ..., a_n))
31
33
* - for every argument list that corresponds to a repeated Java parameter
@@ -43,6 +45,8 @@ import scala.reflect.internal.util.ListOfNil
43
45
* def liftedTry$1 = try { x_i } catch { .. }
44
46
* meth(x_1, .., liftedTry$1(), .. )
45
47
* }
48
+ * - remove calls to elidable methods and replace their bodies with NOPs when elide-below
49
+ * requires it
46
50
*/
47
51
/* </export> */
48
52
abstract class UnCurry extends InfoTransform
@@ -593,7 +597,13 @@ abstract class UnCurry extends InfoTransform
593
597
case None => newRhs
594
598
}
595
599
)
596
- addJavaVarargsForwarders(dd, flatdd)
600
+ // Only class members can reasonably be called from Java due to name mangling.
601
+ // Additionally, the Uncurry info transformer only adds a forwarder symbol to class members,
602
+ // since the other symbols are not part of the ClassInfoType (see reflect.internal.transform.UnCurry)
603
+ if (dd.symbol.owner.isClass)
604
+ addJavaVarargsForwarders(dd, flatdd)
605
+ else
606
+ flatdd
597
607
598
608
case tree : Try =>
599
609
if (tree.catches exists (cd => ! treeInfo.isCatchCase(cd)))
@@ -684,7 +694,7 @@ abstract class UnCurry extends InfoTransform
684
694
// declared type and assign this to a synthetic val. Later, we'll patch
685
695
// the method body to refer to this, rather than the parameter.
686
696
val tempVal : ValDef = {
687
- // SI-9442: using the "uncurry-erased" type (the one after the uncurry phase) can lead to incorrect
697
+ // SI-9442: using the "uncurry-erased" type (the one after the uncurry phase) can lead to incorrect
688
698
// tree transformations. For example, compiling:
689
699
// ```
690
700
// def foo(c: Ctx)(l: c.Tree): Unit = {
@@ -713,7 +723,7 @@ abstract class UnCurry extends InfoTransform
713
723
// to redo this desugaring manually here
714
724
// 2. the type needs to be normalized, since `gen.mkCast` checks this (no HK here, just aliases have
715
725
// to be expanded before handing the type to `gen.mkAttributedCast`, which calls `gen.mkCast`)
716
- val info0 =
726
+ val info0 =
717
727
enteringUncurry(p.symbol.info) match {
718
728
case DesugaredParameterType (desugaredTpe) =>
719
729
desugaredTpe
@@ -755,80 +765,59 @@ abstract class UnCurry extends InfoTransform
755
765
if (! hasRepeated) reporter.error(dd.symbol.pos, " A method without repeated parameters cannot be annotated with the `varargs` annotation." )
756
766
}
757
767
758
- /* Called during post transform, after the method argument lists have been flattened.
759
- * It looks for the method in the `repeatedParams` map, and generates a Java-style
768
+ /**
769
+ * Called during post transform, after the method argument lists have been flattened.
770
+ * It looks for the forwarder symbol in the symbol attachments and generates a Java-style
760
771
* varargs forwarder.
772
+ *
773
+ * @note The Java-style varargs method symbol is generated in the Uncurry info transformer. If the
774
+ * symbol can't be found this method reports a warning and carries on.
775
+ * @see [[scala.reflect.internal.transform.UnCurry ]]
761
776
*/
762
777
private def addJavaVarargsForwarders (dd : DefDef , flatdd : DefDef ): DefDef = {
763
778
if (! dd.symbol.hasAnnotation(VarargsClass ) || ! enteringUncurry(mexists(dd.symbol.paramss)(sym => definitions.isRepeatedParamType(sym.tpe))))
764
779
return flatdd
765
780
766
- def toArrayType (tp : Type ): Type = {
767
- val arg = elementType(SeqClass , tp)
768
- // to prevent generation of an `Object` parameter from `Array[T]` parameter later
769
- // as this would crash the Java compiler which expects an `Object[]` array for varargs
770
- // e.g. def foo[T](a: Int, b: T*)
771
- // becomes def foo[T](a: Int, b: Array[Object])
772
- // instead of def foo[T](a: Int, b: Array[T]) ===> def foo[T](a: Int, b: Object)
773
- arrayType(
774
- if (arg.typeSymbol.isTypeParameterOrSkolem) ObjectTpe
775
- else arg
776
- )
781
+ val forwSym : Symbol = {
782
+ currentClass.info // make sure the info is up to date, so the varargs forwarder symbol has been generated
783
+ flatdd.symbol.attachments.get[VarargsSymbolAttachment ] match {
784
+ case Some (VarargsSymbolAttachment (sym)) => sym
785
+ case None =>
786
+ reporter.warning(dd.pos, s " Could not generate Java varargs forwarder for ${flatdd.symbol}. Please file a bug. " )
787
+ return flatdd
788
+ }
777
789
}
778
790
779
- val theTyper = typer.atOwner(dd, currentClass)
780
- val flatparams = flatdd.symbol.paramss.head
791
+ val newPs = forwSym.tpe.params
781
792
val isRepeated = enteringUncurry(dd.symbol.info.paramss.flatten.map(sym => definitions.isRepeatedParamType(sym.tpe)))
793
+ val oldPs = flatdd.symbol.paramss.head
782
794
783
- // create the type
784
- val forwformals = map2(flatparams, isRepeated) {
785
- case (p, true ) => toArrayType(p.tpe)
786
- case (p, false )=> p.tpe
787
- }
788
- val forwresult = dd.symbol.tpe_* .finalResultType
789
- val forwformsyms = map2(forwformals, flatparams)((tp, oldparam) =>
790
- currentClass.newValueParameter(oldparam.name.toTermName, oldparam.pos).setInfo(tp)
791
- )
792
- def mono = MethodType (forwformsyms, forwresult)
793
- val forwtype = dd.symbol.tpe match {
794
- case MethodType (_, _) => mono
795
- case PolyType (tps, _) => PolyType (tps, mono)
796
- }
797
-
798
- // create the symbol
799
- val forwsym = currentClass.newMethod(dd.name.toTermName, dd.pos, VARARGS | SYNTHETIC | flatdd.symbol.flags) setInfo forwtype
800
- def forwParams = forwsym.info.paramss.flatten
801
-
802
- // create the tree
803
- val forwtree = theTyper.typedPos(dd.pos) {
804
- val locals = map3(forwParams, flatparams, isRepeated) {
805
- case (_, fp, false ) => null
806
- case (argsym, fp, true ) =>
807
- Block (Nil ,
808
- gen.mkCast(
809
- gen.mkWrapArray(Ident (argsym), elementType(ArrayClass , argsym.tpe)),
810
- seqType(elementType(SeqClass , fp.tpe))
811
- )
812
- )
813
- }
814
- val seqargs = map2(locals, forwParams) {
815
- case (null , argsym) => Ident (argsym)
816
- case (l, _) => l
817
- }
818
- val end = if (forwsym.isConstructor) List (UNIT ) else Nil
795
+ val theTyper = typer.atOwner(dd, currentClass)
796
+ val forwTree = theTyper.typedPos(dd.pos) {
797
+ val seqArgs = map3(newPs, oldPs, isRepeated)((param, oldParam, isRep) => {
798
+ if (! isRep) Ident (param)
799
+ else {
800
+ val parTp = elementType(ArrayClass , param.tpe)
801
+ val wrap = gen.mkWrapArray(Ident (param), parTp)
802
+ param.attachments.get[TypeParamVarargsAttachment ] match {
803
+ case Some (TypeParamVarargsAttachment (tp)) => gen.mkCast(wrap, seqType(tp))
804
+ case _ => wrap
805
+ }
806
+ }
807
+ })
819
808
820
- DefDef (forwsym, BLOCK (Apply (gen.mkAttributedRef(flatdd.symbol), seqargs) :: end : _* ))
809
+ val forwCall = Apply (gen.mkAttributedRef(flatdd.symbol), seqArgs)
810
+ DefDef (forwSym, if (forwSym.isConstructor) Block (List (forwCall), UNIT ) else forwCall)
821
811
}
822
812
823
813
// check if the method with that name and those arguments already exists in the template
824
- currentClass.info.member(forwsym .name).alternatives.find(s => s != forwsym && s.tpe.matches(forwsym .tpe)) match {
825
- case Some (s) => reporter.error(dd.symbol.pos,
826
- " A method with a varargs annotation produces a forwarder method with the same signature "
827
- + s.tpe + " as an existing method." )
814
+ enteringUncurry( currentClass.info.member(forwSym .name).alternatives.find(s => s != forwSym && s.tpe.matches(forwSym .tpe) )) match {
815
+ case Some (s) =>
816
+ reporter.error(dd.symbol.pos,
817
+ s " A method with a varargs annotation produces a forwarder method with the same signature ${ s.tpe} as an existing method. " )
828
818
case None =>
829
819
// enter symbol into scope
830
- currentClass.info.decls enter forwsym
831
- addNewMember(forwtree)
820
+ addNewMember(forwTree)
832
821
}
833
822
834
823
flatdd
0 commit comments