@@ -767,6 +767,67 @@ object TypeOps:
767767   *  Otherwise, return NoType. 
768768   */  
769769  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+ 
770831    //  In order for a child type S to qualify as a valid subtype of the parent
771832    //  T, we need to test whether it is possible S <: T.
772833    // 
@@ -788,8 +849,15 @@ object TypeOps:
788849                                 //  then to avoid it failing the <:<
789850                                 //  we'll approximate by widening to its bounds
790851
852+         case  tp : TermRef  if  singletons.contains(tp.symbol) => 
853+           singletons(tp.symbol)
854+ 
791855        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
793861
794862        case  tp : TypeRef  if  ! tp.symbol.isClass => 
795863          val  lookup  =  boundTypeParams.lookup(tp)
@@ -840,67 +908,6 @@ object TypeOps:
840908      }
841909    }
842910
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- 
904911    val  inferThisMap  =  new  InferPrefixMap 
905912    val  tvars  =  tp1.typeParams.map { tparam =>  newTypeVar(tparam.paramInfo.bounds, DepParamName .fresh(tparam.paramName)) }
906913    val  protoTp1  =  inferThisMap.apply(tp1).appliedTo(tvars)
0 commit comments