Skip to content

Commit 8ac2c66

Browse files
committed
Report an error if toplevel denotations come from multiple files
Report an error if toplevel denotations the same name with come from multiple files that have the same modification date. The error was reported in some runs for toplevel/stale when run locally since the files for A_1.scala and B_2.scala were generated too fast so they ended up with the same modification date. B_2.scala has now been beefed up to give the compiler more work to do, so that the race is avoided.
1 parent 72c0014 commit 8ac2c66

File tree

4 files changed

+57
-7
lines changed

4 files changed

+57
-7
lines changed

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

+17-4
Original file line numberDiff line numberDiff line change
@@ -2147,17 +2147,30 @@ object SymDenotations {
21472147
case d => d
21482148
}
21492149

2150-
def dropStale(d: DenotUnion): PreDenotation =
2151-
val compiledNow = d.filterWithPredicate(d =>
2150+
def dropStale(multi: DenotUnion): PreDenotation =
2151+
val compiledNow = multi.filterWithPredicate(d =>
21522152
d.symbol.isDefinedInCurrentRun || d.symbol.associatedFile == null
21532153
// if a symbol does not have an associated file, assume it is defined
21542154
// in the current run anyway. This is true for packages, and also can happen for pickling and
21552155
// from-tasty tests that generate a fresh symbol and then re-use it in the next run.
21562156
)
21572157
if compiledNow.exists then compiledNow
21582158
else
2159-
val youngest = d.aggregate(_.symbol.associatedFile.lastModified, _ max _)
2160-
d.filterWithPredicate(_.symbol.associatedFile.lastModified == youngest)
2159+
val assocFiles = multi.aggregate(d => Set(d.symbol.associatedFile), _ union _)
2160+
if assocFiles.size == 1 then
2161+
multi // they are all overloaded variants from the same file
2162+
else
2163+
// pick the variant(s) from the youngest class file
2164+
val lastModDate = assocFiles.map(_.lastModified).max
2165+
val youngest = assocFiles.filter(_.lastModified == lastModDate)
2166+
if youngest.size > 1 then
2167+
throw TypeError(em"""Toplevel definition $name is defined in
2168+
| ${youngest.head}
2169+
|and also in
2170+
| ${youngest.tail.head}
2171+
|One of these files should be removed from the classpath.""")
2172+
multi.filterWithPredicate(_.symbol.associatedFile == youngest.head)
2173+
end dropStale
21612174

21622175
if (symbol `eq` defn.ScalaPackageClass) {
21632176
val denots = super.computeNPMembersNamed(name)

tests/run/toplevel-stale/A_1.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
def foo(x: Int): String = "old"
1+
def foo234(x: Int): String = "old"

tests/run/toplevel-stale/B_2.scala

+38-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,38 @@
1-
def foo(x: Long): String = "new"
1+
def foo234(x: Long): String = "new"
2+
3+
// Giving the compiler something to do so that we won't get
4+
// the same modification date as A_1.scala
5+
import math.Ordering
6+
7+
val y1 = {
8+
val x1 = summon[Ordering[Int]]
9+
val x2 = summon[Ordering[(Int, Int)]]
10+
val x3 = summon[Ordering[(Int, Int, Int)]]
11+
val x4 = summon[Ordering[(Int, Int, Int, Int)]]
12+
val x5 = summon[Ordering[(Int, Int, Int, Int, Int)]]
13+
val x6 = summon[Ordering[(Int, Int, Int, Int, Int, Int)]]
14+
val x7 = summon[Ordering[(Int, Int, Int, Int, Int, Int, Int)]]
15+
val x8 = summon[Ordering[(Int, Int, Int, Int, Int, Int, Int, Int)]]
16+
}
17+
18+
val y2 = {
19+
val x1 = summon[Ordering[Int]]
20+
val x2 = summon[Ordering[(Int, Int)]]
21+
val x3 = summon[Ordering[(Int, Int, Int)]]
22+
val x4 = summon[Ordering[(Int, Int, Int, Int)]]
23+
val x5 = summon[Ordering[(Int, Int, Int, Int, Int)]]
24+
val x6 = summon[Ordering[(Int, Int, Int, Int, Int, Int)]]
25+
val x7 = summon[Ordering[(Int, Int, Int, Int, Int, Int, Int)]]
26+
val x8 = summon[Ordering[(Int, Int, Int, Int, Int, Int, Int, Int)]]
27+
}
28+
29+
val y3 = {
30+
val x1 = summon[Ordering[Int]]
31+
val x2 = summon[Ordering[(Int, Int)]]
32+
val x3 = summon[Ordering[(Int, Int, Int)]]
33+
val x4 = summon[Ordering[(Int, Int, Int, Int)]]
34+
val x5 = summon[Ordering[(Int, Int, Int, Int, Int)]]
35+
val x6 = summon[Ordering[(Int, Int, Int, Int, Int, Int)]]
36+
val x7 = summon[Ordering[(Int, Int, Int, Int, Int, Int, Int)]]
37+
val x8 = summon[Ordering[(Int, Int, Int, Int, Int, Int, Int, Int)]]
38+
}

tests/run/toplevel-stale/Test_3.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
@main def Test() =
2-
assert(foo(1) == "new")
2+
assert(foo234(1) == "new")

0 commit comments

Comments
 (0)