@@ -782,6 +782,67 @@ object TypeOps:
782782   *  Otherwise, return NoType. 
783783   */  
784784  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+ 
785846    //  In order for a child type S to qualify as a valid subtype of the parent
786847    //  T, we need to test whether it is possible S <: T.
787848    // 
@@ -803,8 +864,15 @@ object TypeOps:
803864                                 //  then to avoid it failing the <:<
804865                                 //  we'll approximate by widening to its bounds
805866
867+         case  tp : TermRef  if  singletons.contains(tp.symbol) => 
868+           singletons(tp.symbol)
869+ 
806870        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
808876
809877        case  tp : TypeRef  if  ! tp.symbol.isClass => 
810878          val  lookup  =  boundTypeParams.lookup(tp)
@@ -855,67 +923,6 @@ object TypeOps:
855923      }
856924    }
857925
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- 
919926    val  inferThisMap  =  new  InferPrefixMap 
920927    val  tvars  =  tp1.typeParams.map { tparam =>  newTypeVar(tparam.paramInfo.bounds, DepParamName .fresh(tparam.paramName)) }
921928    val  protoTp1  =  inferThisMap.apply(tp1).appliedTo(tvars)
0 commit comments