@@ -13,6 +13,7 @@ import dotty.tools.dotc.ast.tpd
13
13
import dotty .tools .dotc .ast .Trees
14
14
import dotty .tools .dotc .core .Annotations .Annotation
15
15
import dotty .tools .dotc .core .Constants ._
16
+ import dotty .tools .dotc .core .Contexts .Context
16
17
import dotty .tools .dotc .core .Decorators ._
17
18
import dotty .tools .dotc .core .Flags
18
19
import dotty .tools .dotc .core .Names .Name
@@ -22,6 +23,8 @@ import dotty.tools.dotc.core.StdNames._
22
23
import dotty .tools .dotc .core .Symbols ._
23
24
import dotty .tools .dotc .core .Types
24
25
import dotty .tools .dotc .core .Types ._
26
+ import dotty .tools .dotc .core .TypeErasure
27
+ import dotty .tools .dotc .transform .GenericSignatures
25
28
26
29
/*
27
30
* Traits encapsulating functionality to convert Scala AST Trees into ASM ClassNodes.
@@ -450,16 +453,27 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
450
453
} // end of trait BCAnnotGen
451
454
452
455
trait BCJGenSigGen {
456
+ import int ._
453
457
454
458
def getCurrentCUnit (): CompilationUnit
455
459
456
- /* @return
457
- * - `null` if no Java signature is to be added (`null` is what ASM expects in these cases).
458
- * - otherwise the signature in question
460
+ /**
461
+ * Generates the generic signature for `sym` before erasure.
459
462
*
460
- * must-single-thread
463
+ * @param sym The symbol for which to generate a signature.
464
+ * @param owner The owner of `sym`.
465
+ * @return The generic signature of `sym` before erasure, as specified in the Java Virtual
466
+ * Machine Specification, §4.3.4, or `null` if `sym` doesn't need a generic signature.
467
+ * @see https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.4
461
468
*/
462
- def getGenericSignature (sym : Symbol , owner : Symbol ): String = int.getGenericSignature(sym, owner)
469
+ def getGenericSignature (sym : Symbol , owner : Symbol ): String = {
470
+ ctx.atPhase(ctx.erasurePhase) {
471
+ val memberTpe =
472
+ if (sym.is(Flags .Method )) sym.denot.info
473
+ else owner.denot.thisType.memberInfo(sym)
474
+ getGenericSignatureHelper(sym, owner, memberTpe).orNull
475
+ }
476
+ }
463
477
464
478
} // end of trait BCJGenSigGen
465
479
@@ -829,6 +843,82 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
829
843
}
830
844
}
831
845
}
846
+
847
+ private def getGenericSignatureHelper (sym : Symbol , owner : Symbol , memberTpe : Type )(implicit ctx : Context ): Option [String ] = {
848
+ if (needsGenericSignature(sym)) {
849
+ val erasedTypeSym = TypeErasure .fullErasure(sym.denot.info).typeSymbol
850
+ if (erasedTypeSym.isPrimitiveValueClass) {
851
+ // Suppress signatures for symbols whose types erase in the end to primitive
852
+ // value types. This is needed to fix #7416.
853
+ None
854
+ } else {
855
+ val jsOpt = GenericSignatures .javaSig(sym, memberTpe)
856
+ if (ctx.settings.XverifySignatures .value) {
857
+ jsOpt.foreach(verifySignature(sym, _))
858
+ }
859
+
860
+ jsOpt
861
+ }
862
+ } else {
863
+ None
864
+ }
865
+ }
866
+
867
+ private def verifySignature (sym : Symbol , sig : String )(implicit ctx : Context ): Unit = {
868
+ import scala .tools .asm .util .CheckClassAdapter
869
+ def wrap (body : => Unit ): Unit = {
870
+ try body
871
+ catch {
872
+ case ex : Throwable =>
873
+ ctx.error(i """ |compiler bug: created invalid generic signature for $sym in ${sym.denot.owner.showFullName}
874
+ |signature: $sig
875
+ |if this is reproducible, please report bug at https://github.com/lampepfl/dotty/issues
876
+ """ .trim, sym.sourcePos)
877
+ throw ex
878
+ }
879
+ }
880
+
881
+ wrap {
882
+ if (sym.is(Flags .Method )) {
883
+ CheckClassAdapter .checkMethodSignature(sig)
884
+ }
885
+ else if (sym.isTerm) {
886
+ CheckClassAdapter .checkFieldSignature(sig)
887
+ }
888
+ else {
889
+ CheckClassAdapter .checkClassSignature(sig)
890
+ }
891
+ }
892
+ }
893
+
894
+ // @M don't generate java generics sigs for (members of) implementation
895
+ // classes, as they are monomorphic (TODO: ok?)
896
+ private final def needsGenericSignature (sym : Symbol ): Boolean = ! (
897
+ // pp: this condition used to include sym.hasexpandedname, but this leads
898
+ // to the total loss of generic information if a private member is
899
+ // accessed from a closure: both the field and the accessor were generated
900
+ // without it. This is particularly bad because the availability of
901
+ // generic information could disappear as a consequence of a seemingly
902
+ // unrelated change.
903
+ ctx.base.settings.YnoGenericSig .value
904
+ || sym.is(Flags .Artifact )
905
+ || sym.isAllOf(Flags .LiftedMethod )
906
+ || sym.is(Flags .Bridge )
907
+ )
908
+
909
+ private def getStaticForwarderGenericSignature (sym : Symbol , moduleClass : Symbol ): String = {
910
+ // scala/bug#3452 Static forwarder generation uses the same erased signature as the method if forwards to.
911
+ // By rights, it should use the signature as-seen-from the module class, and add suitable
912
+ // primitive and value-class boxing/unboxing.
913
+ // But for now, just like we did in mixin, we just avoid writing a wrong generic signature
914
+ // (one that doesn't erase to the actual signature). See run/t3452b for a test case.
915
+
916
+ val memberTpe = ctx.atPhase(ctx.erasurePhase) { moduleClass.denot.thisType.memberInfo(sym) }
917
+ val erasedMemberType = TypeErasure .erasure(memberTpe)
918
+ if (erasedMemberType =:= sym.denot.info)
919
+ getGenericSignatureHelper(sym, moduleClass, memberTpe).orNull
920
+ else null
921
+ }
832
922
}
833
923
834
924
object BCodeHelpers {
0 commit comments