| Summary: | binding type pattern matching sometimes misses decps affecting generic types | ||
|---|---|---|---|
| Product: | [Tools] AspectJ | Reporter: | Andrew Clement <aclement> |
| Component: | Compiler | Assignee: | aspectj inbox <aspectj-inbox> |
| Status: | RESOLVED FIXED | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | ||
| Version: | DEVELOPMENT | ||
| Target Milestone: | 1.6.12 | ||
| Hardware: | PC | ||
| OS: | Mac OS X - Carbon (unsup.) | ||
| Whiteboard: | |||
I ended up making two key changes: 1) ReferenceType.getDeclaredInterfaces() now recognizes if it is being called on a raw type and grabs the interfaces from the generic type. 2) Each referencetype caches the result of the question 'getDeclaredInterfaces()' this means when a new interface is added to the generic type, the raw and any parameterized forms need their caches clearing. The set of 'derivativetypes' is stored in a generic type and should point to the raw form and any parameterizations. The raw form was not being tracked properly, so I fixed that and ensured when the parents are modified that the derivative types have their caches cleared. I only fixed the interface case, I bet there is something similar for superclasses but that is much much rarer, ignoring for now. Interestingly it isn't so easy to construct a testcase. In many scenarios when the isAssignable call fails we fall through to an isCoerceable call and that was passing. In order for that to fail you need a sophisticated combination of generics (declare parents and itds involved), which then cause the method checking at the end of the coerceable check to fail. fixed |
Uncovered by the spring-data project. Here: @Foo class Clazz {} @Foo class OtherClass<T> {} interface Marker {} aspect X { declare parents: (@Foo *) implements Marker; before(Marker m): this(m) { } } the advice can miss applying to OtherClass because the matching for this() is done against the raw type when the affect of the decp is stored on the generic form.