The scala compiler encoding different names with/without inner class's accessing

Given the following scala 3.x codes(I also asked in Stackoverflow):

object NameEncodingTest:
    class HasInner:
        private val x: Int = 0
        private val y: Int = 0

        def getX: Int = x
        def getY: Int = y

        class Inner:
            val inner: Int = y

Decompile it to java:

/*
 * Decompiled with CFR 0.152.
 */
public static class NameEncodingTest.HasInner {
    private final int x;
    public final int NameEncodingTest$HasInner$$y;

    public NameEncodingTest.HasInner() {
        this.x = 0;
        this.NameEncodingTest$HasInner$$y = 0;
    }

    public int getX() {
        return this.x;
    }

    public int getY() {
        return this.NameEncodingTest$HasInner$$y;
    }
}

As a comparison, the class file of javac has the same naming schemas:

// HasInner.java
public class HasInner {
	private int x = 0;
	private int y = 0;

	class Inner {
		final int inner = y;
	}
}

Which compiles to

/*
 * Decompiled with CFR 0.152.
 */
public class HasInner {
    private int x = 0;
    private int y = 0;

    class Inner {
        final int inner;

        Inner() {
            this.inner = HasInner.this.y;
        }
    }
}

I am very curious:

  • Why the fields x and y was using different schemas to encode?
  • Why the field y is changed to public (is not it private ok too)?
  • Is not the simple name schema enough for both cases (just as the javac) ?

This was just asked on chat, “What’s with all the name mangling?”

In this case, an accessible accessor is needed for the inner class, which takes its enclosing outer class in its constructor.

Java used to do the same thing, until the JVM got “nestmate” security allowing a class to declare another class as a friend that can access restricted members.

I don’t know if the details of the representation are a high priority to anyone, except that it would make debugging nicer, to read fewer mangled names.

It would be nice if this were a FAQ, even if the details are not spelled out (because they are implementation details).

also asked at Why the scala compiler encoding different names with/without inner class’s accessing? - Stack Overflow

if you ask the same question on multiple places online, it’s polite to crosslink, so someone doesn’t waste time helping you one place if you already got help in the other place

oh man I need the SO points to reach 40K. My old beginner answers just aren’t cutting it anymore.

I can not see the necessity of it, is not the simple name schema is enough (just as the javac do)?

Sorry for this, I was hurry to go to bed so forgot to add the corsslink.

javac used an accessor with a special name in previous versions.

Traditionally, inner classes do not have special access rights to outer classes.

My experience is that Java linters would complain about the accessor. I had a java-based manager who thought this was a problem of some kind. (The problem would be security. We had bigger security fish to fry.)

The lint would report that access was widened for some accessor.

“Modern” compilers should emit the attributes for who is a nest host and who is a nest member.

Definitely go to bed, as sleep is extremely important.

1 Like