@@ -215,15 +215,6 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
215
215
refInfos.register(tree)
216
216
tree
217
217
218
- override def prepareForTemplate (tree : Template )(using Context ): Context =
219
- ctx.fresh.setProperty(resolvedKey, Resolved ())
220
-
221
- override def prepareForPackageDef (tree : PackageDef )(using Context ): Context =
222
- ctx.fresh.setProperty(resolvedKey, Resolved ())
223
-
224
- override def prepareForStats (trees : List [Tree ])(using Context ): Context =
225
- ctx.fresh.setProperty(resolvedKey, Resolved ())
226
-
227
218
override def transformOther (tree : Tree )(using Context ): tree.type =
228
219
tree match
229
220
case imp : Import =>
@@ -289,7 +280,6 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
289
280
case ByNameTypeTree (result) =>
290
281
transformAllDeep(result)
291
282
// case _: InferredTypeTree => // do nothing
292
- // case _: Export => // nothing to do
293
283
// case _ if tree.isType =>
294
284
case _ =>
295
285
tree
@@ -350,15 +340,6 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
350
340
&& ctxsym.thisType.baseClasses.contains(sym.owner)
351
341
&& ctxsym.thisType.member(sym.name).hasAltWith(d => d.containsSym(sym) && ! name.exists(_ != d.name))
352
342
353
- // Attempt to cache a result at the given context. Not all contexts bear a cache, including NoContext.
354
- // If there is already any result for the name and prefix, do nothing.
355
- def addCached (where : Context , result : Precedence ): Unit =
356
- if where.moreProperties ne null then
357
- where.property(resolvedKey) match
358
- case Some (resolved) =>
359
- resolved.record(sym, name, prefix, result)
360
- case none =>
361
-
362
343
// Avoid spurious NoSymbol and also primary ctors which are never warned about.
363
344
// Selections C.this.toString should be already excluded, but backtopped here for eq, etc.
364
345
if ! sym.exists || sym.isPrimaryConstructor || sym.isEffectiveRoot || defn.topClasses(sym.owner) then return
@@ -367,39 +348,20 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
367
348
// If the sym is an enclosing definition (the owner of a context), it does not count toward usages.
368
349
val isLocal = sym.isLocalToBlock
369
350
var candidate : Context = NoContext
370
- var cachePoint : Context = NoContext // last context with Resolved cache
371
351
var importer : ImportSelector | Null = null // non-null for import context
372
352
var precedence = NoPrecedence // of current resolution
353
+ var enclosed = false // true if sym is owner of an enclosing context
373
354
var done = false
374
- var cached = false
375
355
val ctxs = ctx.outersIterator
376
356
while ! done && ctxs.hasNext do
377
357
val cur = ctxs.next()
378
- if cur.owner eq sym then
379
- addCached(cachePoint, Definition )
380
- return // found enclosing definition
381
- else if isLocal then
358
+ if cur.owner.userSymbol == sym && ! sym.is(Package ) then
359
+ enclosed = true // found enclosing definition, don't register the reference
360
+ if isLocal then
382
361
if cur.owner eq sym.owner then
383
362
done = true // for local def, just checking that it is not enclosing
384
363
else
385
- val cachedPrecedence =
386
- cur.property(resolvedKey) match
387
- case Some (resolved) =>
388
- // conservative, cache must be nested below the result context
389
- if precedence.isNone then
390
- cachePoint = cur // no result yet, and future result could be cached here
391
- resolved.hasRecord(sym, name, prefix)
392
- case none => NoPrecedence
393
- cached = ! cachedPrecedence.isNone
394
- if cached then
395
- // if prefer cached precedence, then discard previous result
396
- if precedence.weakerThan(cachedPrecedence) then
397
- candidate = NoContext
398
- importer = null
399
- cachePoint = cur // actual cache context
400
- precedence = cachedPrecedence // actual cached precedence
401
- done = true
402
- else if cur.isImportContext then
364
+ if cur.isImportContext then
403
365
val sel = matchingSelector(cur.importInfo.nn)
404
366
if sel != null then
405
367
if cur.importInfo.nn.isRootImport then
@@ -419,7 +381,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
419
381
candidate = cur
420
382
importer = sel
421
383
else if checkMember(cur.owner) then
422
- if sym.srcPos.sourcePos.source == ctx.source then
384
+ if sym.is( Package ) || sym. srcPos.sourcePos.source == ctx.source then
423
385
precedence = Definition
424
386
candidate = cur
425
387
importer = null // ignore import in same scope; we can't check nesting level
@@ -429,16 +391,10 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
429
391
candidate = cur
430
392
end while
431
393
// record usage and possibly an import
432
- refInfos.refs.addOne(sym)
394
+ if ! enclosed then
395
+ refInfos.refs.addOne(sym)
433
396
if candidate != NoContext && candidate.isImportContext && importer != null then
434
397
refInfos.sels.put(importer, ())
435
- // possibly record that we have performed this look-up
436
- // if no result was found, take it as Definition (local or rooted head of fully qualified path)
437
- val adjusted = if precedence.isNone then Definition else precedence
438
- if ! cached && (cachePoint ne NoContext ) then
439
- addCached(cachePoint, adjusted)
440
- if cachePoint ne ctx then
441
- addCached(ctx, adjusted) // at this ctx, since cachePoint may be far up the outer chain
442
398
end resolveUsage
443
399
end CheckUnused
444
400
@@ -450,15 +406,8 @@ object CheckUnused:
450
406
451
407
val refInfosKey = Property .StickyKey [RefInfos ]
452
408
453
- val resolvedKey = Property .Key [Resolved ]
454
-
455
409
inline def refInfos (using Context ): RefInfos = ctx.property(refInfosKey).get
456
410
457
- inline def resolved (using Context ): Resolved =
458
- ctx.property(resolvedKey) match
459
- case Some (res) => res
460
- case _ => throw new MatchError (" no Resolved for context" )
461
-
462
411
/** Attachment holding the name of an Ident as written by the user. */
463
412
val OriginalName = Property .StickyKey [Name ]
464
413
@@ -487,7 +436,7 @@ object CheckUnused:
487
436
if inliners == 0
488
437
&& languageImport(imp.expr).isEmpty
489
438
&& ! imp.isGeneratedByEnum
490
- && ! ctx.outer. owner.name.isReplWrapperName
439
+ && ! ctx.owner.name.isReplWrapperName
491
440
then
492
441
imps.put(imp, ())
493
442
case tree : Bind =>
@@ -514,24 +463,6 @@ object CheckUnused:
514
463
var inliners = 0 // depth of inline def (not inlined yet)
515
464
end RefInfos
516
465
517
- // Symbols already resolved in the given Context (with name and prefix of lookup).
518
- class Resolved :
519
- import PrecedenceLevels .*
520
- private val seen = mutable.Map .empty[Symbol , List [(Name , Type , Precedence )]].withDefaultValue(Nil )
521
- // if a result has been recorded, return it; otherwise, NoPrecedence.
522
- def hasRecord (symbol : Symbol , name : Name , prefix : Type )(using Context ): Precedence =
523
- seen(symbol).find((n, p, _) => n == name && p =:= prefix) match
524
- case Some ((_, _, r)) => r
525
- case none => NoPrecedence
526
- // "record" the look-up result, if there is not already a result for the name and prefix.
527
- def record (symbol : Symbol , name : Name , prefix : Type , result : Precedence )(using Context ): Unit =
528
- require(NoPrecedence .weakerThan(result))
529
- seen.updateWith(symbol):
530
- case svs @ Some (vs) =>
531
- if vs.exists((n, p, _) => n == name && p =:= prefix) then svs
532
- else Some ((name, prefix, result) :: vs)
533
- case none => Some ((name, prefix, result) :: Nil )
534
-
535
466
// Names are resolved by definitions and imports, which have four precedence levels:
536
467
object PrecedenceLevels :
537
468
opaque type Precedence = Int
0 commit comments