@@ -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