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

Bug 505935

Summary: [1.8] Compiler error involving wildcards and raw types, works in javac
Product: [Eclipse Project] JDT Reporter: Osvaldo Pinali Doederlein <opinali>
Component: CoreAssignee: JDT-Core-Inbox <jdt-core-inbox>
Status: CLOSED WONTFIX QA Contact:
Severity: major    
Priority: P3 CC: stephan.herrmann
Version: 4.6   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard: stalebug

Description Osvaldo Pinali Doederlein CLA 2016-10-13 22:17:39 EDT
This fails in Eclipse, works in javac:

---


import java.util.List;

public class Test {
  static class F<E> {
    public static <E> F<E> foo(final Iterable<E> iter) { return null; }
  }

  static class D<T, V> {
    List<T> doo(X<V> x) { return null; }
  }

  static interface X<T> {}

  public static void main(String[] args) {
    X<?> x = null;
    D<String, ?> d = new D<String, Integer>();
    F.foo(d.doo((X) x));
  }
}
Comment 1 Sasikanth Bharadwaj CLA 2016-10-14 02:16:00 EDT
Reproducible on master. Compiled fine until 4.6 M6. Trying to narrow down to the commit that caused the change in behavior
Comment 2 Stephan Herrmann CLA 2016-10-14 15:38:00 EDT
@Osvaldo: iron laws of type inference:

(1) NEVER use raw types in conjunction with type inference.

(2) If you really must use raw types, rule (1) applies.

:)


Plus: when removing the cast, also javac will tell you that the program is not type safe:

error: incompatible types: X<CAP#1> cannot be converted to X<CAP#2>
    F.foo(d.doo(x));
                ^
  where CAP#1,CAP#2 are fresh type-variables:
    CAP#1 extends Object from capture of ?
    CAP#2 extends Object from capture of ?
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
Comment 3 Osvaldo Pinali Doederlein CLA 2016-10-14 15:55:54 EDT
Hi Stephan, I know the code is awful, in my defense I'm not the author of the real-world code from which I have derived this repro snippet :)

I can force Eclipse to not break on this code by adding an extra ugly cast:

    F.foo(d.<X>doo((X) x));
            ^^^

The "bug" is the fact that with the original code snippet, javac only complains with lots of warnings, but jdt has a hard failure so it breaks the build. My team is IDE-neutral so people not using Eclipse frequently reintroduce this kind of breakage (from my point of view) by running automated code cleanup tools (this is at Google, where we have an obsession for lint and auto-fixing tools...).
Comment 4 Stephan Herrmann CLA 2016-10-14 16:14:16 EDT
(In reply to Osvaldo Pinali Doederlein from comment #3)
> Hi Stephan, I know the code is awful, in my defense I'm not the author of
> the real-world code from which I have derived this repro snippet :)
> 
> I can force Eclipse to not break on this code by adding an extra ugly cast:
> 
>     F.foo(d.<X>doo((X) x));
>             ^^^

That's not a cast but an explicit type argument, whereby you avoid one step of inference, because you already specify the type, which inference would have to find by itself otherwise. This is a (comparably) good fix for two reasons:
- compiler will check if your type hint makes any sense
- you don't need a cast that could throw CCE at runtime


> The "bug" is the fact that with the original code snippet, javac only
> complains with lots of warnings, but jdt has a hard failure so it breaks the
> build. My team is IDE-neutral so people not using Eclipse frequently
> reintroduce this kind of breakage (from my point of view) by running
> automated code cleanup tools (this is at Google, where we have an obsession
> for lint and auto-fixing tools...).

IDE-neutral is good. Vendor neutral is even better, and to figure out what is the vendor neutral solution we must find out if the given snippet is legal Java per JLS or not. javac is just one implementation, which has its own set of bugs (specifically when dealing with raw types).

Hopefully, seeing the relevant change in ecj will help us understand who is to blame.

waiting for Sasi's result.
Comment 5 Osvaldo Pinali Doederlein CLA 2016-10-14 20:17:24 EDT
Agree 100% with vendor neutrality; the point of bugs like this is that, I suppose, the Java language spec is strict on the outcome of all type errors, it's never an option whether the compiler will emit a fatal error or not... so either javac has a bug, or ecj has a bug, or maybe even the spec has some unclear corner case that should be clarified. I'm curious to know which of these is true here. :)
Comment 6 Sasikanth Bharadwaj CLA 2016-10-17 02:35:33 EDT
(In reply to comment #4)
> 
> waiting for Sasi's result.
It's the commit http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=12d1c84ee9af849add945a196f8d13163f45dde7 for bug 488649 that caused the change in behavior. Specifically, the "signal to erase return type and exceptions, while keeping javac compatibility at 1.7-" causes this error to occur. Will delve into details now.
Comment 7 Eclipse Genie CLA 2020-05-03 00:58:29 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.