Bug 484467 - "Cannot reference a field before it is defined" error depends on source order
Summary: "Cannot reference a field before it is defined" error depends on source order
Status: NEW
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.6   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: JDT-Core-Inbox CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2015-12-16 04:16 EST by Jean-Marie HENAFF CLA
Modified: 2023-02-07 10:54 EST (History)
2 users (show)

See Also:


Attachments
Source files to reproduce the issue (958 bytes, application/gzip)
2015-12-16 04:16 EST, Jean-Marie HENAFF CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jean-Marie HENAFF CLA 2015-12-16 04:16:56 EST
Created attachment 258721 [details]
Source files to reproduce the issue

The following code does not compile with ecj but does with javac.

@AnnotationWithEnum(EnumAnnotated.VALUE)
public enum EnumAnnotated {
  @AnnotationWithEnum(EnumAnnotated.VALUE)
  VALUE;

}

If AnnotationWithEnum.java is placed before EnumAnnotated.java in the source list passed to ecj, compilation fails with:

----------
1. ERROR in /tmp/sample/annotation/test/EnumAnnotated.java (at line 21)
	@AnnotationWithEnum(EnumAnnotated.VALUE)
	                                  ^^^^^
Cannot reference a field before it is defined
----------
1 problem (1 error)


If the order is inverted, it compiles just fine.

I've attached a sample.tar.gz archive with the source files and 2 example of command lines in README.txt for you to reproduce.


Tested with ecj-4.6M4.
Comment 1 Jay Arthanareeswaran CLA 2015-12-17 00:14:51 EST
Same can be observed in the IDE too. The error is reported on a full build but the reconciler doesn't when only EnumAnnotated is compiled.
Comment 2 Jay Arthanareeswaran CLA 2015-12-17 00:50:35 EST
Looks like this is one of those ordering issue with respect to annotations. I can see in the reconciler case, the insideTypeAnnotation is set to true that is keeping the problem from reported.

Stephan, can you take a look at this please?
Comment 3 Greg Woolsey CLA 2018-10-30 13:34:37 EDT
This is still an active bug, and is not specific to annotations.  This simple class compiles fine with javac, but fails to compile with the above error in the latest Eclipse.

Note that the same error happens when the Test class is moved to its own source file in the same package.  In that case, it appears the Eclipse compiler is confusing the enum with the same name vs. the class with that name.  However, the ::new reference must be to a type, not an Enum instance, which is how javac knows which one to reference. 

A workaround is to reference the class in the ::new constructor argument with its fully qualified class name.  Then the Eclipse compiler understands which "Test" is being referenced.  However, javac shows this is not required, and that the source ordering used by Eclipse is not flexible enough to handle this case and the original case for this bug.

public enum EclipseCompileBug {
	/*
	 * Next line fails with these errors in Eclipse, works with javac:
	 * <li>Test cannot be resolved to a type
	 * <li>Cannot reference a field before it is defined
	 */
	Test(Test::new);

	@FunctionalInterface
    public interface IConstructor<T extends Object> {
        T apply();
    }

    private final IConstructor<?> constructor;
	private EclipseCompileBug (IConstructor<?> newObj) {
		constructor = newObj;
	}
	
	public static class Test {
		
	}
}
Comment 4 Stephan Herrmann CLA 2018-10-30 14:59:49 EDT
(In reply to Greg Woolsey from comment #3)
> This is still an active bug, and is not specific to annotations.  This
> simple class compiles fine with javac, but fails to compile with the above
> error in the latest Eclipse.
> 
> Note that the same error happens when the Test class is moved to its own
> source file in the same package.  In that case, it appears the Eclipse
> compiler is confusing the enum with the same name vs. the class with that
> name.  However, the ::new reference must be to a type, not an Enum instance,
> which is how javac knows which one to reference. 
> 
> A workaround is to reference the class in the ::new constructor argument
> with its fully qualified class name.  Then the Eclipse compiler understands
> which "Test" is being referenced.  However, javac shows this is not
> required, and that the source ordering used by Eclipse is not flexible
> enough to handle this case and the original case for this bug.
> 
> public enum EclipseCompileBug {
> 	/*
> 	 * Next line fails with these errors in Eclipse, works with javac:
> 	 * <li>Test cannot be resolved to a type
> 	 * <li>Cannot reference a field before it is defined
> 	 */
> 	Test(Test::new);
> 
> 	@FunctionalInterface
>     public interface IConstructor<T extends Object> {
>         T apply();
>     }
> 
>     private final IConstructor<?> constructor;
> 	private EclipseCompileBug (IConstructor<?> newObj) {
> 		constructor = newObj;
> 	}
> 	
> 	public static class Test {
> 		
> 	}
> }

Thanks for the example. This is an entirely different bug so I filed bug 540631.
Comment 5 Eclipse Genie CLA 2023-02-07 10:54:03 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.