[Checkers] Various Notes Part 2: Type System IGJ
Mahmood Ali
mahmood at MIT.EDU
Sun Apr 27 16:50:16 EDT 2008
Hi again,
Here is my second part in the two-part series.
NOTES ABOUT TYPE SYSTEMS AND IGJ IN PARTICULAR
1. Support for Arrays is essential
Personally, I was surprised by the usage of arrays in almost all case
studies I have done yet!
==========================================
2. I don't like AssignsFields nor any annotation like it (is Raw
annotation like it?)
Type Qualifiers on method receivers have multiple meanings:
* Documenting the side effect of the method. (e.g. Mutable, ReadOnly
in IGJ and Javari)
* Restrict the types on which the method can be dispatched (e.g.
Mutable, ReadOnly, and Interned, etc)
Simply put, the type qualifier provides an documented interface for
*using* the method.
AssignsFields does not quite do that. It does not provide an provide
an interface (for an outside class it is treated as Mutable). It
simply means 'constructor can call this method safely', which is an
implementation detail, and it impacts how the method is implemented
and how any overrider method can be implemented!
While the programmer can easily deal with the raised issues, the
solutions are not elegant.
: Lesson learnt: Never annotate an interface method receiver as
AssignsFields! Be careful with abstract classes!
By tomorrow I will have an estimate how AssignsFields is actually
impacting the implementation!
==========================================
3. Projects have different philosophies
In most of the projects, imperative programming style dominated the
style; but with a few there were some functional style too. However
there is no much overlap between them. In many of the case studies I
found almost no @Immutable annotation (like JOlden, JavaCrond), while
others like functor2 (library for functional programming, with lot of
immutable java.util.Map and functional mappers and reducers) is
basically all @Immutable references!
Furthermore, most classes I dealt with did not represent datatypes,
but rather they were "service" classes, like java.io classes,
connectivity classes, diff creation classes, database classes, etc.
Even some datatype classes are actually service classes.
java.sql.ResultSet for example, is a datatype to wrap the result
received from database statement call. Yet it actually represents a
live connection to the database with a close(). In a sense you can
never have an immutable result set, because at any point the creator
statement closes which would close the result set and then all the
sudden the values in ResultSet are not there anymore! Similarly all
the updator methods are updating the back-end database.
I don't necessary consider this as weakness in the IGJ type system,
but rather an indication of a bad design!
==========================================
4. Allowing type argument qualifiers to change covariantly for
collection is not general.
IGJ allows type qualifiers to change covariantly in type arguments for
collections:
@Mutable List<@Mutable Date> <: @ReadOnly List<@ReadOnly Date>
However, this rule is not constitute a general sound rule. Consider
an interface wrapping a unary operation (method with one parameter).
The interface may be defined as:
interface UnaryOp<Return, Param> {
/**
* Apply the unary operator to the parameter
* @return the result of the operation
*/
public Return apply(Param param);
}
In this case, @ReadOnly UnaryOp<@Mutable Date> is not a subtype of
@ReadOnly UnaryOp<@ReadOnly Date>.
I only saw this style of programming in functor2, I haven't tried to
deal with this quite yet.
==========================================
5. We might like to consider allowing '@I' be a method receiver
Motivation: visitor and call-back currently cannot really be immutable.
Problem: Currently, I can either annotate visitor method receivers
with Mutable or ReadOnly. If I annotate them as Mutable, I cannot
have an immutable visitor; and I annotate them as ReadOnly I cannot
have a mutable visitor or I would need to use a lot of hacks using
Mutable and Assignable fields
Proposed solution:
For documentation purposes, '@I' as method receiver within
*interfaces*, means that this method may mutate or not depending on
the immutability of the subclasses; however, it does not say anything
regarding its invocation-ability (is this a word?)
More information about the checkers
mailing list