@@ -67,17 +67,17 @@ object Checkable {
6767 def isAbstract(P: Type) = !P.dealias.typeSymbol.isClass
6868 def isPatternTypeSymbol(sym: Symbol) = !sym.isClass && sym.is(Case)
6969
70- def replaceP(implicit ctx: Context) = new TypeMap {
70+ def replaceP(tp: Type)( implicit ctx: Context) = new TypeMap {
7171 def apply(tp: Type) = tp match {
7272 case tref: TypeRef
7373 if isPatternTypeSymbol(tref.typeSymbol) => WildcardType
7474 case AnnotatedType(_, annot)
7575 if annot.symbol == defn.UncheckedAnnot => WildcardType
7676 case _ => mapOver(tp)
7777 }
78- }
78+ }.apply(tp)
7979
80- def replaceX(implicit ctx: Context) = new TypeMap {
80+ def replaceX(tp: Type)( implicit ctx: Context) = new TypeMap {
8181 def apply(tp: Type) = tp match {
8282 case tref: TypeRef
8383 if isPatternTypeSymbol(tref.typeSymbol) =>
@@ -86,21 +86,36 @@ object Checkable {
8686 else OrType(defn.AnyType, defn.NothingType)
8787 case _ => mapOver(tp)
8888 }
89- }
89+ }.apply(tp)
90+
91+ /** Approximate type parameters depending on variance */
92+ def stripTypeParam(tp: Type)(implicit ctx: Context) = new ApproximatingTypeMap {
93+ def apply(tp: Type): Type = tp match {
94+ case tp: TypeRef if tp.underlying.isInstanceOf[TypeBounds] =>
95+ val lo = apply(tp.info.loBound)
96+ val hi = apply(tp.info.hiBound)
97+ range(lo, hi)
98+ case _ =>
99+ mapOver(tp)
100+ }
101+ }.apply(tp)
90102
91103 def isClassDetermined(X: Type, P: AppliedType)(implicit ctx: Context) = {
92104 val AppliedType(tycon, _) = P
93105 val typeLambda = tycon.ensureLambdaSub.asInstanceOf[TypeLambda]
94106 val tvars = constrained(typeLambda, untpd.EmptyTree, alwaysAddTypeVars = true)._2.map(_.tpe)
95107 val P1 = tycon.appliedTo(tvars)
96108
97- debug.println("P : " + P.show)
98- debug.println("P1 : " + P1.show)
99- debug.println("X : " + X.show)
109+ debug.println("P : " + P)
110+ debug.println("P1 : " + P1)
111+ debug.println("X : " + X)
112+
113+ P1 <:< X // constraint P1
100114
101- P1 <:< X // may fail, ignore
115+ // use fromScala2x to avoid generating pattern bound symbols
116+ maximizeType(P1, pos, fromScala2x = true)
102117
103- val res = isFullyDefined(P1, ForceDegree.noBottom) && P1 <:< P
118+ val res = P1 <:< P
104119 debug.println("P1 : " + P1)
105120 debug.println("P1 <:< P = " + res)
106121
@@ -116,15 +131,18 @@ object Checkable {
116131 case defn.ArrayOf(tpE) => recur(tpE, tpT)
117132 case _ => recur(defn.AnyType, tpT)
118133 }
119- case tpe: AppliedType => isClassDetermined(X, tpe)(ctx.fresh.setNewTyperState())
134+ case tpe: AppliedType =>
135+ // first try withou striping type parameters for performance
136+ isClassDetermined(X, tpe)(ctx.fresh.setNewTyperState()) ||
137+ isClassDetermined(stripTypeParam(X), tpe)(ctx.fresh.setNewTyperState())
120138 case AndType(tp1, tp2) => recur(X, tp1) && recur(X, tp2)
121139 case OrType(tp1, tp2) => recur(X, tp1) && recur(X, tp2)
122140 case AnnotatedType(t, _) => recur(X, t)
123141 case _: RefinedType => false
124142 case _ => true
125143 })
126144
127- val res = recur(replaceX.apply (X.widen), replaceP.apply (P))
145+ val res = recur(replaceX(X.widen), replaceP(P))
128146
129147 debug.println(i"checking ${X.show} isInstanceOf ${P} = $res")
130148
0 commit comments