Home > Software design >  Compilation error on generic type argument in sealed class permits clause
Compilation error on generic type argument in sealed class permits clause

Time:11-20

I have an abstract class (a phantom type) with 2 nested classes (phantom types as well) to form ADT:

public sealed abstract class APath<R> permits APath<R>.LastWildcard<R>, APath<R>.WholeWildcard<R> {
    ....

    protected final List<ADir> dirs;

    public final class LastWildcard<R1> extends APath<R1> {
        ...
    }

    public final class WholeWildcard<R1> extends APath<R1> {
        ...
    }
}

and ADir is (ADT too):

public sealed abstract class ADir permits ADir.Wildcard, ADir.Dir {
    public final class Wildcard extends ADir {}
    public final class Dir extends ADir {}
}

previously ADir was an interface, but due to this strange error I tried to change it to an abstract class. So, Eclipse and VSCode (with appropriate java extensions which is based on the Eclipse LSP as I know) don't show errors.

But Maven prints errors:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.3:compile (default-compile) on project prefile: Compilation failure: Compilation failure:                                                                                                 
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[13,52] '{' expected                                            
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[15,25] class, interface, enum, or record expected              
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[17,9] class, interface, enum, or record expected               
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[20,17] class, interface, enum, or record expected              
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[22,17] class, interface, enum, or record expected              
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[25,16] class, interface, enum, or record expected              
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[27,9] class, interface, enum, or record expected               
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[29,16] class, interface, enum, or record expected              
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[33,9] class, interface, enum, or record expected               
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[35,16] class, interface, enum, or record expected              
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[38,17] class, interface, enum, or record expected              
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[40,9] class, interface, enum, or record expected               
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[42,16] class, interface, enum, or record expected              
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[44,17] class, interface, enum, or record expected              
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[45,9] class, interface, enum, or record expected               
[ERROR] /D:/Experiment/src/main/java/prefile/pref/APath.java:[47,25] class, interface, enum, or record expected              
...

The location of the first error is here:

public sealed abstract class APath<R> permits APath<R>.LastWildcard<R>, APath<R>.WholeWildcard<R> 
                                                   ^  HERE !!!

My pom.xml is:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>XXX</groupId>
    <artifactId>XXX</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>XXX</name>
    <description>XXX</description>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <exec.mainClass>XXX</exec.mainClass>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.beust</groupId>
            <artifactId>jcommander</artifactId>
            <version>1.82</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
            </plugin>
        </plugins>
    </build>

</project>

And it seems that VSCode (and Eclipse) (at least I think so :) use the same Java (the same JDK). What can be the reason of the errors? Is it really wrong/unsupported syntax? Maybe 17 version is not enough? I have no idea TBH. Any hints and assumptions please.

CodePudding user response:

What can be the reason of the errors? Is it really wrong/unsupported syntax?

Yes. According to the Java language specification, the permits clause of a class is a list of type names not class types (as extends/implements). See JLS. A type name is just the name of a class without any generic type arguments.

In other words, drop the generic type arguments:

public sealed abstract class APath<R> permits APath.LastWildcard, APath.WholeWildcard {
    ....

    protected final List<ADir> dirs;

    public final class LastWildcard<R1> extends APath<R1> {
        ...
    }

    public final class WholeWildcard<R1> extends APath<R1> {
        ...
    }
}

As mentioned in the comments, Eclipse (and the VSCode plugin) use a different java compiler than Maven. The former uses ejc and the latter uses javac which comes with the JDK itself.

That could explain the discrepancy in the errors. It seems like the ecj compiler doesn't implement this part of the language specification correctly.

  • Related