@@ -662,10 +662,18 @@ abstract class BTypes {
662
662
663
663
def isInterface : Either [NoClassBTypeInfo , Boolean ] = info.map(i => (i.flags & asm.Opcodes .ACC_INTERFACE ) != 0 )
664
664
665
- def superClassesTransitive : Either [NoClassBTypeInfo , List [ClassBType ]] = info.flatMap(i => i.superClass match {
666
- case None => Right (Nil )
667
- case Some (sc) => sc.superClassesTransitive.map(sc :: _)
668
- })
665
+ /** The super class chain of this type, starting with Object, ending with `this`. */
666
+ def superClassesChain : Either [NoClassBTypeInfo , List [ClassBType ]] = try {
667
+ var res = List (this )
668
+ var sc = info.orThrow.superClass
669
+ while (sc.nonEmpty) {
670
+ res ::= sc.get
671
+ sc = sc.get.info.orThrow.superClass
672
+ }
673
+ Right (res)
674
+ } catch {
675
+ case Invalid (noInfo : NoClassBTypeInfo ) => Left (noInfo)
676
+ }
669
677
670
678
/**
671
679
* The prefix of the internal name until the last '/', or the empty string.
@@ -737,7 +745,7 @@ abstract class BTypes {
737
745
* Background:
738
746
* http://gallium.inria.fr/~xleroy/publi/bytecode-verification-JAR.pdf
739
747
* http://comments.gmane.org/gmane.comp.java.vm.languages/2293
740
- * https://github.com/scala/bug/issues/3872
748
+ * https://github.com/scala/bug/issues/3872#issuecomment-292386375
741
749
*/
742
750
def jvmWiseLUB (other : ClassBType ): Either [NoClassBTypeInfo , ClassBType ] = {
743
751
def isNotNullOrNothing (c : ClassBType ) = ! c.isNullType && ! c.isNothingType
@@ -758,14 +766,7 @@ abstract class BTypes {
758
766
if (this .isSubtypeOf(other).orThrow) other else ObjectRef
759
767
760
768
case _ =>
761
- // TODO @lry I don't really understand the reasoning here.
762
- // Both this and other are classes. The code takes (transitively) all superclasses and
763
- // finds the first common one.
764
- // MOST LIKELY the answer can be found here, see the comments and links by Miguel:
765
- // - https://github.com/scala/bug/issues/3872
766
- // @jz Wouldn't it be better to walk the superclass chain of both types in reverse (starting from Object), and
767
- // finding the last common link? That would be O(N), whereas this looks O(N^2)
768
- firstCommonSuffix(this :: this .superClassesTransitive.orThrow, other :: other.superClassesTransitive.orThrow)
769
+ firstCommonSuffix(superClassesChain.orThrow, other.superClassesChain.orThrow)
769
770
}
770
771
771
772
assert(isNotNullOrNothing(res), s " jvmWiseLUB computed: $res" )
@@ -774,17 +775,16 @@ abstract class BTypes {
774
775
}
775
776
776
777
private def firstCommonSuffix (as : List [ClassBType ], bs : List [ClassBType ]): ClassBType = {
777
- var chainA = as
778
- var chainB = bs
779
- var fcs : ClassBType = null
780
- do {
781
- if (chainB contains chainA.head) fcs = chainA.head
782
- else if (chainA contains chainB.head) fcs = chainB.head
783
- else {
784
- chainA = chainA.tail
785
- chainB = chainB.tail
786
- }
787
- } while (fcs == null )
778
+ // assert(as.head == ObjectRef, as.head)
779
+ // assert(bs.head == ObjectRef, bs.head)
780
+ var chainA = as.tail
781
+ var chainB = bs.tail
782
+ var fcs = ObjectRef
783
+ while (chainA.nonEmpty && chainB.nonEmpty && chainA.head == chainB.head) {
784
+ fcs = chainA.head
785
+ chainA = chainA.tail
786
+ chainB = chainB.tail
787
+ }
788
788
fcs
789
789
}
790
790
}
0 commit comments