Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 423849

Summary: [1.8][compiler] cannot implement java.nio.file.Path because of compiler name clash
Product: [Eclipse Project] JDT Reporter: kasper nielsen <kasperni>
Component: CoreAssignee: Srikanth Sankaran <srikanth_sankaran>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: srikanth_sankaran
Version: 4.3.1   
Target Milestone: BETA J8   
Hardware: PC   
OS: Mac OS X   
Whiteboard:

Description kasper nielsen CLA 2013-12-11 12:46:24 EST
It is impossible to extend java.nio.file.Path because of a compiler error

The type MyPath must implement the inherited abstract method Path.register(WatchService, WatchEvent.Kind<?>[], WatchEvent.Modifier...)	

The method register(WatchService, WatchEvent.Kind<?>[], WatchEvent.Modifier...) of type MyPath must override or implement a supertype method

Name clash: The method register(WatchService, WatchEvent.Kind<?>[], WatchEvent.Modifier...) of type MyPath has the same erasure as register(WatchService, WatchEvent.Kind<?>[], WatchEvent.Modifier...) of type Path but does not override it

The following two methods are the culprit

WatchKey register(WatchService watcher, Kind<?>[] events, Modifier... modifiers) throws IOException
WatchKey register(WatchService watcher, Kind<?>... events) throws IOException

---Full Source----
public class MyPath implements Path {

    /** {@inheritDoc} */
    @Override
    public FileSystem getFileSystem() {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public boolean isAbsolute() {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public Path getRoot() {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Path getFileName() {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Path getParent() {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public int getNameCount() {
        return 0;
    }

    /** {@inheritDoc} */
    @Override
    public Path getName(int index) {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Path subpath(int beginIndex, int endIndex) {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public boolean startsWith(Path other) {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public boolean startsWith(String other) {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public boolean endsWith(Path other) {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public boolean endsWith(String other) {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public Path normalize() {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Path resolve(Path other) {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Path resolve(String other) {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Path resolveSibling(Path other) {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Path resolveSibling(String other) {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Path relativize(Path other) {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public URI toUri() {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Path toAbsolutePath() {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Path toRealPath(LinkOption... options) throws IOException {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public File toFile() {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public WatchKey register(WatchService watcher, Kind<?>[] events, Modifier... modifiers) throws IOException {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public WatchKey register(WatchService watcher, Kind<?>... events) throws IOException {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Iterator<Path> iterator() {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public int compareTo(Path other) {
        return 0;
    }

}
Comment 1 Srikanth Sankaran CLA 2013-12-12 11:33:25 EST
Thanks for taking a look.
Comment 2 Srikanth Sankaran CLA 2013-12-15 07:48:26 EST
Problem reproducible on top of BETA_JAVA8: Short test case:

// --
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchEvent.Modifier;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

public abstract class X implements Path {
    @Override
    public WatchKey register(WatchService watcher, Kind<?>[] events, Modifier... modifiers) throws IOException {
        return null;
    }
}
Comment 3 Srikanth Sankaran CLA 2013-12-18 22:07:03 EST
I'll take over this one - Looks like TypeSystem is creating two different
ArrayBindings - something about $ in the nested type name is breaking the
type identity.
Comment 4 Srikanth Sankaran CLA 2013-12-18 22:28:49 EST
(In reply to Srikanth Sankaran from comment #3)
> I'll take over this one - Looks like TypeSystem is creating two different
> ArrayBindings - something about $ in the nested type name is breaking the
> type identity.

The ArrayBinding corresponding to the varargs parameter type ends up becoming
a BinaryTypeBinding, while the one from source ends up being a ParameterizedTypeBinding given outer class is parameterized. Fix is to eagerly
resolve the UnresolvedReferenceBinding if it corresponds to an inner type.
Comment 5 Srikanth Sankaran CLA 2013-12-18 22:44:02 EST
Thanks Kasper. Fix and test available here: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=e77a13c5cfd8a2800f9cc3d46536a8ccdc632a8b