Skip to content

Commit 482c65b

Browse files
committed
Improve name conflict warning for case-insensitive filesystems
1 parent 25e8c75 commit 482c65b

File tree

9 files changed

+27
-32
lines changed

9 files changed

+27
-32
lines changed

compiler/src/dotty/tools/backend/jvm/GenBCode.scala

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,23 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
163163
*/
164164
class Worker1(needsOutFolder: Boolean) {
165165

166-
val caseInsensitively = scala.collection.mutable.HashMap.empty[String, Symbol]
166+
private val lowerCaseNames = mutable.HashMap.empty[String, Symbol]
167+
private def checkForCaseConflict(javaClassName: String, classSymbol: Symbol) = {
168+
val lowerCaseName = javaClassName.toLowerCase
169+
lowerCaseNames.get(lowerCaseName) match {
170+
case None =>
171+
lowerCaseNames.put(lowerCaseName, classSymbol)
172+
case Some(dupClassSym) =>
173+
// Order is not deterministic so we enforce lexicographic order between the duplicates for error-reporting
174+
val (cl1, cl2) =
175+
if (classSymbol.effectiveName.toString < dupClassSym.effectiveName.toString) (classSymbol, dupClassSym)
176+
else (dupClassSym, classSymbol)
177+
ctx.atPhase(ctx.typerPhase) { implicit ctx =>
178+
ctx.warning(s"${cl1.show} differs only in case from ${cl2.showLocated}. " +
179+
"Such classes will overwrite one another on case-insensitive filesystems.", cl1.pos)
180+
}
181+
}
182+
}
167183

168184
def run(): Unit = {
169185
while (true) {
@@ -193,30 +209,6 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
193209
val Item1(arrivalPos, cd, cunit) = item
194210
val claszSymbol = cd.symbol
195211

196-
// GenASM checks this before classfiles are emitted, https://github.com/scala/scala/commit/e4d1d930693ac75d8eb64c2c3c69f2fc22bec739
197-
def checkName(claszSymbol: Symbol): Unit = {
198-
val lowercaseJavaClassName = claszSymbol.effectiveName.toString.toLowerCase
199-
caseInsensitively.get(lowercaseJavaClassName) match {
200-
case None =>
201-
caseInsensitively.put(lowercaseJavaClassName, claszSymbol)
202-
case Some(dupClassSym) =>
203-
if (claszSymbol.effectiveName.toString != dupClassSym.effectiveName.toString) {
204-
// Order is not deterministic so we enforce lexicographic order between the duplicates for error-reporting
205-
val (cl1, cl2) =
206-
if (claszSymbol.effectiveName.toString < dupClassSym.effectiveName.toString) (claszSymbol, dupClassSym)
207-
else (dupClassSym, claszSymbol)
208-
ctx.warning(s"Class ${cl1.effectiveName} differs only in case from ${cl2.effectiveName}. " +
209-
"Such classes will overwrite one another on case-insensitive filesystems.", cl1.pos)
210-
}
211-
}
212-
}
213-
checkName(claszSymbol)
214-
if (int.symHelper(claszSymbol).isModuleClass) {
215-
val companionModule = claszSymbol.companionModule
216-
if (int.symHelper(companionModule.owner).isPackageClass)
217-
checkName(companionModule)
218-
}
219-
220212
// -------------- mirror class, if needed --------------
221213
val mirrorC =
222214
if (int.symHelper(claszSymbol).isTopLevelModuleClass) {
@@ -263,6 +255,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
263255
val classFiles = classNodes.map(cls =>
264256
if (outF != null && cls != null) {
265257
try {
258+
checkForCaseConflict(cls.name, claszSymbol)
266259
getFileForClassfile(outF, cls.name, ".class")
267260
} catch {
268261
case e: FileConflictException =>
@@ -272,7 +265,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
272265
} else null
273266
)
274267

275-
// ----------- sbt's callbacks
268+
// ----------- compiler and sbt's callbacks
276269

277270
val (fullClassName, isLocal) = ctx.atPhase(ctx.sbtExtractDependenciesPhase) { implicit ctx =>
278271
(ExtractDependencies.classNameAsString(claszSymbol), claszSymbol.isLocal)

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,10 @@ class CompilationTests extends ParallelTesting {
5555
compileFile("tests/pos-scala2/rewrites.scala", scala2Mode.and("-rewrite")).copyToTarget() +
5656
compileFile("tests/pos-special/utf8encoded.scala", explicitUTF8) +
5757
compileFile("tests/pos-special/utf16encoded.scala", explicitUTF16) +
58-
compileFile("tests/pos-special/i3323.scala", defaultOptions.and("-Xfatal-warnings")) +
59-
compileFile("tests/pos-special/i3323b.scala", defaultOptions.and("-Xfatal-warnings")) +
60-
compileFile("tests/pos-special/i3589-b.scala", defaultOptions.and("-Xfatal-warnings")) +
61-
compileFile("tests/pos-special/i4166.scala", defaultOptions.and("-Xfatal-warnings")) +
62-
compileFile("tests/pos-special/i4185.scala", defaultOptions.and("-Xfatal-warnings")) +
6358
compileFile("tests/pos-special/completeFromSource/Test.scala", defaultOptions.and("-sourcepath", "tests/pos-special")) +
6459
compileFile("tests/pos-special/completeFromSource/Test2.scala", defaultOptions.and("-sourcepath", "tests/pos-special")) +
6560
compileFile("tests/pos-special/completeFromSource/Test3.scala", defaultOptions.and("-sourcepath", "tests/pos-special", "-scansource")) +
61+
compileFilesInDir("tests/pos-special/fatal-warnings", defaultOptions.and("-Xfatal-warnings")) +
6662
compileList(
6763
"compileMixed",
6864
List(
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package Foos
22

33
object Outer {
4-
class X // error
4+
case class X() // error
55
object x
66
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package Foos
2+
3+
object Outer {
4+
class X
5+
object x
6+
}

0 commit comments

Comments
 (0)