@@ -48,15 +48,12 @@ object Implicits {
48
48
/** A common base class of contextual implicits and of-type implicits which
49
49
* represents a set of implicit references.
50
50
*/
51
- abstract class ImplicitRefs (initctx : Context ) {
52
- implicit val ctx : Context =
53
- if (initctx == NoContext ) initctx else initctx retractMode Mode .ImplicitsEnabled
54
-
51
+ abstract class ImplicitRefs extends Showable {
55
52
/** The nesting level of this context. Non-zero only in ContextialImplicits */
56
53
def level : Int = 0
57
54
58
55
/** The implicit references */
59
- def refs : List [TermRef ]
56
+ def refs ( implicit ctx : Context ) : List [TermRef ]
60
57
61
58
/** Return those references in `refs` that are compatible with type `pt`. */
62
59
protected def filterMatching (pt : Type )(implicit ctx : Context ): List [Candidate ] = track(" filterMatching" ) {
@@ -133,70 +130,80 @@ object Implicits {
133
130
134
131
if (refs.isEmpty) Nil
135
132
else {
136
- val nestedCtx = ctx.fresh.addMode(Mode .TypevarsMissContext )
133
+ val nestedCtx = ctx.fresh
134
+ .retractMode(Mode .ImplicitsEnabled )
135
+ .addMode(Mode .TypevarsMissContext )
137
136
refs
138
137
.filter(ref => nestedCtx.typerState.test(refMatches(ref)(nestedCtx)))
139
138
.map(Candidate (_, level))
140
139
}
141
140
}
141
+
142
+ def toText (printer : Printer ): Text = printer.toText(this )
142
143
}
143
144
144
145
/** The implicit references coming from the implicit scope of a type.
145
146
* @param tp the type determining the implicit scope
146
147
* @param companionRefs the companion objects in the implicit scope.
147
148
*/
148
- class OfTypeImplicits (tp : Type , val companionRefs : TermRefSet )(initctx : Context ) extends ImplicitRefs (initctx) {
149
- assert(initctx.typer != null )
150
- lazy val refs : List [TermRef ] = {
151
- val buf = new mutable.ListBuffer [TermRef ]
152
- for (companion <- companionRefs) buf ++= companion.implicitMembers
153
- buf.toList
149
+ class OfTypeImplicits (val tp : Type , val companionRefs : TermRefSet ) extends ImplicitRefs {
150
+ private [this ] var myRefs : List [TermRef ] = _
151
+ def refs (implicit ctx : Context ): List [TermRef ] = {
152
+ if (myRefs == null ) {
153
+ val buf = new mutable.ListBuffer [TermRef ]
154
+ for (companion <- companionRefs) buf ++= companion.implicitMembers
155
+ myRefs = buf.toList
156
+ }
157
+ myRefs
154
158
}
155
159
160
+ private [this ] var myEligible : List [Candidate ] = _
156
161
/** The candidates that are eligible for expected type `tp` */
157
- lazy val eligible : List [Candidate ] =
158
- /* >|>*/ track(" eligible in tpe" ) /* <|<*/ {
159
- /* >|>*/ ctx.traceIndented(i " eligible( $tp), companions = ${companionRefs.toList}%, % " , implicitsDetailed, show = true ) /* <|<*/ {
160
- if (refs.nonEmpty && monitored) record(s " check eligible refs in tpe " , refs.length)
161
- filterMatching(tp)
162
+ def eligible (implicit ctx : Context ): List [Candidate ] = {
163
+ if (myEligible == null ) {
164
+ /* >|>*/ track(" eligible in tpe" ) /* <|<*/ {
165
+ /* >|>*/ ctx.traceIndented(i " eligible( $tp), companions = ${companionRefs.toList}%, % " , implicitsDetailed, show = true ) /* <|<*/ {
166
+ if (refs.nonEmpty && monitored) record(s " check eligible refs in tpe " , refs.length)
167
+ myEligible = filterMatching(tp)
168
+ }
162
169
}
163
170
}
164
-
165
- override def toString =
166
- i " OfTypeImplicits( $tp), companions = ${companionRefs.toList}%, %; refs = $refs%, %. "
171
+ myEligible
172
+ }
167
173
}
168
174
169
175
/** The implicit references coming from the context.
170
- * @param refs the implicit references made visible by the current context.
176
+ * @param myRefs the implicit references made visible by the current context.
171
177
* Note: The name of the reference might be different from the name of its symbol.
172
178
* In the case of a renaming import a => b, the name of the reference is the renamed
173
179
* name, b, whereas the name of the symbol is the original name, a.
174
- * @param outerCtx the next outer context that makes visible further implicits
175
180
*/
176
- class ContextualImplicits (val refs : List [TermRef ], val outerImplicits : ContextualImplicits )( initctx : Context ) extends ImplicitRefs (initctx) {
181
+ class ContextualImplicits (myRefs : List [TermRef ], val outerImplicits : ContextualImplicits , private val ictx : Context ) extends ImplicitRefs {
177
182
private val eligibleCache = new mutable.AnyRefMap [Type , List [Candidate ]]
178
183
184
+ override def refs (implicit ctx : Context ) = myRefs
185
+
179
186
/** The level increases if current context has a different owner or scope than
180
187
* the context of the next-outer ImplicitRefs. This is however disabled under
181
188
* Scala2 mode, since we do not want to change the implicit disambiguation then.
182
189
*/
183
190
override val level : Int =
184
191
if (outerImplicits == null ) 1
185
- else if (ctx .scala2Mode ||
186
- (ctx .owner eq outerImplicits.ctx .owner) &&
187
- (ctx .scope eq outerImplicits.ctx .scope)) outerImplicits.level
192
+ else if (ictx .scala2Mode ||
193
+ (ictx .owner eq outerImplicits.ictx .owner) &&
194
+ (ictx .scope eq outerImplicits.ictx .scope)) outerImplicits.level
188
195
else outerImplicits.level + 1
189
196
190
197
/** Is this the outermost implicits? This is the case if it either the implicits
191
198
* of NoContext, or the last one before it.
192
199
*/
193
- private def isOuterMost = {
200
+ def isOuterMost = {
194
201
val finalImplicits = NoContext .implicits
195
202
(this eq finalImplicits) || (outerImplicits eq finalImplicits)
196
203
}
197
204
198
205
/** The implicit references that are eligible for type `tp`. */
199
- def eligible (tp : Type ): List [Candidate ] = /* >|>*/ track(s " eligible in ctx " ) /* <|<*/ {
206
+ def eligible (tp : Type )( implicit ctx : Context ) : List [Candidate ] = /* >|>*/ track(s " eligible in ctx " ) /* <|<*/ {
200
207
if (tp.hash == NotCached ) computeEligible(tp)
201
208
else eligibleCache get tp match {
202
209
case Some (eligibles) =>
@@ -208,7 +215,7 @@ object Implicits {
208
215
if (monitored) record(s " elided eligible refs " , elided(this ))
209
216
eligibles
210
217
case None =>
211
- if (ctx eq NoContext ) Nil
218
+ if (ictx eq NoContext ) Nil
212
219
else {
213
220
val savedEphemeral = ctx.typerState.ephemeral
214
221
ctx.typerState.ephemeral = false
@@ -222,8 +229,8 @@ object Implicits {
222
229
}
223
230
}
224
231
225
- private def computeEligible (tp : Type ): List [Candidate ] = /* >|>*/ ctx.traceIndented(i " computeEligible $tp in $refs%, % " , implicitsDetailed) /* <|<*/ {
226
- if (monitored) record(s " check eligible refs in ctx " , refs.length)
232
+ private def computeEligible (tp : Type )( implicit ctx : Context ) : List [Candidate ] = /* >|>*/ ctx.traceIndented(i " computeEligible $tp in $refs%, % " , implicitsDetailed) /* <|<*/ {
233
+ if (monitored) record(s " check eligible refs in ictx " , refs.length)
227
234
val ownEligible = filterMatching(tp)
228
235
if (isOuterMost) ownEligible
229
236
else ownEligible ::: {
@@ -232,21 +239,16 @@ object Implicits {
232
239
}
233
240
}
234
241
235
- override def toString = {
236
- val own = i " (implicits: $refs%, %) "
237
- if (isOuterMost) own else own + " \n " + outerImplicits
238
- }
239
-
240
242
/** This context, or a copy, ensuring root import from symbol `root`
241
243
* is not present in outer implicits.
242
244
*/
243
245
def exclude (root : Symbol ): ContextualImplicits =
244
246
if (this == NoContext .implicits) this
245
247
else {
246
248
val outerExcluded = outerImplicits exclude root
247
- if (ctx .importInfo.site.termSymbol == root) outerExcluded
249
+ if (ictx .importInfo.site(ictx) .termSymbol(ictx) == root) outerExcluded
248
250
else if (outerExcluded eq outerImplicits) this
249
- else new ContextualImplicits (refs , outerExcluded)(ctx )
251
+ else new ContextualImplicits (myRefs , outerExcluded, ictx )
250
252
}
251
253
}
252
254
@@ -360,14 +362,8 @@ trait ImplicitRunInfo { self: RunInfo =>
360
362
361
363
private val implicitScopeCache = mutable.AnyRefMap [Type , OfTypeImplicits ]()
362
364
363
- /** The implicit scope of a type `tp`
364
- * @param liftingCtx A context to be used when computing the class symbols of
365
- * a type. Types may contain type variables with their instances
366
- * recorded in the current context. To find out the instance of
367
- * a type variable, we need the current context, the current
368
- * runinfo context does not do.
369
- */
370
- def implicitScope (rootTp : Type , liftingCtx : Context ): OfTypeImplicits = {
365
+ /** The implicit scope of a type `tp` */
366
+ def implicitScope (rootTp : Type )(implicit ctx : Context ): OfTypeImplicits = {
371
367
372
368
val seen : mutable.Set [Type ] = mutable.Set ()
373
369
val incomplete : mutable.Set [Type ] = mutable.Set ()
@@ -379,7 +375,6 @@ trait ImplicitRunInfo { self: RunInfo =>
379
375
* abstract types are eliminated.
380
376
*/
381
377
object liftToClasses extends TypeMap {
382
- override implicit protected val ctx : Context = liftingCtx
383
378
override def stopAtStatic = true
384
379
def apply (tp : Type ) = tp match {
385
380
case tp : TypeRef if tp.symbol.isAbstractOrAliasType =>
@@ -442,7 +437,7 @@ trait ImplicitRunInfo { self: RunInfo =>
442
437
if (companion.exists) addRef(companion.termRef)
443
438
cls.classParents foreach addParentScope
444
439
}
445
- tp.classSymbols(liftingCtx) foreach addClassScope
440
+ tp.classSymbols foreach addClassScope
446
441
case _ =>
447
442
// We exclude lower bounds to conform to SLS 7.2:
448
443
// "The parts of a type T are: [...] if T is an abstract type, the parts of its upper bound"
@@ -468,7 +463,8 @@ trait ImplicitRunInfo { self: RunInfo =>
468
463
iscope(liftedTp, isLifted = true ).companionRefs
469
464
else
470
465
collectCompanions(tp)
471
- val result = new OfTypeImplicits (tp, refs)(ctx)
466
+ val result = new OfTypeImplicits (tp, refs)
467
+
472
468
if (ctx.typerState.ephemeral)
473
469
record(" ephemeral cache miss: implicitScope" )
474
470
else if (canCache &&
@@ -606,7 +602,7 @@ trait Implicits { self: Typer =>
606
602
def lazyImplicitCtx (lazyImplicit : Symbol ): Context = {
607
603
val lctx = ctx.fresh
608
604
for (delayedRef <- ctx.property(DelayedImplicit ))
609
- lctx.setImplicits(new ContextualImplicits (delayedRef :: Nil , ctx.implicits)( ctx))
605
+ lctx.setImplicits(new ContextualImplicits (delayedRef :: Nil , ctx.implicits, ctx))
610
606
lctx.setProperty(DelayedImplicit , lazyImplicit.termRef)
611
607
}
612
608
@@ -909,7 +905,7 @@ trait Implicits { self: Typer =>
909
905
}
910
906
}
911
907
912
- def implicitScope (tp : Type ): OfTypeImplicits = ctx.runInfo.implicitScope(tp, ctx )
908
+ def implicitScope (tp : Type ): OfTypeImplicits = ctx.runInfo.implicitScope(tp)
913
909
}
914
910
915
911
final class ExplainedImplicitSearch (pt : Type , argument : Tree , pos : Position )(implicit ctx : Context )
0 commit comments