@@ -179,7 +179,9 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
179
179
* code would have two extra parameters for each of the many calls that go from
180
180
* one sub-part of isSubType to another.
181
181
*/
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
+ {
183
185
184
186
def monitoredIsSubType = {
185
187
if (pendingSubTypes == null ) {
@@ -2104,40 +2106,31 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
2104
2106
import config .Printers .debug
2105
2107
import typer .Inferencing ._
2106
2108
2107
- def incompatibleClasses : Boolean = {
2109
+ def compatibleClasses : Boolean = {
2108
2110
import Flags ._
2109
2111
val tpClassSym = tp.widenSingleton.classSymbol
2110
2112
val ptClassSym = pt.widenSingleton.classSymbol
2111
2113
debug.println(i " tpClassSym= $tpClassSym, fin= ${tpClassSym.is(Final )}" )
2112
2114
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)
2116
2118
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
2119
2121
}
2120
2122
}
2121
2123
2122
2124
def loop (tp : Type ): Boolean =
2123
2125
// trace.force(i"loop($tp) // ${tp.toString}")
2124
2126
{
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
2136
2129
case tp @ AppliedType (tycon : TypeRef , _) if tycon.symbol.isClass =>
2137
2130
val ptClassSym = pt.classSymbol
2138
2131
def firstParentSharedWithPt (tp : Type , tpClassSym : ClassSymbol ): Symbol =
2139
- // trace.force(i"f($tp)")
2140
- {
2132
+ // trace.force(i"f($tp)")
2133
+ {
2141
2134
var parents = tpClassSym.info.parents
2142
2135
// println(i"parents of $tpClassSym = $parents%, %")
2143
2136
parents match {
@@ -2156,29 +2149,89 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
2156
2149
}
2157
2150
val sym = firstParentSharedWithPt(tycon, tycon.symbol.asClass)
2158
2151
// 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)
2161
2155
case tp : TypeProxy =>
2162
- loop( tp.superType)
2163
- case _ => false
2156
+ tp.superType
2157
+ case _ => return true
2164
2158
}
2159
+ constrainPatternType(pt, res) || loop(res)
2165
2160
}
2166
2161
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
+ }
2182
2235
}
2183
2236
}
2184
2237
0 commit comments