diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index d9059bab77af..6d72cebf54c5 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -513,14 +513,29 @@ class PlainPrinter(_ctx: Context) extends Printer { def toTextPrefixOf(tp: NamedType): Text = controlled { homogenize(tp.prefix) match { case NoPrefix => "" - case tp: SingletonType => toTextRef(tp) ~ "." - case tp => trimPrefix(toTextLocal(tp)) ~ "#" + case prefix: SingletonType => toTextRef(prefix) ~ "." + case prefix => + // Use "." for Java nested classes (e.g., java.util.Map.Entry) + // Use "#" for Scala type projections (e.g., Outer#Inner) + val separator = if (isJavaNestedClass(tp)) "." else "#" + trimPrefix(toTextLocal(prefix)) ~ separator } } protected def isEmptyPrefix(sym: Symbol): Boolean = sym.isEffectiveRoot || sym.isAnonymousClass || sym.name.isReplWrapperName + /** Check if tp represents a Java nested class that should use "." separator. */ + protected def isJavaNestedClass(tp: NamedType)(using Context): Boolean = { + val sym = tp.symbol + sym.exists && + sym.is(JavaDefined) && + sym.isClass && + sym.owner.exists && + sym.owner.is(JavaDefined) && + sym.owner.isClass + } + /** String representation of a definition's type following its name, * if symbol is completed, ": ?" otherwise. */ diff --git a/tests/neg/i24711-java-nested-types.check b/tests/neg/i24711-java-nested-types.check new file mode 100644 index 000000000000..005a0ab71e52 --- /dev/null +++ b/tests/neg/i24711-java-nested-types.check @@ -0,0 +1,21 @@ +-- [E007] Type Mismatch Error: tests/neg/i24711-java-nested-types.scala:2:20 ------------------------------------------- +2 | val test1: Int = (??? : java.util.Map.Entry[String, Int]) // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Found: java.util.Map.Entry[String, Int] + | Required: Int + | + | longer explanation available when compiling with `-explain` +-- [E007] Type Mismatch Error: tests/neg/i24711-java-nested-types.scala:4:38 ------------------------------------------- +4 | val test2: Int = java.util.Map.entry("key", 1) // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Found: java.util.Map.Entry[String, Int] + | Required: Int + | + | longer explanation available when compiling with `-explain` +-- [E007] Type Mismatch Error: tests/neg/i24711-java-nested-types.scala:7:20 ------------------------------------------- +7 | val test4: Int = (??? : Outer#Inner) // error + | ^^^^^^^^^^^^^^^^^ + | Found: Test.this.Outer#Inner + | Required: Int + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/i24711-java-nested-types.scala b/tests/neg/i24711-java-nested-types.scala new file mode 100644 index 000000000000..bb27a15df245 --- /dev/null +++ b/tests/neg/i24711-java-nested-types.scala @@ -0,0 +1,8 @@ +class Test { + val test1: Int = (??? : java.util.Map.Entry[String, Int]) // error + + val test2: Int = java.util.Map.entry("key", 1) // error + + trait Outer { type Inner } + val test4: Int = (??? : Outer#Inner) // error +}