Disabling full names in error messages

The compile-error messages I get are usually much harder to read due to them using fully qualified names everywhere. Is there a way to disable this? Perhaps a compiler option? I often end up manually removing the paths before even attempting to read them.

An example:

None of the overloaded alternatives of method u in class FiniteSet with types
 [U]
  (that: util.collections.extensional.FiniteSet.NonEmpty[U]):
    util.collections.extensional.FiniteSet.NonEmpty[
      Extended.this.rooted.Constructor | U]
 [U]
  (that: util.collections.extensional.FiniteSet[U]):
    util.collections.extensional.FiniteSet[Extended.this.rooted.Constructor | U]
 [U]
  (that: util.collections.generic.SimpleSet[U]):
    util.collections.generic.SimpleSet[Extended.this.rooted.Constructor | U]
...
1 Like

The Scala 2 ticket from 2014 is now closed for lack of trying.

The problem is that if we don’t do full names, it can easily become ambiguous and potentially misleading. E.g. there are several Seq classes. If you know one but the system refers to another it can be super-confusing. What we could do is have the fully qualified name in where clauses. So the example would become:

None of the overloaded alternatives of method u in class FiniteSet with types
 [U](that: NonEmpty[U]): NonEmpty[rooted.Constructor | U]
 [U](that: FiniteSet[U]): FiniteSet[rooted.Constructor | U]
 [U](that: SimpleSet[U]): SimpleSet[rooted.Constructor | U]

where

  NonEmpty      is a class in object util.collections.extensional.FiniteSet
  FiniteSet     is a class in package util.collections.extensional
  rooted        is a field of the enclosing class Extended
  SimpleSet     is a class in package util.collections.generic
9 Likes

That looks like it would be a great improvement. Even better than having a flag that would usually make the message clearer, but sometimes ambiguous.

I considered using an old ticket that predates superscripting for refining what is shown.

Here is an example that is superscripted even though the message already shows a disambiguating prefix.

➜  snips cat /tmp/huh.scala

object X:
  class C

object Y:
  class C

def f(other: Y.C): Any =
  import X.C
  val c: C = other
  c

@main def test = f(new Y.C)
➜  snips scala-cli compile --server=false -S 3.8.4-RC2 /tmp/huh.scala
-- [E007] Type Mismatch Error: /tmp/huh.scala:10:13 ----------------------------
10 |  val c: C = other
   |             ^^^^^
   |             Found:    (other : Y.C)
   |             Required: X.C²
   |
   |             where:    C  is a class in object Y
   |                       C² is a class in object X
   |
   | longer explanation available when compiling with `-explain`
1 error found
Compilation failed

I speculated that I would just like to reduce common prefixes, so that the message might show mutable.Seq and immutable.Seq instead of superscripting. Perhaps the addendum says where those packages are found.

Currently

   |         Found:    Seq[Int]
   |         Required: scala.collection.mutable.Seq²[Int]
   |
   |         where:    Seq  is a trait in package scala.collection.immutable
   |                   Seq² is a trait in package scala.collection.mutable

If there is no common prefix, then it must superscript; but if the disjoint prefixes are short, as in this example, then it’s convenient just to show them inline.

It shows X.C and Y.C without superscripts if C is inherited from the same trait; but that’s actually when I’d like it to tell me more about where C is defined.

Another example of “just the right amount of prefix” is something like View.Concat or similar nested classes with simple names.

The interesting mechanism is that the message printer adds superscripts as it sees them; anything that requires postprocessing would have to collect the items and re-render the text.

3 Likes

By coincidence just noticed that PC has a ShortenedTypePrinter.

Here is the PR to show View.Concat. Probably much thought has gone into these issues.

Note that is 10 Feb 2024, not 24:00 UTC.