akshattandon / projectlombok

Automatically exported from code.google.com/p/projectlombok
0 stars 0 forks source link

Random javac compilation error: Cannot use 'val' here #694

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. git clone https://github.com/icgc-dcc/dcc.git
2. git checkout 5df0ba29beb8779fa75ae28c55aff40cbb5c2cb3
3. mvn clean package -am -pl dcc-etl/dcc-etl-indexer -DskipTests

You may need to repeat 3. multiple times to observe the error

What is the expected output? What do you see instead?

I expect the build to complete successfully, but see the following output 
instead:

ERROR] Failed to execute goal 
org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on 
project dcc-etl-indexer: Compilation failure
[ERROR]  
dcc/dcc-etl/dcc-etl-indexer/src/main/java/org/icgc/dcc/etl/indexer/document/core
/DocumentProcessor.java:[121,9] Cannot use 'val' here because initializer 
expression does not have a representable type: Type cannot be resolved

Please provide any additional information below.

I have given access to my private github repo to one of the core developers 
(rzwitserloot) who has confirmed that this occurs randomly. 

Using Lombok 1.12.6

mvn -v  
Apache Maven 3.2.1 (ea8b2b07643dbb1b84b6d16e1f08391b666bc1e9; 
2014-02-14T12:37:52-05:00)
Maven home: /usr/local/Cellar/maven/3.2.1/libexec
Java version: 1.7.0_55, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.7.0_55.jdk/Contents/Home/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.9.2", arch: "x86_64", family: "mac"

Original issue reported on code.google.com by rtier...@gmail.com on 13 Jun 2014 at 6:14

GoogleCodeExporter commented 9 years ago
After _A LOT_ of searching and trying things, it looks like this is caused by 
the following:

1) The order in which source files are processed is semi-random, probably 
because a map with undefined order is in the process somewhere, and it sorts on 
memory position which is non-deterministic.

2) You use val x = new Foo() {} syntax someplace (as in, the RHS of a val-typed 
local variable declaration is or contains an anonymous inner class literal), 
_AND_ this is evaluated BEFORE Foo itself. In this case, all usage of 'val' in 
Foo will cause errors.

We're not 100% sure if that really is it, but so far it looks like it is. In 
the original sources, the relevant line is:

 dcc/dcc-etl/dcc-etl-indexer/src/main/java/org/icgc/dcc/etl/indexer/document/schema/ForwardSchemaGenerator.java:115 (method: createProcessor), which uses 'val' along with an anonymous inner class literal of DocumentProcessor on the right hand side. The actual errors which usually (but not always) occur, occur during val usage of DocumentProcessor.

So far, on successful runs, DocumentProcessor is done first and 
ForwardSchemaGenerator later, and on failing runs, it's the reverse. 
'unvalling' the assignment on line 115 so far has resulted in 10 successful 
runs and no failures, so seems like bingo.

We're going to try and 'fix' this by eliminating the anonymous inner class 
aspect of any RHS expression and then attribing it, and if that does not work, 
we're probably going to declare any usage of AICLs in the RHS as invalid. Note 
that our preferred solution does mean that this:

val x = new Object() { public int someNewMethodThatDoesntOverrideAnything() { 
return 5; }}.someNewMethodThatDoesntOverrideAnything();

would NOT be equivalent to 'final int x = ...' even though it should be, but 
we'll assume that the above is pretty much never used by any java programmers 
ever. So, that particular bit being broken is fine in my book, I think.

Original comment by reini...@gmail.com on 28 Jun 2014 at 10:52

GoogleCodeExporter commented 9 years ago
CONFIRM previous hypothesis. This test case proves it. It requires 3 files:

File1.java:

    public class File1 {{
        lombok.val f2 = new File2() {};
    }}

File2.java:

    public class File2 {{
        lombok.val f3 = 0;
    }}

now compile with:

javac -cp lombok.jar *.java

in a dir with just the above 2 files.

Half of the time it fails, the other half it succeeds. (It succeeds if File2 is 
processed first, fails if File1 is processed first). If you remove the {} on 
line 2 of File1.java (remove the anonymous inner class literal aspect of it), 
the problem ceases to exist, and all compiles always succeed, regardless of 
whether File1 or File2 ends up getting processed first.

NB: The following replacement for File1.java also causes the compile run to 
fail 50% of the time:

    public class File1 {{
        class F2 extends File2 {}
        lombok.val f2 = new File2();
    }}

essentially, any method local thing that extends a source-path type will 'ruin' 
val in that source-path type if ANY attributing is done of any member anywhere 
in that scope. Most likely the solution is to update our tree copier to be more 
careful about how to handle this, because right now evidently the 'real' File2 
nodes are being modified somehow.

Original comment by r.spilker on 28 Jun 2014 at 11:15

GoogleCodeExporter commented 9 years ago
Wow, I really appreciate all your hard work here. Great investigating!

Any idea on when you might be able to handle this or throw an error in eclipse 
/ cli?

Thanks again

Original comment by rtier...@gmail.com on 7 Jul 2014 at 2:00

GoogleCodeExporter commented 9 years ago
Hold on to your hats... I think I fixed this thing.

Give this edge build a shot?

http://projectlombok.org/download-edge.html

Original comment by reini...@gmail.com on 31 Jan 2015 at 3:54