@@ -67,17 +67,17 @@ object Checkable {
67
67
def isAbstract (P : Type ) = ! P .dealias.typeSymbol.isClass
68
68
def isPatternTypeSymbol (sym : Symbol ) = ! sym.isClass && sym.is(Case )
69
69
70
- def replaceP (implicit ctx : Context ) = new TypeMap {
70
+ def replaceP (tp : Type )( implicit ctx : Context ) = new TypeMap {
71
71
def apply (tp : Type ) = tp match {
72
72
case tref : TypeRef
73
73
if isPatternTypeSymbol(tref.typeSymbol) => WildcardType
74
74
case AnnotatedType (_, annot)
75
75
if annot.symbol == defn.UncheckedAnnot => WildcardType
76
76
case _ => mapOver(tp)
77
77
}
78
- }
78
+ }.apply(tp)
79
79
80
- def replaceX (implicit ctx : Context ) = new TypeMap {
80
+ def replaceX (tp : Type )( implicit ctx : Context ) = new TypeMap {
81
81
def apply (tp : Type ) = tp match {
82
82
case tref : TypeRef
83
83
if isPatternTypeSymbol(tref.typeSymbol) =>
@@ -86,21 +86,36 @@ object Checkable {
86
86
else OrType (defn.AnyType , defn.NothingType )
87
87
case _ => mapOver(tp)
88
88
}
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)
90
102
91
103
def isClassDetermined (X : Type , P : AppliedType )(implicit ctx : Context ) = {
92
104
val AppliedType (tycon, _) = P
93
105
val typeLambda = tycon.ensureLambdaSub.asInstanceOf [TypeLambda ]
94
106
val tvars = constrained(typeLambda, untpd.EmptyTree , alwaysAddTypeVars = true )._2.map(_.tpe)
95
107
val P1 = tycon.appliedTo(tvars)
96
108
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
100
114
101
- P1 <:< X // may fail, ignore
115
+ // use fromScala2x to avoid generating pattern bound symbols
116
+ maximizeType(P1 , pos, fromScala2x = true )
102
117
103
- val res = isFullyDefined( P1 , ForceDegree .noBottom) && P1 <:< P
118
+ val res = P1 <:< P
104
119
debug.println(" P1 : " + P1 )
105
120
debug.println(" P1 <:< P = " + res)
106
121
@@ -116,15 +131,18 @@ object Checkable {
116
131
case defn.ArrayOf (tpE) => recur(tpE, tpT)
117
132
case _ => recur(defn.AnyType , tpT)
118
133
}
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())
120
138
case AndType (tp1, tp2) => recur(X , tp1) && recur(X , tp2)
121
139
case OrType (tp1, tp2) => recur(X , tp1) && recur(X , tp2)
122
140
case AnnotatedType (t, _) => recur(X , t)
123
141
case _ : RefinedType => false
124
142
case _ => true
125
143
})
126
144
127
- val res = recur(replaceX.apply (X .widen), replaceP.apply (P ))
145
+ val res = recur(replaceX(X .widen), replaceP(P ))
128
146
129
147
debug.println(i " checking ${X .show} isInstanceOf ${P } = $res" )
130
148
0 commit comments