1

Consider this Java program:

public class IntersectionBug {

    public static interface FooInterface {
        public void foo();
    }

    public static class FooSupport {
        protected void foo() {
        }
    }

    public static class Whatever<T extends FooSupport & FooInterface> {
    }
}

It fails to compile under JDK 1.8 compiler:

$ javac IntersectionBug.java
IntersectionBug.java:12: error: foo() in FooSupport cannot implement foo() in FooInterface
    public static class Whatever<T extends FooSupport & FooInterface> {
                                 ^
  attempting to assign weaker access privileges; was public
1 error

Obviously, if some type T is both a FooSupport and a FooInterface, then it must have a public void foo(), so the error is bogus.

My question: is this a compiler bug, or does the JLS really specify that this program is invalid? If the latter is the case, why the sub-optimal JLS behavior here?

Archie
  • 4,959
  • 1
  • 30
  • 36

1 Answers1

1

JLS §4.9 defines intersection types and what are their members via the concept of a notional class. In your particular case the notional class is:

class <notional> extends FooSupport implements FooInterface {}

Please note the empty class body.

The JLS paragraph is meant to imply that the notional class must be well-formed, or a compile error occurs. Clearly a class that inherits a protected implementation for a public interface method is not well-formed.

I agree that there could be other ways of specifying an intersection type that would admit unknown subclasses of FooSupport that would resolve the above conflict by overriding the method with public visibility.

I believe the style of definition via the notional class was chosen to keep complexity at bay. See how succinct §4.9 is in comparison to other definitions.

PS: Also ecj rejects your example, saying:

The inherited method IntersectionBug.FooSupport.foo() cannot hide the public abstract method in IntersectionBug.FooInterface

Stephan Herrmann
  • 7,963
  • 2
  • 27
  • 38
  • In [this answer](https://stackoverflow.com/a/34661152/2711488), Brian Goetz confirms in a related Q&A that the treatment of notional types like actual types is a bug, even if caused by the specification itself. Besides that, `javac` is piling even more problem into [the old one](https://bugs.openjdk.java.net/browse/JDK-7120669), like [this newer one](https://bugs.openjdk.java.net/browse/JDK-8200156)… – Holger Mar 19 '19 at 11:55
  • Thanks @Holger for the interesting links. Normally I'd reserve the term "bug" for when an implementation violates a specification, but Brian surely is one of the few people being in the position to classify a spec as buggy vis-a-vis a primordial intention :) -- Given that we haven't seen a lot of action in the JDK bug in many years, would it make sense to change one compiler (ecj) to comply with an assumed, intended, unwritten spec? Or should we just accept the fact that Java (as materialized by JLS,java,ecj) is not the language it is intended to be? – Stephan Herrmann Mar 21 '19 at 12:35
  • Well, I’m not in a position to decide this. But I assume there is some communication between the ECJ team and javac team regarding such open issues? So perhaps you can put some pressure on them? To my experience, JDK bugs can stay an arbitrarily long time in the list, as long as no-one puts pressure on the issue. Besides that, I’d like to point at the fact that [there is already a deviation](https://stackoverflow.com/q/45798233/2711488) and well, I’m not sure whether I can read from the specification that the “notional type” must be checked regarding inheritance rules at all. – Holger Mar 21 '19 at 14:16
  • @Holger Yes, there is communication between ECJ team and javac team, and also JLS authors. However, I prefer to restrict that communication to technical discussions, rather than trying to put pressure. Doing both on the same channel doesn't seem to work well. I just wish "the community" would be more vocal towards Oracle, demanding solutions to those open issues. Pet peeve currently being https://bugs.openjdk.java.net/browse/JDK-8215739 – Stephan Herrmann Mar 21 '19 at 18:09
  • Don’t take “putting pressure” too literally. Starting a discussion would be a good start. “the community” has the problem that they can’t contribute to the existing bugs on the list at all; only registered developers can do that and it’s not that easy to become a registered developer with the necessary permissions. All, the average developer can do, is to start a new bug report [at this place](https://bugreport.java.com/bugreport/) and watch the progress (or lack thereof) helplessly… – Holger Mar 22 '19 at 07:14