Bug 121805 - Incorrect ambiguous binding of parameter(s) error
Summary: Incorrect ambiguous binding of parameter(s) error
Status: REOPENED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: DEVELOPMENT   Edit
Hardware: PC Windows XP
: P3 normal with 1 vote (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-12-21 20:13 EST by Ramnivas Laddad CLA
Modified: 2018-01-21 09:46 EST (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ramnivas Laddad CLA 2005-12-21 20:13:13 EST
I tried the project reported originally as a part of bug #118149 with the latest release (AspectJ 5). While the compiler doesn't crash anymore, I am getting the following error:

ambiguous binding of parameter(s) entity across '||' in pointcut UIEntityManagementAspect.aj

Here are the aspects:
public abstract aspect AbstractEntityManagementAspect {
    public abstract pointcut entityAccessor(CommonEntity entity);

    ... advice to the pointcut...
}

public aspect UIEntityManagementAspect extends AbstractEntityManagementAspect
{
    public pointcut entityAccessor1(CommonEntity entity)
        : (execution(* CommonEntity+.add*(CommonEntity+))
           || (execution(* CommonEntity+.remove*(CommonEntity+))))
          && within(CommonEntity+)
          && args(entity) && if(entity != null);

    public pointcut entityAccessor2(CommonEntity entity)
        : execution(ManageEntity.new(CommonEntity+, ..)) 
          && within(ManageEntity)
          && args(entity, ..) 
          && if(entity != null);

    public pointcut entityAccessor(CommonEntity entity)
        : entityAccessor1(entity) || entityAccessor2(entity);

    declare parents: Entity implements CommonEntity;
}

Since entityAccessor1() and entityAccessor2() do not share a selected 
join point, the collected context should not be ambiguous. This bug is 
still preventing me from implmenting an elegant solution (without 
having to repeat the advice) reported as a part of bug #118149.
Comment 1 Adrian Colyer CLA 2005-12-22 04:24:41 EST
The place to fix this is in BcelWeaver.couldEverMatchSameJoinPoints(Pointcut,Pointcut)

but here be dragons... it's very easily to return false from this test in too many cases (ie. you think they could never match the same join points, but there's a case you've forgotten). 

A careful improvement to this algorithm would reduce the number of time we report ambiguous binding when we strictly didn't need to.
Comment 2 Andrew Clement CLA 2006-07-11 03:53:45 EDT
Well I was going to look at this ... so I wrote this program:

class CommonEntity {

  public void add(CommonEntity ce) {}
  public void remove(CommonEntity ce) {}

}

class ManageEntity {

  ManageEntity(CommonEntity ce) {
  }
}


abstract aspect Y {
  abstract pointcut entityAccessor(CommonEntity entity);
  before(CommonEntity entity): entityAccessor(entity) {}
}


aspect X extends Y {

    public pointcut entityAccessor1(CommonEntity entity)
        : (execution(* CommonEntity+.add*(CommonEntity+))
           || (execution(* CommonEntity+.remove*(CommonEntity+))))
          && within(CommonEntity+)
          && args(entity) && if(entity != null);

    public pointcut entityAccessor2(CommonEntity entity)
        : execution(ManageEntity.new(CommonEntity+, ..))
          && within(ManageEntity)
          && args(entity, ..)
          && if(entity != null);

    public pointcut entityAccessor(CommonEntity entity)
        : entityAccessor1(entity) || entityAccessor2(entity);


}


it only fails at AspectJ 1.5.0:

Complex.java:36 [error] ambiguous binding of parameter(s) entity across '||' in pointcut
: entityAccessor1(entity) || entityAccessor2(entity);
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

at either AspectJ 1.5.1a or AspectJ1.5.2 - it compiles fine (who knows what accidentally fixed it... possibly the fixes in pointcut rewriting...)

>ajc Complex.java -showWeaveInfo
Join point 'constructor-execution(void ManageEntity.<init>(CommonEntity))' in Type 'ManageEntity' (Complex.java:10) advised by before advice from 'X' (Complex.java:17) [with runtime test]

Join point 'method-execution(void CommonEntity.add(CommonEntity))' in Type 'CommonEntity' (Complex.java:3) advised by before advice from 'X' (Complex.java:17) [with runtime test]

Join point 'method-execution(void CommonEntity.remove(CommonEntity))' in Type 'CommonEntity' (Complex.java:4) advised by before advice from 'X' (Complex.java:17) [with runtime test]


please reopen if you still have similar problems Ramnivas
Comment 3 Andrew Clement CLA 2006-07-11 04:41:21 EDT
not sure what on earth is going on now ... this is one of those cases where when run as a set of tests (Ajc153Tests) it fails, when run standalone it works... so reopening this for now until we get to the bottom of the wierdness.
Comment 4 Andrew Clement CLA 2007-10-23 11:57:22 EDT
is this still misbehaving?
Comment 5 Ramnivas Laddad CLA 2009-06-26 12:48:54 EDT
(In reply to comment #4)
> is this still misbehaving?
> 

Looks like it is still misbehaving, per http://www.nabble.com/Re:-Match-all-method-calls-with-a-specific-parameter--type-at-any-position-p24222906.html 
Comment 6 Andrew Clement CLA 2009-06-26 12:54:40 EDT
I believe this may be a case of recording the problem against something other than the current unit being processed - that is why it doesn't always get correctly reported and appears to come and go.
Comment 7 Harish Kommaraju CLA 2011-11-01 10:32:38 EDT
Any updates on this bug? I am still facing this issue in eclipse indigo using aspectj
Comment 8 Andrew Clement CLA 2011-11-01 16:21:50 EDT
I'd recommend splitting up your pointcut into pieces to workaround it.
Comment 9 Harish Kommaraju CLA 2011-11-01 23:52:15 EDT
Splitting up pointcut is still not working when I use a single advice and have something like (pointcut1(m) || pointcut2(m))

So only option I had is use to use two different advices altogether and have both the advices call another common method.

Would appreciate if anyone can provide a workaround using single advice only
Comment 10 Andrew Clement CLA 2013-06-24 11:02:56 EDT
unsetting the target field which is currently set for something already released
Comment 11 Pavel Yushkovskiy CLA 2014-01-18 06:20:26 EST
I've found that it is still actual for version 1.7.4.

Sample code is:

public privileged aspect TestAspect {

  pointcut checkMethodBecauseOfClass(TestAnn access):
      execution(* *(..)) && @within(access) && if(in(access, ElementType.METHOD));

  pointcut checkMethod(TestAnn access):
      execution(@TestAnn * *.*(..)) && @annotation(access);

  before(@NotNull TestAnn ann): checkMethodBecauseOfClass(ann) || checkMethod(ann) {
    final boolean needStack = ann.stackTrace();
    logMethod(thisJoinPoint, needStack);
  }

......

}

And the compiller's error is:

ajc: ambiguous binding of parameter(s) ann across '||' in pointcut
Comment 12 Sebastien Tardif CLA 2018-01-21 09:46:03 EST
Trying to workaround the issues I tried something like:

(cflow(update(session1)) || cflow(delete(session2)))

Then in the advice body I just do: 
Session session = ObjectUtils.firstNonNull(session1,session2);

However, AspectJ is still complaining with "Inconsistent binding".

At the end of the day, the developer knows better, how can I tell AspectJ to trust my judgment?