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

Clean up "incompatible bounds" error messages

    Details

      Description

      Messages reporting incompatible bounds contain a lot of extraneous details that can be cleaned up. JDK-8067883 helped by avoiding the messages entirely in certain situations, but we can do a better job of presenting useful information when we do end up using the messages.

      Test:
          interface I<T> {
              <S> Class<S> m(T arg, Class<? extends S> c1 ,Class<? extends S> c2, Class<S> c3);
          }

          static <T> Class<T> anyClass() { return null; }

          void m(I<Double> i) {
              Class<? extends String> c = i.m(23.0, Number.class, anyClass(), Object.class, anyClass());
          }

      Output:
      error: incompatible types: inference variable S has incompatible bounds
              Class<? extends String> c = i.m(23.0, Number.class, anyClass(), Object.class, anyClass());
                                             ^
          upper bounds: String,Object
          lower bounds: T#2,Number
        where S,T#1,T#2 are type-variables:
          S extends Object declared in method <S>m(T#1,Class<? extends S>,Class<? extends S>,Class<S>,Class<S>)
          T#1 extends Object declared in interface I
          T#2 extends Object declared in method <T#2>anyClass()

      ---

      Some observations:

      - "Object" as an upper bound is trivially redundant: we already have upper bound String. (Similar could be said for redundant lower bounds, too -- and also maybe where an eq bound is a subtype of a certain upper/lower bound, but at that point maybe we're masking useful information...)

      - T#1 is not relevant, and shouldn't even appear. The "declared in method" clause should perhaps present the signature *after* substitution of class type variables?

      - There is, for some reason, no mention of the equality constraints coming from the 3rd and 4th arguments: S=Object and S=T#3

      - If we did present the equality constraints, it would be pointless to mention T#3 -- any bounds on T#3 have been propagated to S. Such ivars only add noise (a lot of it, since each one gets its own "where..." sentence).

      - Similarly, it's not useful to talk about T#2 as a lower bound, because it doesn't contribute to the "incompatible bounds" problem. Generally, I don't think bare type variables belong here, either, although there may be some caveats (solving multiple vars at once, legacy inference algorithm, ...)

      ---

      Proposed error message:
      error: incompatible types: inference variable S has incompatible bounds
              Class<? extends String> c = i.m(23.0, Number.class, anyClass(), Object.class, anyClass());
                                             ^
          equal bounds: Object
          upper bounds: String
          lower bounds: Number
        where S is a type-variable:
          S extends Object declared in method <S>m(Double,Class<? extends S>,Class<? extends S>,Class<S>,Class<S>)

      (Or, in a variation that doesn't have the eq bound, report upper bound String and lower bound Number.)

        Attachments

          Activity

            People

            • Assignee:
              dlsmith Dan Smith
              Reporter:
              dlsmith Dan Smith
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated: