Skip to content

Commit 5e5d2c9

Browse files
committed
Cache only when the context corresponds to prefix
Caching a lookup of c in a.b.c is ok at a.b. A lookup from a.p should not see the cached value.
1 parent 88a741b commit 5e5d2c9

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

+18-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import dotty.tools.dotc.util.chaining.*
2525

2626
import java.util.IdentityHashMap
2727

28+
import scala.collection.immutable.LazyList
2829
import scala.collection.mutable, mutable.{ArrayBuilder, ListBuffer, Stack}
2930

3031
import CheckUnused.*
@@ -63,8 +64,22 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
6364
if depth < 10 && prefix.exists && !prefix.classSymbol.isEffectiveRoot then
6465
resolveUsage(prefix.classSymbol, nme.NO_NAME, NoPrefix)
6566
loopOverPrefixes(prefix.normalizedPrefix, depth + 1)
67+
/*
6668
if tree.srcPos.isZeroExtentSynthetic then
67-
loopOverPrefixes(tree.typeOpt.normalizedPrefix, depth = 0)
69+
println(s"ZES ${tree.show}")
70+
def prefixed(t: Type) =
71+
if t.exists && !t.classSymbol.isEffectiveRoot then
72+
println(s"CS ${t.classSymbol}")
73+
Some(t, t.normalizedPrefix)
74+
else
75+
None
76+
val prefixes = LazyList.unfold(tree.typeOpt)(prefixed).take(10).force
77+
println(s"PREFIXES ${prefixes}")
78+
for (prefix <- prefixes.drop(1))
79+
()
80+
*/
81+
//if tree.srcPos.isZeroExtentSynthetic then
82+
// loopOverPrefixes(tree.typeOpt.normalizedPrefix, depth = 0)
6883
resolveUsage(tree.symbol, tree.name, tree.typeOpt.importPrefix.skipPackageObject)
6984
else if tree.hasType then
7085
resolveUsage(tree.tpe.classSymbol, tree.name, tree.tpe.importPrefix.skipPackageObject)
@@ -330,7 +345,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
330345
def addCached(where: Context, result: Precedence): Unit =
331346
if where.moreProperties ne null then
332347
where.property(resolvedKey) match
333-
case Some(resolved) =>
348+
case Some(resolved) if where.owner.isLocalToBlock || where.owner.info =:= prefix =>
334349
resolved.record(sym, name, prefix, result)
335350
case none =>
336351

@@ -361,7 +376,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
361376
cur.property(resolvedKey) match
362377
case Some(resolved) =>
363378
// conservative, cache must be nested below the result context
364-
if precedence.isNone then
379+
if precedence.isNone && (cur.owner.isLocalToBlock || cur.owner.info =:= prefix) then
365380
cachePoint = cur // no result yet, and future result could be cached here
366381
resolved.hasRecord(sym, name, prefix)
367382
case none => NoPrecedence

tests/warn/i22971.scala

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//> using options -Wunused:imports -Vprint:typer
2+
//> abusing options -Yprint-trees:format
3+
4+
package p:
5+
6+
trait Base
7+
class Class extends Base
8+
9+
abstract class Entity[T: GetType]
10+
11+
class Thing extends Entity[Class]
12+
13+
trait GetType[T]
14+
15+
object GetType {
16+
//implicit object GetTypeClass extends GetType[Class]
17+
//given GetTypeClass: GetType[Class] = new GetType[Class] {}
18+
//val GetTypeClass: GetType[Class] = new GetType[Class] {}
19+
implicit val GetTypeClass: GetType[Class] = new GetType[Class] {}
20+
}
21+
object Main {
22+
def main(args: Array[String]): Unit = {
23+
import GetType.*
24+
//import GetType.given
25+
val e = GetTypeClass
26+
}
27+
//def test: Unit = summon[GetType[Class]]
28+
}
29+
30+
package q:
31+
32+
class C:
33+
def f =
34+
import p.*
35+
GetType.GetTypeClass
36+
def g =
37+
import p.GetType.*
38+
GetTypeClass
39+
/*
40+
def h =
41+
import p.*
42+
summon[GetType[Class]]
43+
44+
class D extends p.Entity[p.Class]
45+
*/

0 commit comments

Comments
 (0)