@@ -176,7 +176,9 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
176
176
* code would have two extra parameters for each of the many calls that go from
177
177
* one sub-part of isSubType to another.
178
178
*/
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
+ {
180
182
181
183
def monitoredIsSubType = {
182
184
if (pendingSubTypes == null ) {
@@ -2143,40 +2145,31 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
2143
2145
import config .Printers .debug
2144
2146
import typer .Inferencing ._
2145
2147
2146
- def incompatibleClasses : Boolean = {
2148
+ def compatibleClasses : Boolean = {
2147
2149
import Flags ._
2148
2150
val tpClassSym = tp.widenSingleton.classSymbol
2149
2151
val ptClassSym = pt.widenSingleton.classSymbol
2150
2152
debug.println(i " tpClassSym= $tpClassSym, fin= ${tpClassSym.is(Final )}" )
2151
2153
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)
2155
2157
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
2158
2160
}
2159
2161
}
2160
2162
2161
2163
def loop (tp : Type ): Boolean =
2162
2164
// trace.force(i"loop($tp) // ${tp.toString}")
2163
2165
{
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
2175
2168
case tp @ AppliedType (tycon : TypeRef , _) if tycon.symbol.isClass =>
2176
2169
val ptClassSym = pt.classSymbol
2177
2170
def firstParentSharedWithPt (tp : Type , tpClassSym : ClassSymbol ): Symbol =
2178
- // trace.force(i"f($tp)")
2179
- {
2171
+ // trace.force(i"f($tp)")
2172
+ {
2180
2173
var parents = tpClassSym.info.parents
2181
2174
// println(i"parents of $tpClassSym = $parents%, %")
2182
2175
parents match {
@@ -2195,29 +2188,89 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
2195
2188
}
2196
2189
val sym = firstParentSharedWithPt(tycon, tycon.symbol.asClass)
2197
2190
// 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)
2200
2194
case tp : TypeProxy =>
2201
- loop( tp.superType)
2202
- case _ => false
2195
+ tp.superType
2196
+ case _ => return true
2203
2197
}
2198
+ constrainPatternType(pt, res) || loop(res)
2204
2199
}
2205
2200
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
+ }
2221
2274
}
2222
2275
}
2223
2276
0 commit comments