Bug 113257 - Incremental Compilation Bug: parameter not bound with no parameter
Summary: Incremental Compilation Bug: parameter not bound with no parameter
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: DEVELOPMENT   Edit
Hardware: PC Windows XP
: P2 normal (vote)
Target Milestone: 1.5.0RC1   Edit
Assignee: Andrew Clement CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-10-20 13:00 EDT by Ron Bodkin CLA
Modified: 2005-12-14 06:37 EST (History)
0 users

See Also:


Attachments
zip containing testcase and dev work (2.88 KB, application/zip)
2005-12-13 12:23 EST, Helen Beeken CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ron Bodkin CLA 2005-10-20 13:00:15 EDT
I keep getting an incremental compilation error on this pointcut when I save 
other files (in AJDT):

    public pointcut scope() :
        within(DoMonitorErrors+) ||
        ((within(pkg1..*)|| within(pkg2..*) || within(pkg3..*)) && 
        !within(pkg1.monitoring..*));

It is used as follows:
    after() throwing (Throwable t) : publicMethodExec() && scope() && 
adviceEnabled() {
...
        recordThrowable(t, thisJoinPointStaticPart, 
thisEnclosingJoinPointStaticPart);
    }

    before(Throwable t) : handler(*) && args(t) && scope() && adviceEnabled() {
...
        recordThrowable(t, thisJoinPointStaticPart, 
thisEnclosingJoinPointStaticPart);
    }

The resulting incremental compilation produces an error which requires a full 
rebuild to clear:
	the parameter t is not bound in [all branches of] pointcut
	ErrorMonitor.aj	aspectjSupport/src/pkg1/monitoring	line 58
Comment 1 Andrew Clement CLA 2005-10-21 02:53:30 EDT
Hmmm ... i fixed a bug yesterday to do with messages like this "the parameter t
is not bound in [all branches of] pointcut" - however it wasn't an incremental
case that was causing it.
Comment 2 Andrew Clement CLA 2005-11-11 07:15:02 EST
Sorry to do this to you Ron - is this easily recreatable on a recent AJDT -
firstly I'd like to see if the change I mentioned in the previous comment fixed
it, but I'd also like to see what you get if you put '-Xdev:Pinpoint' in the
'non-standard compiler options' setting in AJDT, that should put out some kind
of context about what is going on with the message.  Ideally I'd love to turn on
the pointcut rewriter for your environment and see what the rewriter is
producing but that isnt command line or ajdt configurable :(

I've tried taking your small snippets and making a program, but (sigh) it works
for me.  Or you could email me the project if it doesnt have too many
dependencies and you dont mind me seeing it?

Comment 3 Ron Bodkin CLA 2005-11-14 09:15:38 EST
Because of bug 113368 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=113368) - 
see the 2nd comment relating to incremental compilation I am getting NPE's on 
all incremental compiles on the project so I can't test easily. I tried 
commented out the line I suspected but there are other if pointcuts and at 
least one is (still?) causing the NPE...

So I guess 113368 is blocking this one...
Comment 4 Andrew Clement CLA 2005-11-24 10:49:12 EST
Ron - with 113368 now resolved - can you try this one again?
Comment 5 Andrew Clement CLA 2005-11-28 08:01:28 EST
*bump* any chance of reconfirming this failure Ron?
Comment 6 Ron Bodkin CLA 2005-11-28 13:40:06 EST
I downloaded the latest AJDT build and it looks like this problem is solved. I'll reopen if I see it again...
Comment 7 Ron Bodkin CLA 2005-12-07 14:22:35 EST
I just saw this bug again in AJDT 1.3.0.20051207063004 (the latest dev build) today. I was editing one aspect and the resulting incremental build choked when this aspect fired (the ITD DoMonitorErrors is affecting the other, incrementally compiled, aspect).
Comment 8 Helen Beeken CLA 2005-12-12 06:02:27 EST
Hi Ron - I'm trying to reproduce the problem you're seeing and have so far been unsuccessful....would you be able to attach the ErrorMonitor aspect and the aspect you were editing when you last saw the problem? 
Comment 9 Andrew Clement CLA 2005-12-12 09:18:36 EST
In addition to Helens question, can I ask if you have multiple aspects in a hierarchy here Ron?  Where is adviceEnabled() defined? In a super abstract aspect?
Comment 10 Ron Bodkin CLA 2005-12-12 13:09:45 EST
Yes there are multiple aspects. We have 

public aspect ErrorMonitor extends AbstractMonitorAspect {
...
    protected pointcut isAdviceEnabled() : if(ErrorMonitor.aspectOf().isAdviceEnabled()) ;  

}

And in 
public abstract aspect AbstractMonitorAspect {
...
	protected pointcut scope() : within(com.myco..*);

	protected pointcut adviceEnabled() : isAdviceEnabled() && scope();

	protected abstract pointcut isAdviceEnabled();

	public boolean isAdviceEnabled() {
		return enabled;
	}

	public void setAdviceEnabled(boolean enabled) {
		this.enabled = enabled;
	}
}

If this lead doesn't help you find the bug, I will try to narrow it down to a small test case that is easy to share.
Comment 11 Helen Beeken CLA 2005-12-13 09:58:07 EST
Ron - With the extra info you've provided, we've been able to recreate the problem you're seeing. All that's required is the following aspect:


package pkg1.monitoring;

public aspect ErrorMonitoring {
	
    pointcut adviceEnabled() : isAdviceEnabled() && scope();	
    pointcut isAdviceEnabled() : if(true);
	
    pointcut scope() : within(DoMonitorErrors+) || !within(pkg1.monitoring..*);

    before(Throwable t) : args(t) && scope() && adviceEnabled() {}
	
}

and an empty class "DoMonitorErrors.java". A scenario which causes the error is creating a new aspect.
Comment 12 Helen Beeken CLA 2005-12-13 12:23:34 EST
Created attachment 31654 [details]
zip containing testcase and dev work

This zip file contains two patches:

* pr113257-tests-patch.txt: apply to the tests project - contains testcase which shows failure
* pr113257-weaver-patch.txt: apply to the weaver project - contains dev work done today on this bug.
Comment 13 Andrew Clement CLA 2005-12-14 03:42:05 EST
Helen and I have spent a good deal of time hacking on this bug.  It is the pointcut rewriter.  During the first compile a big nasty pointcut is rewritten in DNF - then on the incremental compile we rewrite it again into DNF - this produces a broken result because the method pullUpDisjunctions doesnt cope with:

(A || B) && (C || D)

and if its ignored then the result isn't DNF.  I had a quick look around for what that looks like when the ||s are moved up - but couldn't find much, so I dug out my boolean algebra knowledge ...

truth table for ABCD and the above expression:

ABCD    A|B  C|D  (A|B)&(C|D)
0000     0    0        0
0001     0    1        0
0010     0    1        0
0011     0    1        0
0100     1    0        0
0101     1    1        1
0110     1    1        1
0111     1    1        1
1000     1    0        0
1001     1    1        1
1010     1    1        1
1011     1    1        1
1100     1    0        0
1101     1    1        1
1110     1    1        1
1111     1    1        1


So, all the 1's in the last column are:  
 (lower case = NOT, + = OR, letters adjacent to each other = AND)
   aBcD+aBCd+aBCD+AbcD+AbCd+AbCD+ABcD+ABCd+ABCD
and reducing that gives:

=> aBcD+aBCd+aBCD+AbcD+AbCd+AbCD+ABcD+ABC
=> aBcD+aBC+AbcD+AbCd+AbCD+ABcD+ABC
=> aBcD+aBC+AbcD+AbC+ABcD+ABC
=> aBcD+BC+AbcD+AbC+ABcD
=> aBcD+BC+AcD+AbC
=> aBcD+BC+AcD+AbC

or in english (?!?)

(¬A && B && ¬C && D) || (B && C) || (A && ¬C && D) || (A && ¬B && C)

truth table for that beast:

ABCD  BC   aBcD    AcD    AbC (| of those)
0000   0     0      0      0      0
0001   0     0      0      0      0
0010   0     0      0      0      0
0011   0     0      0      0      0
0100   0     0      0      0      0
0101   0     1      0      0      1
0110   1     0      0      0      1
0111   1     0      0      0      1
1000   0     0      0      0      0
1001   0     0      1      0      1
1010   0     0      0      1      1
1011   0     0      0      1      1
1100   0     0      0      0      0
1101   0     0      1      0      1
1110   1     0      0      0      1
1111   1     0      0      0      1

which is the same answer.

So ... I implemented that.  However - DNFs aren't unique and constantly rewriting pcuts on every build is painful.  The above change to cope with (A||B)&&(C||D) introduces new NOTs into the pcut which the 'distributingNot' mechanism (part of becoming DNF) will attempt to move around on the next rewrite - when there is no need.  What is better is for us to recognize something is in DNF and don't mess with it.  So I implemented that too.  We still simplifyAnds and sortOrs - I didn't make that conditional on whether we are in DNF because some pcuts are in DNF but still need simplying or sorting.

phew - fix checked in.

Anyway, the fix is in - behaves for this problem and every other testcase in the suite.
Comment 14 Andrew Clement CLA 2005-12-14 04:19:27 EST
fix available.
Comment 15 Andrew Clement CLA 2005-12-14 06:37:30 EST
Hmmmmm .. trusty old spacewar didn't like my change - and then Mr Colyer pointed out an equivalent, much nicer rewrite:

(A || B) && (C || D)

=>

(A && C) || (A && D) || (B && C) || (B && D)

(DOH!)

which is also likely to give us more stable rewrites.  Spacewar even likes it :)
(Although I'm not sure why spacewar didn't like mine - must be an invalid assumption I'm making about something...)

i need a holiday