diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index c57929e4d363..65bd5ca27d7d 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -159,7 +159,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter */ class Worker1(needsOutFolder: Boolean) { - val caseInsensitively = scala.collection.mutable.Map.empty[String, Symbol] + val caseInsensitively = scala.collection.mutable.HashMap.empty[String, Symbol] def run(): Unit = { while (true) { @@ -190,19 +190,25 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter val claszSymbol = cd.symbol // GenASM checks this before classfiles are emitted, https://github.com/scala/scala/commit/e4d1d930693ac75d8eb64c2c3c69f2fc22bec739 - val lowercaseJavaClassName = claszSymbol.name.toString.toLowerCase - caseInsensitively.get(lowercaseJavaClassName) match { - case None => - caseInsensitively.put(lowercaseJavaClassName, claszSymbol) - case Some(dupClassSym) => - // Order is not deterministic so we enforce lexicographic order between the duplicates for error-reporting - if (claszSymbol.name.toString < dupClassSym.name.toString) - ctx.warning(s"Class ${claszSymbol.name} differs only in case from ${dupClassSym.name}. " + - "Such classes will overwrite one another on case-insensitive filesystems.", claszSymbol.pos) - else - ctx.warning(s"Class ${dupClassSym.name} differs only in case from ${claszSymbol.name}. " + - "Such classes will overwrite one another on case-insensitive filesystems.", dupClassSym.pos) + def checkName(claszSymbol: Symbol): Unit = { + val lowercaseJavaClassName = claszSymbol.effectiveName.toString.toLowerCase + caseInsensitively.get(lowercaseJavaClassName) match { + case None => + caseInsensitively.put(lowercaseJavaClassName, claszSymbol) + case Some(dupClassSym) => + if (claszSymbol.effectiveName.toString != dupClassSym.effectiveName.toString) { + // Order is not deterministic so we enforce lexicographic order between the duplicates for error-reporting + val (cl1, cl2) = + if (claszSymbol.effectiveName.toString < dupClassSym.effectiveName.toString) (claszSymbol, dupClassSym) + else (dupClassSym, claszSymbol) + ctx.warning(s"Class ${cl1.effectiveName} differs only in case from ${cl2.effectiveName}. " + + "Such classes will overwrite one another on case-insensitive filesystems.", cl1.pos) + } + } } + checkName(claszSymbol) + if (int.symHelper(claszSymbol).isModuleClass) + checkName(claszSymbol.companionModule) // -------------- mirror class, if needed -------------- val mirrorC = diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 1c5efcd57de7..c85678626d95 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -58,6 +58,7 @@ class CompilationTests extends ParallelTesting { compileFile("tests/pos-special/i3323.scala", defaultOptions.and("-Xfatal-warnings")) + compileFile("tests/pos-special/i3323b.scala", defaultOptions.and("-Xfatal-warnings")) + compileFile("tests/pos-special/i3589-b.scala", defaultOptions.and("-Xfatal-warnings")) + + compileFile("tests/pos-special/i4166.scala", defaultOptions.and("-Xfatal-warnings")) + compileFile("tests/pos-special/completeFromSource/Test.scala", defaultOptions.and("-sourcepath", "tests/pos-special")) + compileFile("tests/pos-special/completeFromSource/Test2.scala", defaultOptions.and("-sourcepath", "tests/pos-special")) + compileFile("tests/pos-special/completeFromSource/Test3.scala", defaultOptions.and("-sourcepath", "tests/pos-special", "-scansource")) + diff --git a/tests/neg-custom-args/fatal-warnings/i2673b.scala b/tests/neg-custom-args/fatal-warnings/i2673b.scala new file mode 100644 index 000000000000..e3c29d6bc8d0 --- /dev/null +++ b/tests/neg-custom-args/fatal-warnings/i2673b.scala @@ -0,0 +1,4 @@ +package Foos + +class Bar // error +object bar diff --git a/tests/neg-custom-args/fatal-warnings/i2673c.scala b/tests/neg-custom-args/fatal-warnings/i2673c.scala new file mode 100644 index 000000000000..3e9cff320ea2 --- /dev/null +++ b/tests/neg-custom-args/fatal-warnings/i2673c.scala @@ -0,0 +1,6 @@ +package Foos + +object Outer { + class X // error + object x +} diff --git a/tests/pos-special/i4166.scala b/tests/pos-special/i4166.scala new file mode 100644 index 000000000000..44684bc68855 --- /dev/null +++ b/tests/pos-special/i4166.scala @@ -0,0 +1,7 @@ +package foo { + class Hello +} + +package bar { + class Hello +} diff --git a/tests/pos/test4a.scala b/tests/pos/test4a.scala index ada0ba4e5f49..3efa059b73c2 100644 --- a/tests/pos/test4a.scala +++ b/tests/pos/test4a.scala @@ -7,10 +7,10 @@ class O[X]() { val j:I[X] = null; } -object o extends O[C]() { +object p extends O[C]() { def c: C = c; def main = { - o.j.foo(c); + p.j.foo(c); } } diff --git a/tests/pos/test4refine.scala b/tests/pos/test4refine.scala index abf078193568..5e76d10be3a9 100644 --- a/tests/pos/test4refine.scala +++ b/tests/pos/test4refine.scala @@ -10,7 +10,7 @@ object test { import test._; -trait S extends o.I { +trait S extends p.I { type Y = D; def bar: E = foo(c,d); } @@ -25,15 +25,15 @@ abstract class O() { val j:I { type Y = X } = null; } -object o extends O() { +object p extends O() { type X = C; def main = { val s: S = null; import s._; foo(c,d); - o.i.foo(c,e); - o.j.foo(c,c); + p.i.foo(c,e); + p.j.foo(c,c); bar } } @@ -42,8 +42,8 @@ class Main() { val s: S = null; import s._; foo(c,d); - o.i.foo(c,e); - o.j.foo(c,c); + p.i.foo(c,e); + p.j.foo(c,c); bar; }