[Checkers] Method Type Parameters

Mahmood Ali mahmood at MIT.EDU
Sat Mar 15 01:37:21 EDT 2008


Hi guys,

I will be working on resolving type parameters next.  I am having some  
trouble designing this, so I would like to get your input on it.

Consider us having
static <T> T get(T t1, T t2) { return null; }

__THE PROBLEM__
Resolving a type variable in a method invocation may require a type  
inference if the used does not supply/declare them (e.g.  
Collections.<Date>emptySet()).  From my understanding of the JLS Sec.  
15.12.2, there are three stages:

1. Resolving type variables based on type parameters: With a first  
order approximation, we simply find the least upper bound on all the  
uses of the type parameters.  So if I call get(date, integer), I will  
get lub(date, integer) as a return type. That doesn't always work, but  
Javac provide you with this information.

2. Resolving type variables based on their assignment context.  If a  
type variable is not resolved based on parameters and the return type  
is used in an assignment (or pseudo-assignment), we match the type  
variable to the desired type, so the type of Collections.emptySet() is  
Set<Integer> when it is assigned to Set<Integer> variable or Set<Date>  
when it's a assigned to Set<Date> variable.  In other words, the  
return type is not only on the method invocation tree only, but also  
on the context that it is in.

3. Any yet unresolved type variables are specified as  
java.lang.Object. So Collections.emptySet() in a non-assignment  
context is resolved to Set<Object>

__MY APPROACH__
It is relatively easy to find the un-annotated type of the type  
variable, simply by using the Javac Types API, so we merely need to  
find the right annotations for the type.

STEP ONE: BASED ON TYPE PARAMETERS:
Once we know how the type variable is resolved, we can simply find all  
the uses of the parameters and find the lub in a similar fashion to  
conditional expression type inference.  I would simply refactor the  
code for inferring conditional expressions to return to me the correct  
type.

STEP TWO: BASED ON CONTEXT: HARDEST PART
We will have to figure out what it gets assigned to, if the type  
variable is unbounded.  One way of doing it is to use a TreePath and  
climb the tree to find whether it is an assignment context or not, and  
what the required type is.  Please note that this should be recursive,  
as the assignment could actually be to a parameter in a method  
invocation that requires type inference (e.g. get(Integer, get(Date,  
String))).

STEP THREE: Assign to Object (or actually to the supertype of T if one  
is specified):
Whatever left from the second step gets assigned of Object.   
Unfortunately, that means that actually need to perform step two  
before resolving Object, as it is not sufficient to see that the Javac  
Type is Object.  Consider the following case
Set<@Null Object> set = Collections.emptySet();
Collections.emptySet();

The second statement will get Set<Object> due to unresolved E, while  
the first one is assigned to Object due to step two and should  
actually be @Null Object.

However, I don't know if will ever need to infere the type of return  
type of a method invocation that are not part of an assignment context  
(since otherwise, we won't need to type check the return type anyway).

__Engineering Techniques__
We can do the first type of inference and postpone the second one for  
later, and simply require the users to explicitly set the type variable.

What do you guys thing?



More information about the checkers mailing list