This patch merged the functionality from ObjCGenericsChecker into DynamicTypePropagation checker.
Note that the Generics Checker can still be turned on or off individually but this only affects whether diagnostics are generated or not.
There is no intended functional change in this patch.
Rationale
This is a refactoring that makes some collaboration between the ObjCGenericsChecker and DynamicTypePropagation checker possible.
The final goal (which will be achieved by some followup patches) is to use the reasoning of ObjCGenericsChecker about generics to infer dynamic type for objects.
Lets consider the following scenario:
id object = arrayOfStrings.firstObject;
Here the DynamicTypePropagation checker can not infer any dynamic type information because the static type of the arrayOfStrings.firstObject expression is id when arrayOfStrings is not annotated. However the generics checker might be able to infer an upper bound (NSString *) for the same expression from the usage of the symbol.
In a follow up patch when the DynamicTypePropagation checker fails to infer the dynamic type for an object, we would fall back to the inference of the generics checker, because it may have additional information.
Impact
When an exact type is inferred as a dynamic type (this happens when the allocation was visible by the analyzer), method calls on that object will be "devirtualized" (inlined).
When the allocation is not visible but an upper bound can be inferred, there will be a path split on method calls. On one path the method will be inlined (when a body is available) on the other, there will be no inlining.
There are some heuristic cases, where an upper bound is treated as an exact type.
The expected effect of the follow up patch is that, upper bound can be inferred more frequently. Due to cross translation unit limits, this might not change the inlining behavior significantly. However there are other advantages. Utilizing this dynamic type information, a generic type checker could be implemented trivially which could catch errors like:
id object = myNSNumber;
NSString *myString = object;
Why not keep the Generics checker and the dynamic type propagation as completely separate checks?
One of the problem is that, right now both checkers infer type information from casts. In order to be able to fallback to the type inference of Generics checker when the type inference of dynamic type propagation failed, the Generics checker should assume that the dynamic type propagation is done already by the time its callback is invoked. Since there is no way to specify ordering between the checkers right now, the only way to do it correctly is to merge two checks into one checker.
What do you think?