Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8275746

Elements.hides and static interface methods

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P3 P3
    • 25
    • None
    • tools

      Is it incorrect for Elements.hides to report that static methods in interfaces hide static methods in super-interfaces?

      https://docs.oracle.com/javase/specs/jls/se11/html/jls-9.html#jls-9.4.1 discusses that it's a compile time error for static methods in interfaces to hide instance methods in super-interaces. It also mentions that interfaces don't inherit static methods, which suggests static methods in interfaces can't hide static methods in super-interfaces.

      i.e. the following doesn't compile because static methods aren't inherited into interfaces, so it seems impossible for a declaration of 'f' in B to hide the one in A:

      interface A {
        static void f() {}
      }
      interface B extends A {
        static void g() {
          f();
        }
      }

      Consider:

      ```
      interface A {
        static void f() {}
      }
      interface B extends A {
        static void f() {}
      }
      ```

      ```
      import java.util.ArrayDeque;
      import java.util.ArrayList;
      import java.util.Deque;
      import java.util.List;
      import java.util.Set;
      import javax.annotation.processing.AbstractProcessor;
      import javax.annotation.processing.RoundEnvironment;
      import javax.annotation.processing.SupportedAnnotationTypes;
      import javax.lang.model.SourceVersion;
      import javax.lang.model.element.Element;
      import javax.lang.model.element.TypeElement;
      import javax.lang.model.util.ElementScanner8;
      import javax.tools.Diagnostic;

      @SupportedAnnotationTypes("*")
      public class P extends AbstractProcessor {
        @Override
        public SourceVersion getSupportedSourceVersion() {
          return SourceVersion.latestSupported();
        }

        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
          List<Element> elements = new ArrayList<>();
          new ElementScanner8<Void, Void>() {
            @Override
            public Void scan(Element e, Void unused) {
              elements.add(e);
              return super.scan(e, null);
            }
          }.scan(roundEnv.getRootElements(), null);
          for (Element a : elements) {
            for (Element b : elements) {
              boolean hides = processingEnv.getElementUtils().hides(a, b);
              String message = String.format("hides(%s, %s) = %s\n", key(a), key(b), hides);
              if (hides) {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, message);
              }
            }
          }
          return false;
        }

        private Object key(Element e) {
          Deque<String> bits = new ArrayDeque<>();
          do {
            if (e.getSimpleName().length() > 0) {
              bits.add(e.getSimpleName().toString());
            }
            e = e.getEnclosingElement();
          } while (e != null);
          return String.join(".", bits);
        }
      }
      ```

      $ javac -processor P T.java
      Note: hides(f.B, f.A) = true

            darcy Joe Darcy
            cushon Liam Miller-Cushon
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: