@@ -2,7 +2,7 @@ package dotty.tools
2
2
package dotc
3
3
package core
4
4
5
- import Contexts ._ , Types ._ , Symbols ._ , Names ._ , Flags ._
5
+ import Contexts ._ , Types ._ , Symbols ._ , Names ._ , NameKinds . * , Flags ._
6
6
import SymDenotations ._
7
7
import util .Spans ._
8
8
import util .Stats
@@ -839,40 +839,63 @@ object TypeOps:
839
839
}
840
840
}
841
841
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.
844
867
//
845
- // See tests/patmat/i3938.scala
868
+ // See tests/patmat/i3938.scala, tests/pos/i15029.more.scala, tests/pos/i16785.scala
846
869
class InferPrefixMap extends TypeMap {
847
870
var prefixTVar : Type | Null = null
848
871
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 =>
850
873
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
852
878
TermRef (this (tref.prefix), symbol.sourceModule)
853
879
else if (prefixTVar != null )
854
880
this (tref)
855
881
else {
856
882
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)) }
858
885
val tref2 = this (tref.applyIfParameterized(tvars))
859
- prefixTVar = newTypeVar(TypeBounds .upper(tref2))
886
+ prefixTVar = newTypeVar(TypeBounds .upper(tref2), DepParamName .fresh(tref.name) )
860
887
prefixTVar.uncheckedNN
861
888
}
862
889
case tp => mapOver(tp)
863
890
}
864
891
}
865
892
866
893
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) ) }
868
895
val protoTp1 = inferThisMap.apply(tp1).appliedTo(tvars)
869
896
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)
876
899
877
900
// If parent contains a reference to an abstract type, then we should
878
901
// refine subtype checking to eliminate abstract types according to
0 commit comments