@@ -2,7 +2,7 @@ package dotty.tools
22package dotc
33package core
44
5- import Contexts ._ , Types ._ , Symbols ._ , Names ._ , Flags ._
5+ import Contexts ._ , Types ._ , Symbols ._ , Names ._ , NameKinds . * , Flags ._
66import SymDenotations ._
77import util .Spans ._
88import util .Stats
@@ -839,40 +839,63 @@ object TypeOps:
839839 }
840840 }
841841
842- // Prefix inference, replace `p.C.this.Child` with `X.Child` where `X <: p.C`
843- // Note: we need to strip ThisType in `p` recursively.
842+ /** Gather GADT symbols and `ThisType`s found in `tp2`, ie. the scrutinee. */
843+ object TraverseTp2 extends TypeTraverser :
844+ val thisTypes = util.HashSet [ThisType ]()
845+ val gadtSyms = new mutable.ListBuffer [Symbol ]
846+
847+ def traverse (tp : Type ) = {
848+ val tpd = tp.dealias
849+ if tpd ne tp then traverse(tpd)
850+ else tp match
851+ case tp : ThisType if ! tp.tref.symbol.isStaticOwner && ! thisTypes.contains(tp) =>
852+ thisTypes += tp
853+ traverseChildren(tp.tref)
854+ case tp : TypeRef if tp.symbol.isAbstractOrParamType =>
855+ gadtSyms += tp.symbol
856+ traverseChildren(tp)
857+ case _ =>
858+ traverseChildren(tp)
859+ }
860+ TraverseTp2 .traverse(tp2)
861+ val thisTypes = TraverseTp2 .thisTypes
862+ val gadtSyms = TraverseTp2 .gadtSyms.toList
863+
864+ // Prefix inference, given `p.C.this.Child`:
865+ // 1. return it as is, if `C.this` is found in `tp`, i.e. the scrutinee; or
866+ // 2. replace it with `X.Child` where `X <: p.C`, stripping ThisType in `p` recursively.
844867 //
845- // See tests/patmat/i3938.scala
868+ // See tests/patmat/i3938.scala, tests/pos/i15029.more.scala, tests/pos/i16785.scala
846869 class InferPrefixMap extends TypeMap {
847870 var prefixTVar : Type | Null = null
848871 def apply (tp : Type ): Type = tp match {
849- case ThisType (tref : TypeRef ) if ! tref.symbol.isStaticOwner =>
872+ case tp @ ThisType (tref) if ! tref.symbol.isStaticOwner =>
850873 val symbol = tref.symbol
851- if (symbol.is(Module ))
874+ if thisTypes.contains(tp) then
875+ prefixTVar = tp // e.g. tests/pos/i16785.scala, keep Outer.this
876+ prefixTVar.uncheckedNN
877+ else if symbol.is(Module ) then
852878 TermRef (this (tref.prefix), symbol.sourceModule)
853879 else if (prefixTVar != null )
854880 this (tref)
855881 else {
856882 prefixTVar = WildcardType // prevent recursive call from assigning it
857- val tvars = tref.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
883+ // e.g. tests/pos/i15029.more.scala, create a TypeVar for `Instances`' B, so we can disregard `Ints`
884+ val tvars = tref.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds, DepParamName .fresh(tparam.paramName)) }
858885 val tref2 = this (tref.applyIfParameterized(tvars))
859- prefixTVar = newTypeVar(TypeBounds .upper(tref2))
886+ prefixTVar = newTypeVar(TypeBounds .upper(tref2), DepParamName .fresh(tref.name) )
860887 prefixTVar.uncheckedNN
861888 }
862889 case tp => mapOver(tp)
863890 }
864891 }
865892
866893 val inferThisMap = new InferPrefixMap
867- val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
894+ val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds, DepParamName .fresh(tparam.paramName) ) }
868895 val protoTp1 = inferThisMap.apply(tp1).appliedTo(tvars)
869896
870- val getAbstractSymbols = new TypeAccumulator [List [Symbol ]]:
871- def apply (xs : List [Symbol ], tp : Type ) = tp.dealias match
872- case tp : TypeRef if tp.symbol.exists && ! tp.symbol.isClass => foldOver(tp.symbol :: xs, tp)
873- case tp => foldOver(xs, tp)
874- val syms2 = getAbstractSymbols(Nil , tp2).reverse
875- if syms2.nonEmpty then ctx.gadtState.addToConstraint(syms2)
897+ if gadtSyms.nonEmpty then
898+ ctx.gadtState.addToConstraint(gadtSyms)
876899
877900 // If parent contains a reference to an abstract type, then we should
878901 // refine subtype checking to eliminate abstract types according to
0 commit comments