Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Understanding generic types in args(..) construction

Hi Eric,

first of all, thanks for your fast response.
Please, see the comments inline

*However* no List<Y> is ever subtype of a List<X> for any two
different concrete types X and Y, regardless of whether Y is a subtype
of X! As a consequence, also List<Integer> cannot possibly be an
ArrayList<Number>.

For Java I 100% agree with you.
For AspectJ what I've seen so far for args(..) and after(..) returning(..) constructions is that it does not follow the Java subtyping for generic types. Actually it would be a lot easer to understand if they had used the same behavior, but...
Note that the same issue happens also for <? extends Number>.

What surprises me is the fact that the first advice in BC matches.
Actually this should not match either, I believe, because also a
List<Integer> can never be a List<Number>. I am not sure... could this
have to do with type erasure?

If args(..) constructions followed the Java subtyping, again, I would agree 100% with you.
But according to some experiments I did, unfortunately it does not work at the same way (may be a bug, I don't know).

About the erasure..
In the byte code on the signature attribute, the Java compiler stores the generic information. So it is possible to the AspectJ compiler to check the right generic type to match.
   // Method descriptor #15 (Ljava/util/List;)V
   // Signature: (Ljava/util/List<Ljava/lang/Integer;>;)V
   // Stack: 4, Locals: 3
   void m(java.util.List arg0);

For me it seems to be understandable why they have decided to implement the args(..) stuff in that way (although I don't like it). If the method m receives a List of integers in the Java code, it will cause no runtime error (after type erasure) into the advice when an integer be assign to number variable. but, what does not make sense for me is: When AspectJ uses a runtime test to check if it is an ArrayList the matching is totally different. I've shown only one example, but there are others cases where it change the behavior because of the runtime test. Does not make sense.

I need to understand if this design were planned by the AspectJ developer or if it is a bug. If it were planned, what is the correct semantics for this? how args(..) should work? Shouldn't be better (and a lot easer) if it followed the same Java subtyping?

Thanks a lot,
Fernando Rubbo



Eric

2008/11/1 Fernando Rubbo <fernando.rubbo@xxxxxxxxx>:
> Hi all,
>
> I have a question about args(..) and after(..) returning(..) construction
> semantics when generic types are applied.
> Actually, it is not clear for me how it is working and why it is working
> this way. Let me show an example to help to depict my thoughts.
>
> class C{
>     void m(List<Integer> e){}
> }
>
> aspect AC {
>     void around():execution(* C.*(..)) && args(List<Integer>) {} // Matchs
> C.m
>     void around():execution(* C.*(..)) && args(ArrayList<Integer>) {} //
> Unchecked match C.m - uses rRuntime check
> }
>
> In this simple example, it is easy to notice that both advices will match
> the method C.m. Note that the second one will make a runtime test to check
> if the method caller has passed, as a parameter, an ArrayList object. Since
> actual type parameters are erasured during compile-time, the AspectJ
> compiler just warn the programmer that this is an unchecked match (however,
> it is easy to notice that in this case it will never cause a
> ClassCastException during runtime).
>
> To show my question, take a look on the below aspect:
>
> aspect BC {
>     void around():execution(* C.*(..)) && args(List<Number>) {}  // Matchs
> C.m
>     void around():execution(* C.*(..)) && args(ArrayList<Number>) {} // DOES
> NOT MATCH C.m
> }
>
> This is exactly the same aspect I've shown before, just changing type
> parameter from Integer to Number in both args(..) constructions.
> Note that in BC aspect, the first advice follows the same semantics than the
> AC one, and then, matches  the method C.m. However,  the second advice DOES
> NOT follow the same semantics (that the AC one), and then, DOES NOT MATCH
> C.m AT ALL.
>
> My question is:
> Should not the second advice of BC aspect match the method C.m and use a
> runtime check to verify if the given parameter is an ArrayList? Some one can
> explain to me why the second advice is not matching the method C.m?
>
> The same problem is found in the following using the <? extends Number>
> aspect CC {
>     void around():execution(* C.*(..)) && args(List<? extends Number>) {}
> // Matchs C.m
>     void around():execution(* C.*(..)) && args(ArrayList<? extends Number>)
> {} // DOES NOT MATCH C.m
> }
>
>
> There exists a formal description saying how args(..) and after(..)
> returning (..) must works?
>
>
> Thanks in advance
> Fernando Rubbo
>
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>
>



--
Eric Bodden
Sable Research Group, McGill University, Montréal, Canada
Got an interesting job offer? http://www.bodden.de/hire-me/
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users


Back to the top