@@ -782,6 +782,67 @@ object TypeOps:
782
782
* Otherwise, return NoType.
783
783
*/
784
784
private def instantiateToSubType (tp1 : NamedType , tp2 : Type , mixins : List [Type ])(using Context ): Type = trace(i " instantiateToSubType( $tp1, $tp2, $mixins) " , typr) {
785
+ /** Gather GADT symbols and singletons found in `tp2`, ie. the scrutinee. */
786
+ object TraverseTp2 extends TypeTraverser :
787
+ val singletons = util.HashMap [Symbol , SingletonType ]()
788
+ val gadtSyms = new mutable.ListBuffer [Symbol ]
789
+
790
+ def traverse (tp : Type ) = try
791
+ val tpd = tp.dealias
792
+ if tpd ne tp then traverse(tpd)
793
+ else tp match
794
+ case tp : ThisType if ! singletons.contains(tp.tref.symbol) && ! tp.tref.symbol.isStaticOwner =>
795
+ singletons(tp.tref.symbol) = tp
796
+ traverseChildren(tp.tref)
797
+ case tp : TermRef =>
798
+ singletons(tp.typeSymbol) = tp
799
+ traverseChildren(tp)
800
+ case tp : TypeRef if ! gadtSyms.contains(tp.symbol) && tp.symbol.isAbstractOrParamType =>
801
+ gadtSyms += tp.symbol
802
+ traverseChildren(tp)
803
+ // traverse abstract type infos, to add any singletons
804
+ // for example, i16451.CanForward.scala, add `Namer.this`, from the info of the type parameter `A1`
805
+ // also, i19031.ci-reg2.scala, add `out`, from the info of the type parameter `A1` (from synthetic applyOrElse)
806
+ traverseChildren(tp.info)
807
+ case _ =>
808
+ traverseChildren(tp)
809
+ catch case ex : Throwable => handleRecursive(" traverseTp2" , tp.show, ex)
810
+ TraverseTp2 .traverse(tp2)
811
+ val singletons = TraverseTp2 .singletons
812
+ val gadtSyms = TraverseTp2 .gadtSyms.toList
813
+
814
+ // Prefix inference, given `p.C.this.Child`:
815
+ // 1. return it as is, if `C.this` is found in `tp`, i.e. the scrutinee; or
816
+ // 2. replace it with `X.Child` where `X <: p.C`, stripping ThisType in `p` recursively.
817
+ //
818
+ // See tests/patmat/i3938.scala, tests/pos/i15029.more.scala, tests/pos/i16785.scala
819
+ class InferPrefixMap extends TypeMap {
820
+ var prefixTVar : Type | Null = null
821
+ def apply (tp : Type ): Type = tp match {
822
+ case tp : TermRef if singletons.contains(tp.symbol) =>
823
+ prefixTVar = singletons(tp.symbol) // e.g. tests/pos/i19031.ci-reg2.scala, keep out
824
+ prefixTVar.uncheckedNN
825
+ case ThisType (tref) if ! tref.symbol.isStaticOwner =>
826
+ val symbol = tref.symbol
827
+ if singletons.contains(symbol) then
828
+ prefixTVar = singletons(symbol) // e.g. tests/pos/i16785.scala, keep Outer.this
829
+ prefixTVar.uncheckedNN
830
+ else if symbol.is(Module ) then
831
+ TermRef (this (tref.prefix), symbol.sourceModule)
832
+ else if (prefixTVar != null )
833
+ this (tref.applyIfParameterized(tref.typeParams.map(_ => WildcardType )))
834
+ else {
835
+ prefixTVar = WildcardType // prevent recursive call from assigning it
836
+ // e.g. tests/pos/i15029.more.scala, create a TypeVar for `Instances`' B, so we can disregard `Ints`
837
+ val tvars = tref.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds, DepParamName .fresh(tparam.paramName)) }
838
+ val tref2 = this (tref.applyIfParameterized(tvars))
839
+ prefixTVar = newTypeVar(TypeBounds .upper(tref2), DepParamName .fresh(tref.name))
840
+ prefixTVar.uncheckedNN
841
+ }
842
+ case tp => mapOver(tp)
843
+ }
844
+ }
845
+
785
846
// In order for a child type S to qualify as a valid subtype of the parent
786
847
// T, we need to test whether it is possible S <: T.
787
848
//
@@ -803,8 +864,15 @@ object TypeOps:
803
864
// then to avoid it failing the <:<
804
865
// we'll approximate by widening to its bounds
805
866
867
+ case tp : TermRef if singletons.contains(tp.symbol) =>
868
+ singletons(tp.symbol)
869
+
806
870
case ThisType (tref : TypeRef ) if ! tref.symbol.isStaticOwner =>
807
- tref
871
+ val symbol = tref.symbol
872
+ if singletons.contains(symbol) then
873
+ singletons(symbol)
874
+ else
875
+ tref
808
876
809
877
case tp : TypeRef if ! tp.symbol.isClass =>
810
878
val lookup = boundTypeParams.lookup(tp)
@@ -855,67 +923,6 @@ object TypeOps:
855
923
}
856
924
}
857
925
858
- /** Gather GADT symbols and singletons found in `tp2`, ie. the scrutinee. */
859
- object TraverseTp2 extends TypeTraverser :
860
- val singletons = util.HashMap [Symbol , SingletonType ]()
861
- val gadtSyms = new mutable.ListBuffer [Symbol ]
862
-
863
- def traverse (tp : Type ) = try
864
- val tpd = tp.dealias
865
- if tpd ne tp then traverse(tpd)
866
- else tp match
867
- case tp : ThisType if ! singletons.contains(tp.tref.symbol) && ! tp.tref.symbol.isStaticOwner =>
868
- singletons(tp.tref.symbol) = tp
869
- traverseChildren(tp.tref)
870
- case tp : TermRef if tp.symbol.is(Param ) =>
871
- singletons(tp.typeSymbol) = tp
872
- traverseChildren(tp)
873
- case tp : TypeRef if ! gadtSyms.contains(tp.symbol) && tp.symbol.isAbstractOrParamType =>
874
- gadtSyms += tp.symbol
875
- traverseChildren(tp)
876
- // traverse abstract type infos, to add any singletons
877
- // for example, i16451.CanForward.scala, add `Namer.this`, from the info of the type parameter `A1`
878
- // also, i19031.ci-reg2.scala, add `out`, from the info of the type parameter `A1` (from synthetic applyOrElse)
879
- traverseChildren(tp.info)
880
- case _ =>
881
- traverseChildren(tp)
882
- catch case ex : Throwable => handleRecursive(" traverseTp2" , tp.show, ex)
883
- TraverseTp2 .traverse(tp2)
884
- val singletons = TraverseTp2 .singletons
885
- val gadtSyms = TraverseTp2 .gadtSyms.toList
886
-
887
- // Prefix inference, given `p.C.this.Child`:
888
- // 1. return it as is, if `C.this` is found in `tp`, i.e. the scrutinee; or
889
- // 2. replace it with `X.Child` where `X <: p.C`, stripping ThisType in `p` recursively.
890
- //
891
- // See tests/patmat/i3938.scala, tests/pos/i15029.more.scala, tests/pos/i16785.scala
892
- class InferPrefixMap extends TypeMap {
893
- var prefixTVar : Type | Null = null
894
- def apply (tp : Type ): Type = tp match {
895
- case tp : TermRef if singletons.contains(tp.symbol) =>
896
- prefixTVar = singletons(tp.symbol) // e.g. tests/pos/i19031.ci-reg2.scala, keep out
897
- prefixTVar.uncheckedNN
898
- case ThisType (tref) if ! tref.symbol.isStaticOwner =>
899
- val symbol = tref.symbol
900
- if singletons.contains(symbol) then
901
- prefixTVar = singletons(symbol) // e.g. tests/pos/i16785.scala, keep Outer.this
902
- prefixTVar.uncheckedNN
903
- else if symbol.is(Module ) then
904
- TermRef (this (tref.prefix), symbol.sourceModule)
905
- else if (prefixTVar != null )
906
- this (tref.applyIfParameterized(tref.typeParams.map(_ => WildcardType )))
907
- else {
908
- prefixTVar = WildcardType // prevent recursive call from assigning it
909
- // e.g. tests/pos/i15029.more.scala, create a TypeVar for `Instances`' B, so we can disregard `Ints`
910
- val tvars = tref.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds, DepParamName .fresh(tparam.paramName)) }
911
- val tref2 = this (tref.applyIfParameterized(tvars))
912
- prefixTVar = newTypeVar(TypeBounds .upper(tref2), DepParamName .fresh(tref.name))
913
- prefixTVar.uncheckedNN
914
- }
915
- case tp => mapOver(tp)
916
- }
917
- }
918
-
919
926
val inferThisMap = new InferPrefixMap
920
927
val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds, DepParamName .fresh(tparam.paramName)) }
921
928
val protoTp1 = inferThisMap.apply(tp1).appliedTo(tvars)
0 commit comments