Bug 418530 - Can't access introduced field from 'this' or client class
Summary: Can't access introduced field from 'this' or client class
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.7.3   Edit
Hardware: PC Mac OS X
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-10-02 11:44 EDT by Matthew Adams CLA
Modified: 2013-10-02 18:12 EDT (History)
1 user (show)

See Also:


Attachments
sample project demonstrating error (2.86 KB, application/zip)
2013-10-02 11:44 EDT, Matthew Adams CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Matthew Adams CLA 2013-10-02 11:44:26 EDT
Created attachment 236043 [details]
sample project demonstrating error

A class receiving an introduced field via a trait pattern cannot access the field, and a client of a class receiving an introduced field cannot access the field.  Decompilation shows that the introduced field is present and public.

Erroneous behavior seen from 1.7.3-1.8.0.

Sample project attached.

=====
public aspect Trait {

	public interface I extends Behavior {}
	
	declare parents: @Behaved * implements I;
	
	private final String I.name = getClass().getName();
	
	public String I.hello() {
		return "hello" + name;
	}
}
=====
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Behaved {
}
=====
public interface Behavior {

	String hello();
}
=====
@Behaved
public class Target {

	public void accessIntroducedField() {
		String s = this.name;
	}
}
=====
public class TargetClient {

	Target target = new Target();

	public void accessField() {
		String name = target.name;
	}
}
Comment 1 Andrew Clement CLA 2013-10-02 15:34:45 EDT
The ITD visibility is actually with respect to the aspect - this is the original AspectJ design.

private means only the crosscutting concern in the aspect can see it.  If you add a method to the aspect:

public String foo(Target t) {
  return t.name;
}

that reference will compile just fine.

That said, I'm not totally against changing the behaviour as I know peoples expectations don't always agree with this original design decision (and the interpretation right now is: "I want to stuff a new private field into that type" - ignoring the crosscutting concern scope).

It is the same as the 'dont mangle field names on the target' issue. The mangling was done for the exact same reason (this is a field that lives inside that target type but is really only there for the aspect).

Can you just use ITD getters?
Comment 2 Matthew Adams CLA 2013-10-02 16:32:42 EDT
I'm not sure what you mean by ITD getters -- the mangled method (in this example)
ajc$interFieldGet$testcase_Trait$testcase_Trait$I$name()

or adding my own getter method that gets introduced along with the rest, like this?
public aspect Trait {

	public interface I extends Behavior {}
	
	declare parents: @Behaved * implements I;
	
	private String I.name = getClass().getName();
	
	public String I.hello() {
		return "hello" + name;
	}
/////////////////// MANUALLY CODED GETTER & SETTER?	
	public String I.name() {
		return this.name;
	}
	
	public void I.name(String s){
		this.name = s;
	}
}


It seems as though there's room here for more access levels than private, meaning "visible only to the aspect", and public, meaning "visible to everything".  What I'm really looking for is "visible to the aspect, the target and subtypes of the target".

The fact that, after compilation, the Java access modifier is public is still troubling, because if the class with the public ITD field is put in a jar on the classpath of a consuming project, the consuming project would see the public field, unlike what you see in the providing project.  That strikes me as inconsistent.

I suppose my viewpoint is that if a consuming module can see the ITD field, then it should also be visible to the class receiving the ITD field in the providing module.

It doesn't really seem worth it to allow "protected" here; that'd be more work than necessary, because getters can be manually added.  I think more value would be offered by full-blown trait support.
Comment 3 Andrew Clement CLA 2013-10-02 17:22:22 EDT
> The fact that, after compilation, the Java access modifier is public is still 
> troubling, because if the class with the public ITD field is put in a jar on the > classpath of a consuming project, the consuming project would see the public 
> field, unlike what you see in the providing project.  That strikes me as 
> inconsistent.

Yes, it is inconsistent. Partly caused by you demanding I make the generated name non mangled :)  Previously a private ITD manifested in a mangled field name so it wouldn't interact adversely with other fields already on the type and, if using appropriate tools, anyone content assisting against that type wouldn't be shown fields prefixed ajc$interField because they were implementation details.

All these problems come down to the fact that AspectJ had an original design philosophy but that isn't how users are thinking about these constructs. These days no-one really cares about privacy with respect to the crosscutting concern.

> It seems as though there's room here for more access levels than private

Yes, there are almost two privacy levels to specify, for the target and the aspect.

/////////////////// MANUALLY CODED GETTER & SETTER?	
	public String I.name() {
		return this.name;
	}
	
	public void I.name(String s){
		this.name = s;
	}

Yes, that is what I meant. Is that sufficient for you for now as a workaround? (I know it is not ideal)
Comment 4 Matthew Adams CLA 2013-10-02 17:52:31 EDT
My workaround is to just use public as the modifier for ITD fields.

Let's call this one closed as WONTFIX.
Comment 5 Andrew Clement CLA 2013-10-02 18:06:55 EDT
WONTFIX is a bit extreme, this area clearly needs more looking at. It is possible if proper traits were there and we were not trying to force ITDs to behave as traits we might be having more success.

If we do follow the user expectations rather than the strict AspectJ original design we can certainly produce simpler woven code (that executes faster).
Comment 6 Matthew Adams CLA 2013-10-02 18:12:34 EDT
(In reply to Andrew Clement from comment #5)
> WONTFIX is a bit extreme, this area clearly needs more looking at. It is
> possible if proper traits were there and we were not trying to force ITDs to
> behave as traits we might be having more success.
> 
> If we do follow the user expectations rather than the strict AspectJ
> original design we can certainly produce simpler woven code (that executes
> faster).

I like the sound of that...  :)