Bug 543081 - Generic wildcard compiler bug
Summary: Generic wildcard compiler bug
Status: NEW
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.7.3   Edit
Hardware: PC Windows 10
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: JDT-Core-Inbox CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2018-12-28 17:20 EST by N247S - CLA
Modified: 2023-02-26 19:31 EST (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description N247S - CLA 2018-12-28 17:20:02 EST
The Eclipse JDT Compiler does not handle generic wildcard correctly.
There are 2 reported instances I found so far already. One of them I encountered myself (Example 2), another was linked to me by StackOverflow-user '@xtratic' (Example 1).





Example 1: [StackOverflow link: https://stackoverflow.com/questions/53959451/wildcard-and-type-pameter-bounds-in-java]

In this case the compiler doesn't correctly warn about an incorrect bound generic parameter (circular dependency issue).



MCVE:
class A {}

class B<T extends A, E extends T> {
    B<?, A> b; // fails compilation (correct)
    B<?, ? extends A> b2; // passes compilation (incorrect)
}



In this case field 'b' does trow an error (correctly), but field 'b2' is considered valid by the compiler.


Eclipse version: unkown
OS/Hardware: unkown
JDK-version: 1.8.0 161





Example 2: [StackOverflow link: https://stackoverflow.com/questions/53962916/possible-eclipse-bug/53963616#comment94765265_53963616]

In this case complete identical wildcard declarations are considered incompatible to the point where a self-call will even fail



MCVE:
static class A {}
static class B<F, S extends A> {}
static class C<F extends B> {}
	
public static <F extends A, T> void test(C<? super B<? super F, ? super T>> test)
	{
		test(test); // fails compilation (incorrect)
	}



In this case the self-call to `test` should be completely valid, although it fails to compile.

Note1, other compilers had no issues with this test-case [link to test case from the StackOverflow post: https://ideone.com/AxjBrq].


Eclipse version: Oxygen.3a 4.7.3a (possibly for higher versions as well)
OS/Hardware: Windows 10 [PC]
JDK-version: 1.8.0 162



Workaround:
one possible solution for this problem is to declare the complete generic-parameter-type before the method declaration. e.g.:



public static <F extends A, T, S extends C<? super B<? super F, ? super T>>> void test1(S test)
	{
		GeneralTest.test1(test);
	}



Technically this works, but it's not according java-standards.
Besides it adds a lot of confusion/unnecessary code.
Comment 1 Stephan Herrmann CLA 2018-12-30 13:16:24 EST
Let's start with Example 1 here, please file a separate bug for Example 2.

This is what I see when compiling Example 1:

javac (tried 1.8.0_162, 9.0.4, 11):
B.java:4: error: type argument A is not within bounds of type-variable E
    B<?, A> b; // fails compilation (correct)
         ^
  where E,T are type-variables:
    E extends T declared in class B
    T extends A declared in class B
1 error

ecj (tried 4.4.2 through 4.10): ACCEPT


Ergo:
(1) Compilers agree on accepting the location marked "// passes compilation (incorrect)".

(2) Compilers disagree about accepting / rejecting the other location, marked "// fails compilation (correct)", so we need to ask whether ecj should be changed to reject this line. I don't have the time right now to dig into JLS in order to figure out, if rejecting is the desired behavior.

Perhaps the comments were meant to describe javac behavior??
Comment 2 Michael Ihde CLA 2018-12-30 19:36:00 EST
(In reply to Stephan Herrmann from comment #1)
> Let's start with Example 1 here, please file a separate bug for Example 2.
> 
> This is what I see when compiling Example 1:
> 
> javac (tried 1.8.0_162, 9.0.4, 11):
> B.java:4: error: type argument A is not within bounds of type-variable E
>     B<?, A> b; // fails compilation (correct)
>          ^
>   where E,T are type-variables:
>     E extends T declared in class B
>     T extends A declared in class B
> 1 error
> 
> ecj (tried 4.4.2 through 4.10): ACCEPT
> 
> 
> Ergo:
> (1) Compilers agree on accepting the location marked "// passes compilation
> (incorrect)".
> 
> (2) Compilers disagree about accepting / rejecting the other location,
> marked "// fails compilation (correct)", so we need to ask whether ecj
> should be changed to reject this line. I don't have the time right now to
> dig into JLS in order to figure out, if rejecting is the desired behavior.
> 
> Perhaps the comments were meant to describe javac behavior??

This is xtratic from the StackOverflow answer https://stackoverflow.com/a/53960187/2442526

I'd suggested the first case be linked in this report since it may have been relevant, my apologies if that was incorrect. Since the first link is the current focus I will assume it will remain the singular topic of this bug report.

N247S just mixed up his comments, I have corrected them below:

    class A {}
 
    class B<T extends A, E extends T> {
        // javac 8u112 emits a compile error
        // Eclipse 4.9.0 compiler does NOT emit a compile error
        B<?, A> b;

        // both do not emit a compile error, as expected 
        B<?, ? extends A> b2;
    }

Thank you!
Comment 3 N247S - CLA 2019-01-02 11:56:40 EST
@Stephan Herrmann; it seems pretty strange to separate (edge)cases for a problem which are verry simular in their cause.

I just hope this will result in an actual fix of the root of this problem, rather than a fix of separate edge cases, as the more I mess around with it the more I realize how imparitive this bug/these bugs actually is.

Example 2: 543128 [link: https://bugs.eclipse.org/bugs/show_bug.cgi?id=543128]
Comment 4 Stephan Herrmann CLA 2019-01-02 16:04:29 EST
(In reply to N247S - from comment #3)
> @Stephan Herrmann; it seems pretty strange to separate (edge)cases for a
> problem which are verry simular in their cause.
> 
> I just hope this will result in an actual fix of the root of this problem,
> rather than a fix of separate edge cases, as the more I mess around with it
> the more I realize how imparitive this bug/these bugs actually is.
> 
> Example 2: 543128 [link:
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=543128]

In this bug we are discussing an issue where ecj accepts a program which javac rejects. In the other bug we have the opposite situation. I would be very surprised if there's a connection.
Comment 5 Stephan Herrmann CLA 2019-01-04 18:33:03 EST
(In reply to Stephan Herrmann from comment #4)
> (In reply to N247S - from comment #3)
> > @Stephan Herrmann; it seems pretty strange to separate (edge)cases for a
> > problem which are verry simular in their cause.
> > 
> > I just hope this will result in an actual fix of the root of this problem,
> > rather than a fix of separate edge cases, as the more I mess around with it
> > the more I realize how imparitive this bug/these bugs actually is.
> > 
> > Example 2: 543128 [link:
> > https://bugs.eclipse.org/bugs/show_bug.cgi?id=543128]
> 
> In this bug we are discussing an issue where ecj accepts a program which
> javac rejects. In the other bug we have the opposite situation. I would be
> very surprised if there's a connection.

Indeed the fix under test for bug 543128 has no effect on the example as rendered in comment 2
Comment 6 Stephan Herrmann CLA 2019-08-17 20:26:37 EDT
Tentatively putting it on the radar for the next iteration.
Comment 7 Stephan Herrmann CLA 2019-11-17 16:08:44 EST
Bulk move of unassigned bugs to 4.15
Comment 8 Stephan Herrmann CLA 2020-02-27 18:49:17 EST
Bulk move to 4.16
Comment 9 Stephan Herrmann CLA 2020-05-18 18:47:19 EDT
Bulk move of unassigned bugs to 4.17
Comment 10 Eclipse Genie CLA 2023-02-26 19:31:51 EST
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.

If you have further information on the current state of the bug, please add it. 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.