@@ -179,7 +179,9 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
179179 * code would have two extra parameters for each of the many calls that go from
180180 * one sub-part of isSubType to another.
181181 */
182- protected def recur (tp1 : Type , tp2 : Type ): Boolean = trace(s " isSubType ${traceInfo(tp1, tp2)} $approx" , subtyping) {
182+ protected def recur (tp1 : Type , tp2 : Type ): Boolean =
183+ // trace.force(s"isSubType ${traceInfo(tp1, tp2)} $approx", subtyping)
184+ {
183185
184186 def monitoredIsSubType = {
185187 if (pendingSubTypes == null ) {
@@ -2104,40 +2106,31 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
21042106 import config .Printers .debug
21052107 import typer .Inferencing ._
21062108
2107- def incompatibleClasses : Boolean = {
2109+ def compatibleClasses : Boolean = {
21082110 import Flags ._
21092111 val tpClassSym = tp.widenSingleton.classSymbol
21102112 val ptClassSym = pt.widenSingleton.classSymbol
21112113 debug.println(i " tpClassSym= $tpClassSym, fin= ${tpClassSym.is(Final )}" )
21122114 debug.println(i " pt= $pt { ${pt.getClass}}, ptClassSym= $ptClassSym, fin= ${ptClassSym.is(Final )}" )
2113- tpClassSym.exists && ptClassSym.exists && {
2114- if (tpClassSym.is(Final )) ! tpClassSym.derivesFrom(ptClassSym)
2115- else if (ptClassSym.is(Final )) ! ptClassSym.derivesFrom(tpClassSym)
2115+ ! tpClassSym.exists || ! ptClassSym.exists || {
2116+ if (tpClassSym.is(Final )) tpClassSym.derivesFrom(ptClassSym)
2117+ else if (ptClassSym.is(Final )) ptClassSym.derivesFrom(tpClassSym)
21162118 else if (! tpClassSym.is(Flags .Trait ) && ! ptClassSym.is(Flags .Trait ))
2117- ! ( tpClassSym.derivesFrom(ptClassSym) || ptClassSym.derivesFrom(tpClassSym) )
2118- else false
2119+ tpClassSym.derivesFrom(ptClassSym) || ptClassSym.derivesFrom(tpClassSym)
2120+ else true
21192121 }
21202122 }
21212123
21222124 def loop (tp : Type ): Boolean =
21232125// trace.force(i"loop($tp) // ${tp.toString}")
21242126 {
2125- if (constrainPatternType(pt, tp)) true
2126- else if (incompatibleClasses) {
2127- // println("incompatible classes")
2128- false
2129- }
2130- else tp match {
2131- case _ : ConstantType =>
2132- // constants cannot possibly intersect with types that aren't their supertypes
2133- false
2134- case tp : SingletonType => loop(tp.underlying)
2135- case tp : TypeRef if tp.symbol.isClass => loop(tp.firstParent)
2127+ val res : Type = tp match {
2128+ case tp : TypeRef if tp.symbol.isClass => tp.firstParent
21362129 case tp @ AppliedType (tycon : TypeRef , _) if tycon.symbol.isClass =>
21372130 val ptClassSym = pt.classSymbol
21382131 def firstParentSharedWithPt (tp : Type , tpClassSym : ClassSymbol ): Symbol =
2139- // trace.force(i"f($tp)")
2140- {
2132+ // trace.force(i"f($tp)")
2133+ {
21412134 var parents = tpClassSym.info.parents
21422135// println(i"parents of $tpClassSym = $parents%, %")
21432136 parents match {
@@ -2156,29 +2149,89 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
21562149 }
21572150 val sym = firstParentSharedWithPt(tycon, tycon.symbol.asClass)
21582151// println(i"sym=$sym ; tyconsym=${tycon.symbol}")
2159- if (! sym.exists) true
2160- else ! (sym == tycon.symbol) && loop(tp.baseType(sym))
2152+ if (! sym.exists) return true
2153+ // else !(sym == tycon.symbol) &&
2154+ tp.baseType(sym)
21612155 case tp : TypeProxy =>
2162- loop( tp.superType)
2163- case _ => false
2156+ tp.superType
2157+ case _ => return true
21642158 }
2159+ constrainPatternType(pt, res) || loop(res)
21652160 }
21662161
2167- pt match {
2168- case AndType (pt1, pt2) =>
2169- notIntersection(tp, pt1) && notIntersection(tp, pt2)
2170- case OrType (pt1, pt2) =>
2171- either(notIntersection(tp, pt1), notIntersection(tp, pt2))
2172- case _ =>
2173- tp match {
2174- case OrType (tp1, tp2) =>
2175- either(notIntersection(tp1, pt), notIntersection(tp2, pt))
2176- case AndType (tp1, tp2) =>
2177- notIntersection(tp1, pt) && notIntersection(tp2, pt)
2178- case _ =>
2179- loop(tp)
2180- }
2181- }
2162+ tp.dealias match {
2163+ case OrType (tp1, tp2) =>
2164+ either(notIntersection(tp1, pt), notIntersection(tp2, pt))
2165+ case AndType (tp1, tp2) =>
2166+ notIntersection(tp1, pt) && notIntersection(tp2, pt)
2167+ case tp : RefinedOrRecType =>
2168+ def keepInvariantRefinements (tp : Type ): Type = tp match {
2169+ case tp : RefinedType =>
2170+ if (tp.refinedName.isTermName) keepInvariantRefinements(tp.parent)
2171+ else {
2172+ // def resolve(tp: Type): Type = tp match {
2173+ // case TypeAlias(tp) => resolve(tp.dealias)
2174+ // case tp => tp
2175+ // }
2176+ // val tpInfo = tp.refinedInfo
2177+ // val tpInfoDealiased = resolve(tpInfo)
2178+ // val ptInfo = pt.member(tp.refinedName).info
2179+ // val ptInfoDealiased = resolve(ptInfo)
2180+ // println(
2181+ // i"""tpInfo = ${tpInfo}
2182+ // |tpInfoDealiased = ${tpInfoDealiased}
2183+ // |ptInfo = ${ptInfo}
2184+ // |ptInfoDealiased = ${ptInfoDealiased}""".stripMargin
2185+ // )
2186+ // println(i"visiting refinement: ${tp.refinedName} : ${tp.refinedInfo}")
2187+ tp.refinedInfo match {
2188+ case TypeAlias (tp1) =>
2189+ val pt1 = pt.member(tp.refinedName).info
2190+ if (pt1.exists && pt1.bounds.contains(tp1) || ! pt1.exists)
2191+ keepInvariantRefinements(tp.parent)
2192+ else
2193+ NoType
2194+ case tpb : TypeBounds =>
2195+ pt.member(tp.refinedName).info match {
2196+ case TypeAlias (pt1) =>
2197+ if (tpb.contains(pt1))
2198+ keepInvariantRefinements(tp.parent)
2199+ else
2200+ NoType
2201+ case _ =>
2202+ keepInvariantRefinements(tp.parent)
2203+ }
2204+ }
2205+ }
2206+ case tp : RecType =>
2207+ keepInvariantRefinements(tp.parent)
2208+ case _ =>
2209+ tp
2210+ }
2211+ val tp1 = keepInvariantRefinements(tp)
2212+ if (! tp1.exists) {
2213+ // println(i"noType for $tp")
2214+ false
2215+ } else
2216+ notIntersection(tp1, pt)
2217+ case tp =>
2218+ pt.dealias match {
2219+ case AndType (pt1, pt2) =>
2220+ notIntersection(tp, pt1) && notIntersection(tp, pt2)
2221+ case OrType (pt1, pt2) =>
2222+ either(notIntersection(tp, pt1), notIntersection(tp, pt2))
2223+ case pt : RefinedOrRecType =>
2224+ // note: at this point, we have already extracted the information we wanted from the refinement
2225+ // and it would only interfere in the following subtype check in constrainPatternType
2226+ def stripRefinement (tp : Type ): Type = tp match {
2227+ case tp : RefinedOrRecType => stripRefinement(tp.parent)
2228+ case tp => tp
2229+ }
2230+ notIntersection(tp, stripRefinement(pt))
2231+ case pt =>
2232+ constrainPatternType(pt, tp) || compatibleClasses && loop(tp)
2233+ }
2234+ }
21822235 }
21832236}
21842237
0 commit comments