@@ -176,7 +176,9 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
176176 * code would have two extra parameters for each of the many calls that go from
177177 * one sub-part of isSubType to another.
178178 */
179- protected def recur (tp1 : Type , tp2 : Type ): Boolean = trace(s " isSubType ${traceInfo(tp1, tp2)} $approx" , subtyping) {
179+ protected def recur (tp1 : Type , tp2 : Type ): Boolean =
180+ // trace.force(s"isSubType ${traceInfo(tp1, tp2)} $approx", subtyping)
181+ {
180182
181183 def monitoredIsSubType = {
182184 if (pendingSubTypes == null ) {
@@ -2143,40 +2145,31 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
21432145 import config .Printers .debug
21442146 import typer .Inferencing ._
21452147
2146- def incompatibleClasses : Boolean = {
2148+ def compatibleClasses : Boolean = {
21472149 import Flags ._
21482150 val tpClassSym = tp.widenSingleton.classSymbol
21492151 val ptClassSym = pt.widenSingleton.classSymbol
21502152 debug.println(i " tpClassSym= $tpClassSym, fin= ${tpClassSym.is(Final )}" )
21512153 debug.println(i " pt= $pt { ${pt.getClass}}, ptClassSym= $ptClassSym, fin= ${ptClassSym.is(Final )}" )
2152- tpClassSym.exists && ptClassSym.exists && {
2153- if (tpClassSym.is(Final )) ! tpClassSym.derivesFrom(ptClassSym)
2154- else if (ptClassSym.is(Final )) ! ptClassSym.derivesFrom(tpClassSym)
2154+ ! tpClassSym.exists || ! ptClassSym.exists || {
2155+ if (tpClassSym.is(Final )) tpClassSym.derivesFrom(ptClassSym)
2156+ else if (ptClassSym.is(Final )) ptClassSym.derivesFrom(tpClassSym)
21552157 else if (! tpClassSym.is(Flags .Trait ) && ! ptClassSym.is(Flags .Trait ))
2156- ! ( tpClassSym.derivesFrom(ptClassSym) || ptClassSym.derivesFrom(tpClassSym) )
2157- else false
2158+ tpClassSym.derivesFrom(ptClassSym) || ptClassSym.derivesFrom(tpClassSym)
2159+ else true
21582160 }
21592161 }
21602162
21612163 def loop (tp : Type ): Boolean =
21622164// trace.force(i"loop($tp) // ${tp.toString}")
21632165 {
2164- if (constrainPatternType(pt, tp)) true
2165- else if (incompatibleClasses) {
2166- // println("incompatible classes")
2167- false
2168- }
2169- else tp match {
2170- case _ : ConstantType =>
2171- // constants cannot possibly intersect with types that aren't their supertypes
2172- false
2173- case tp : SingletonType => loop(tp.underlying)
2174- case tp : TypeRef if tp.symbol.isClass => loop(tp.firstParent)
2166+ val res : Type = tp match {
2167+ case tp : TypeRef if tp.symbol.isClass => tp.firstParent
21752168 case tp @ AppliedType (tycon : TypeRef , _) if tycon.symbol.isClass =>
21762169 val ptClassSym = pt.classSymbol
21772170 def firstParentSharedWithPt (tp : Type , tpClassSym : ClassSymbol ): Symbol =
2178- // trace.force(i"f($tp)")
2179- {
2171+ // trace.force(i"f($tp)")
2172+ {
21802173 var parents = tpClassSym.info.parents
21812174// println(i"parents of $tpClassSym = $parents%, %")
21822175 parents match {
@@ -2195,29 +2188,89 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
21952188 }
21962189 val sym = firstParentSharedWithPt(tycon, tycon.symbol.asClass)
21972190// println(i"sym=$sym ; tyconsym=${tycon.symbol}")
2198- if (! sym.exists) true
2199- else ! (sym == tycon.symbol) && loop(tp.baseType(sym))
2191+ if (! sym.exists) return true
2192+ // else !(sym == tycon.symbol) &&
2193+ tp.baseType(sym)
22002194 case tp : TypeProxy =>
2201- loop( tp.superType)
2202- case _ => false
2195+ tp.superType
2196+ case _ => return true
22032197 }
2198+ constrainPatternType(pt, res) || loop(res)
22042199 }
22052200
2206- pt match {
2207- case AndType (pt1, pt2) =>
2208- notIntersection(tp, pt1) && notIntersection(tp, pt2)
2209- case OrType (pt1, pt2) =>
2210- either(notIntersection(tp, pt1), notIntersection(tp, pt2))
2211- case _ =>
2212- tp match {
2213- case OrType (tp1, tp2) =>
2214- either(notIntersection(tp1, pt), notIntersection(tp2, pt))
2215- case AndType (tp1, tp2) =>
2216- notIntersection(tp1, pt) && notIntersection(tp2, pt)
2217- case _ =>
2218- loop(tp)
2219- }
2220- }
2201+ tp.dealias match {
2202+ case OrType (tp1, tp2) =>
2203+ either(notIntersection(tp1, pt), notIntersection(tp2, pt))
2204+ case AndType (tp1, tp2) =>
2205+ notIntersection(tp1, pt) && notIntersection(tp2, pt)
2206+ case tp : RefinedOrRecType =>
2207+ def keepInvariantRefinements (tp : Type ): Type = tp match {
2208+ case tp : RefinedType =>
2209+ if (tp.refinedName.isTermName) keepInvariantRefinements(tp.parent)
2210+ else {
2211+ // def resolve(tp: Type): Type = tp match {
2212+ // case TypeAlias(tp) => resolve(tp.dealias)
2213+ // case tp => tp
2214+ // }
2215+ // val tpInfo = tp.refinedInfo
2216+ // val tpInfoDealiased = resolve(tpInfo)
2217+ // val ptInfo = pt.member(tp.refinedName).info
2218+ // val ptInfoDealiased = resolve(ptInfo)
2219+ // println(
2220+ // i"""tpInfo = ${tpInfo}
2221+ // |tpInfoDealiased = ${tpInfoDealiased}
2222+ // |ptInfo = ${ptInfo}
2223+ // |ptInfoDealiased = ${ptInfoDealiased}""".stripMargin
2224+ // )
2225+ // println(i"visiting refinement: ${tp.refinedName} : ${tp.refinedInfo}")
2226+ tp.refinedInfo match {
2227+ case TypeAlias (tp1) =>
2228+ val pt1 = pt.member(tp.refinedName).info
2229+ if (pt1.exists && pt1.bounds.contains(tp1) || ! pt1.exists)
2230+ keepInvariantRefinements(tp.parent)
2231+ else
2232+ NoType
2233+ case tpb : TypeBounds =>
2234+ pt.member(tp.refinedName).info match {
2235+ case TypeAlias (pt1) =>
2236+ if (tpb.contains(pt1))
2237+ keepInvariantRefinements(tp.parent)
2238+ else
2239+ NoType
2240+ case _ =>
2241+ keepInvariantRefinements(tp.parent)
2242+ }
2243+ }
2244+ }
2245+ case tp : RecType =>
2246+ keepInvariantRefinements(tp.parent)
2247+ case _ =>
2248+ tp
2249+ }
2250+ val tp1 = keepInvariantRefinements(tp)
2251+ if (! tp1.exists) {
2252+ // println(i"noType for $tp")
2253+ false
2254+ } else
2255+ notIntersection(tp1, pt)
2256+ case tp =>
2257+ pt.dealias match {
2258+ case AndType (pt1, pt2) =>
2259+ notIntersection(tp, pt1) && notIntersection(tp, pt2)
2260+ case OrType (pt1, pt2) =>
2261+ either(notIntersection(tp, pt1), notIntersection(tp, pt2))
2262+ case pt : RefinedOrRecType =>
2263+ // note: at this point, we have already extracted the information we wanted from the refinement
2264+ // and it would only interfere in the following subtype check in constrainPatternType
2265+ def stripRefinement (tp : Type ): Type = tp match {
2266+ case tp : RefinedOrRecType => stripRefinement(tp.parent)
2267+ case tp => tp
2268+ }
2269+ notIntersection(tp, stripRefinement(pt))
2270+ case pt =>
2271+ constrainPatternType(pt, tp) || compatibleClasses && loop(tp)
2272+ }
2273+ }
22212274 }
22222275}
22232276
0 commit comments