Final volatile value is passed in scalac while failed in javac

The following java failed in javac (java 17.0.8)

public class Volatile {
	final volatile boolean[] mask = new boolean[128];
}

Volatile.java:2: error: illegal combination of modifiers: final and volatile
final volatile boolean mask = new boolean[128];
^

However, the following scala file passed in scalac (Scala 3.4.0-RC1)


class Volatile:
	@volatile final val mask: Array[Boolean] = Array.ofDim(128)

And decompiled as following codes:

/*
 * Decompiled with CFR 0.152.
 */
public class Volatile {
    private final volatile boolean[] mask = new boolean[128];

    public final boolean[] mask() {
        return this.mask;
    }
}

Is this a bug in scalac, or, at least should be enhance in scalac ?

Let’s start with the fact that Java final != Scala final. In Scala being final at the Bytecode level is mostly related to usage of val vs var.
Scala final does not affect directly some of JMM (Java Memory Model) guarantees, it’s only used for inheritance purpouse to disallow any further overrides.
final volatile bolean could be translated to @volatile var boolean

However, what we see here is a bug in the compiler - only var can be volatile. It seems like it is catched in Scala 2, but not in Scala 3.
I’ve submitted an issue: https://github.com/lampepfl/dotty/issues/19416

3 Likes