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