Skip to content

Commit 7c73e54

Browse files
committed
Fix #7650: Drop stale toplevel definitions
1 parent d217690 commit 7c73e54

File tree

4 files changed

+27
-4
lines changed

4 files changed

+27
-4
lines changed

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ object Denotations {
116116
*/
117117
def filterWithFlags(required: FlagSet, excluded: FlagSet)(implicit ctx: Context): PreDenotation
118118

119+
/** Map `f` over all single denotations and aggregate the results with `g`. */
120+
def aggregate[T](f: SingleDenotation => T, g: (T, T) => T): T
121+
119122
private var cachedPrefix: Type = _
120123
private var cachedAsSeenFrom: AsSeenFromResult = _
121124
private var validAsSeenFrom: Period = Nowhere
@@ -1132,6 +1135,7 @@ object Denotations {
11321135
if (denots.exists && denots.matches(this)) NoDenotation else this
11331136
def filterWithFlags(required: FlagSet, excluded: FlagSet)(implicit ctx: Context): SingleDenotation =
11341137
if (required.isEmpty && excluded.isEmpty || compatibleWith(required, excluded)) this else NoDenotation
1138+
def aggregate[T](f: SingleDenotation => T, g: (T, T) => T): T = f(this)
11351139

11361140
type AsSeenFromResult = SingleDenotation
11371141
protected def computeAsSeenFrom(pre: Type)(implicit ctx: Context): SingleDenotation = {
@@ -1286,6 +1290,8 @@ object Denotations {
12861290
derivedUnion(denot1 filterDisjoint denot, denot2 filterDisjoint denot)
12871291
def filterWithFlags(required: FlagSet, excluded: FlagSet)(implicit ctx: Context): PreDenotation =
12881292
derivedUnion(denot1.filterWithFlags(required, excluded), denot2.filterWithFlags(required, excluded))
1293+
def aggregate[T](f: SingleDenotation => T, g: (T, T) => T): T =
1294+
g(denot1.aggregate(f, g), denot2.aggregate(f, g))
12891295
protected def derivedUnion(denot1: PreDenotation, denot2: PreDenotation) =
12901296
if ((denot1 eq this.denot1) && (denot2 eq this.denot2)) this
12911297
else denot1 union denot2

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,19 +2122,34 @@ object SymDenotations {
21222122
case pcls :: pobjs1 =>
21232123
if (pcls.isCompleting) recur(pobjs1, acc)
21242124
else {
2125-
// A package object inherits members from `Any` and `Object` which
2126-
// should not be accessible from the package prefix.
21272125
val pmembers = pcls.computeNPMembersNamed(name).filterWithPredicate { d =>
2126+
// Drop members of `Any` and `Object`, as well as top-level definitions
2127+
// in the empty package that are not defined in the current run.
21282128
val owner = d.symbol.maybeOwner
21292129
(owner ne defn.AnyClass) && (owner ne defn.ObjectClass)
21302130
}
21312131
recur(pobjs1, acc.union(pmembers))
21322132
}
21332133
case nil =>
21342134
val directMembers = super.computeNPMembersNamed(name)
2135-
if (acc.exists) acc.union(directMembers.filterWithPredicate(!_.symbol.isAbsent()))
2136-
else directMembers
2135+
if !acc.exists then directMembers
2136+
else acc.union(directMembers.filterWithPredicate(!_.symbol.isAbsent())) match
2137+
case d: DenotUnion => dropStale(d)
2138+
case d => d
21372139
}
2140+
2141+
def dropStale(d: DenotUnion): PreDenotation =
2142+
val compiledNow = d.filterWithPredicate(d =>
2143+
d.symbol.isDefinedInCurrentRun || d.symbol.associatedFile == null
2144+
// if a symbol does not have an associated file, assume it is defined
2145+
// in the current run anyway. This typically happens for pickling and
2146+
// from-tasty tests that generate a fresh symbol and then re-use it in the next run.
2147+
)
2148+
if compiledNow.exists then compiledNow
2149+
else
2150+
val youngest = d.aggregate(_.symbol.associatedFile.lastModified, _ max _)
2151+
d.filterWithPredicate(_.symbol.associatedFile.lastModified == youngest)
2152+
21382153
if (symbol `eq` defn.ScalaPackageClass) {
21392154
val denots = super.computeNPMembersNamed(name)
21402155
if (denots.exists) denots

tests/pos/i7650/Test_1.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@main def Test() = println("hi")

tests/pos/i7650/Test_2.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
object Test

0 commit comments

Comments
 (0)