Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 513766 - [1.8][inference] Compiler error when autoboxing type inferrring expression in if clause
Summary: [1.8][inference] Compiler error when autoboxing type inferrring expression in...
Status: VERIFIED NOT_ECLIPSE
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.7   Edit
Hardware: PC Windows 7
: P3 major (vote)
Target Milestone: 4.7 M7   Edit
Assignee: Stephan Herrmann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-03-16 10:35 EDT by Martin Elf CLA
Modified: 2019-07-29 06:08 EDT (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 Martin Elf CLA 2017-03-16 10:35:17 EDT
Eclipse shows compilation error "Type mismatch: cannot convert from Object to boolean" when type inferring expression is being autoboxed in an "if clause". However java compiler (Oracle JDK 1.8.0_92) compiles and runs the code correctly. 

Code that does not compile in Eclipse:
=====================
public class Test {
    private static <T> T get(String key) {
        return (T) Boolean.TRUE;
    }
	
    public static void main(String[] args) {
        if(get("key")) {
            System.out.println("Passed");
        }
    }
}
=====================
Comment 1 Stephan Herrmann CLA 2017-03-16 10:45:45 EDT
Interesting.

Bonus question: can you show the paragraph in JLS specifying that the condition in an if expression should be inferred against target type Boolean? IOW, does an if statement define an assignment context or an invocation context? I don't see that in the spec.

In my understanding, get() must be resolved as a standalone expression (i.e., with no target type), hence inferring T to Object is the best we can do.
Comment 2 Martin Elf CLA 2017-04-19 03:52:05 EDT
Based on jls-14.9 of SE8, the "if" expression must be boolean or Boolean, or a compile-time error occurs. From this the inferring to Boolean can be judged. The same does java compiler based on jls-18.2.1 as the "if" expression is "Expression -> Boolean".

I would very much appreciate this to be fixed because it is a blocker for using Eclipse on my project. I am forced to use IntelliJ as it correctly compiles this code.
Comment 3 Martin Elf CLA 2017-04-19 03:58:23 EDT
The same applies for ternary expressions.
Comment 4 Stephan Herrmann CLA 2017-04-19 13:51:24 EDT
Intuitively, you're right of course. But in implementing JLS intuition is sometimes misleading. Before we can ask "which target type", we have to ask "what kind of context" and the answer must be either "assignment context" or "invocation context", otherwise using a target type during inference is illegal per JLS.

(In reply to Martin Elf from comment #2)
> I would very much appreciate this to be fixed because it is a blocker for
> using Eclipse on my project. I am forced to use IntelliJ as it correctly
> compiles this code.

To the best of my knowledge, "correctly" is wrong in this sentence. Until proven wrong I will hold that the code in comment 0 is not legal Java 8.


See also my answer to a related question on SO (which contains further links):
- http://stackoverflow.com/questions/43038736/type-mismatch-error-in-java-8/43075498#answer-43075498

If this is blocking you please consider reminding Oracle that they have a spec bug  that has been unresolved for several years now.
Comment 5 Stephan Herrmann CLA 2017-04-20 16:46:28 EDT
(In reply to Stephan Herrmann from comment #4)
> If this is blocking you please consider reminding Oracle that they have a
> spec bug  that has been unresolved for several years now.

Never mind, I asked them, and Dan Smith (JLS author) calls this a bug in javac, sorry. JLS is not going to change and hence ecj cannot accept this program.
Comment 6 Martin Elf CLA 2017-04-28 03:43:51 EDT
I disagree with ecj not accepting this. Based on the stackoverflow link I changed "compiler compliance level" in Eclipse from 1.8 to 1.7. This time the code compiles fine and Eclipse is not complaining. Therefore I propose that ecj fixes this - either by not showing error in 1.8 (preferred) or by showing error in 1.7 too as to be consistent with JLS.
Comment 7 Stephan Herrmann CLA 2017-04-28 19:58:34 EDT
(In reply to Martin Elf from comment #6)
> I disagree with ecj not accepting this.

This seems to imply you disagree with JLS?


> Based on the stackoverflow link I
> changed "compiler compliance level" in Eclipse from 1.8 to 1.7. This time
> the code compiles fine and Eclipse is not complaining. Therefore I propose
> that ecj fixes this - either by not showing error in 1.8 (preferred) or by
> showing error in 1.7 too as to be consistent with JLS.

Changing the behavior at 1.8 would mean to deliberately introduce a bug, which is not my plan.

Regarding pre-1.8 type inference, the knowledge in the team is dwindling to be honest, and I cannot argue from the top of my head, whether or not your program is a legal Java 7 program.
Ergo, I have insufficient confidence for raising more errors at 1.7, and surely people never like if the same language version starts rejecting programs that previously were accepted. A difference between 1.7 and 1.8 modes, OTOH, may well be justified given that type inference was completely rewritten (spec & impl) for 1.8.
Comment 8 Martin Elf CLA 2017-04-29 05:02:35 EDT
Well, my point is that main idea behind Eclipse is to help developers to write java code rather than to be JLS validator. Definitely it is not helping at all, when it does not compile code that the most frequently used javac compiles. I doubt that javac would be fixed even if the bug was raised. It would mean that many applications will fail to compile. Is it possible to at least provide an option in Eclipse to behave like javac? By default turned off.
Comment 9 Jay Arthanareeswaran CLA 2017-05-09 09:00:10 EDT
(In reply to Martin Elf from comment #8)
> Well, my point is that main idea behind Eclipse is to help developers to
> write java code rather than to be JLS validator. Definitely it is not
> helping at all, when it does not compile code that the most frequently used
> javac compiles. I doubt that javac would be fixed even if the bug was
> raised. It would mean that many applications will fail to compile. Is it
> possible to at least provide an option in Eclipse to behave like javac? By
> default turned off.

I changed the code from comment #0 slightly to this: 

public class Test {
    public static void main(String[] args) {
        if(Another.get("key")) {
            System.out.println("Passed");
        }
    }
}
class Another {
	public static <T> T get(String key) {
        return (T) "";
    }
}

This compiles in Javac albeit with notes about unchecked and unsafe operations. Now trying to run this program results in a ClassCastException. Would you really risk a run time error?
Comment 10 Stephan Herrmann CLA 2017-05-09 09:07:34 EDT
(In reply to Martin Elf from comment #8)
> I doubt that javac would be fixed even if the bug was raised.

Let's together watch https://bugs.openjdk.java.net/browse/JDK-8179483
Comment 11 Jay Arthanareeswaran CLA 2017-05-09 09:22:36 EDT
Verified for 4.7 M7
Comment 12 Stephan Herrmann CLA 2019-03-14 16:43:36 EDT
For the records: I just stumbled upon the java 12 version of this javac bug:

//--
public class X {
    @SuppressWarnings("preview")
    public void foo(int i) {
    	if (switch(i) { default -> magic(); })
            System.out.println("true");
        if (magic())
            System.out.println("true, too");
    }
    <T> T magic() { return null; }
}
//--

Both if statements are illegally accepted by javac, correctly rejected by ecj.

For a moment I was uncertain regarding this sentence from ยง15.28.1:

"Where a poly switch expression appears in a context of a particular kind with target type T, its result expressions similarly appear in a context of the same kind with target type T."

I was worried that "context of a particular kind" could blur the distinction of contexts, but then the term "poly switch expression" already clarifies that we are inside an invocation or assignment context. All is good.
Comment 13 Manoj N Palat CLA 2019-03-14 20:08:18 EDT
(In reply to Stephan Herrmann from comment #12)
> For the records: I just stumbled upon the java 12 version of this javac bug:
es
> that we are inside an invocation or assignment context. All is good.

Thanks Stephan for clarification. I've added this as an additional test to SwitchExpressionTest via commit:https://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA_12&id=e2d24f0b92eac7f0e09c2a997511f00da5b8ed5e
Comment 14 Eclipse Genie CLA 2019-07-29 04:19:20 EDT
New Gerrit change created: https://git.eclipse.org/r/146723
Comment 16 Stephan Herrmann CLA 2019-07-29 06:08:32 EDT
(In reply to Eclipse Genie from comment #15)
> Gerrit change https://git.eclipse.org/r/146723 was merged to [master].
> Commit:
> http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/
> ?id=de94bf3e02a331d5abf69c0fbc4855e04f919774

Integrated the test with our runjavac mode, documenting the javac bug.