Few cents about my commits

iOS13 PostFix #1: Generic class arguments and @Block parameters


iOS13 bindings are complete but CocoaTouch related issues keep arriving, part of them about compiler not able to compile one or other class. Most of these issues can be detected just by compiling entire CocoaTouch library as simple smock test to find out outstanding issues. This can be done by force linking its class path with template like this:


This post start series of fixes discovered during compilation of CocoaTouch library.

PostFix #1: Generic class arguments and @Block parameters

Other postfixes:

What is wrong

Issue was detected while compility NSOrderedCollectionDifference.getDifferenceByTransformingChanges. It failed with following exception:

org.robovm.compiler.CompilerException: Unresolved type variable T in parameter 1 of @Block method


All tests were perfromed by modifying ObjCBlockPluginTest.java as it provides quick run experience. For test following block interface will be used:

public interface Block<R, A, B> {
    R run(A a, B b);

Case 1, reproducing CocoaTouch issue

Attempt to use following generic class with block argument…

public static class BlockTest<T> {
    public native void foo(Block<T, Integer, Float> b);

Cause exception:

org.robovm.compiler.CompilerException: Unresolved type variable T in return type of @Block method

(Strange) By the way, such cace is expected in UT testResolveTargetMethodSignatureGenericWithUnresolvedIndirectTypeVariable.


Case 2

Changing a generic class argument name (ONLY!) fixes the exception from case 1.

public static class BlockTest<R> {
    public native void foo(Block<R, Integer, Float> b);

Case 3 – more bugs

Swaping type arguments…

    public static class BlockTest<R, A, B> {
        public native void foo(Block<R, B, A> b);

causes recursion loop and stack overflow exception in result:

java.lang.StackOverflowError at org.robovm.compiler.plugin.objc.ObjCBlockPlugin.resolveMethodType(ObjCBlockPlugin.java:903) at org.robovm.compiler.plugin.objc.ObjCBlockPlugin.resolveMethodType(ObjCBlockPlugin.java:920)

Case 4 – more bugs2

Naming class arguments same to Block arguments casuses in wrong type resolution:

public static class BlockTest<R, B extends Integer> {
    public native void foo(Block<R, B, Float> b);

results in following wrong block:

public interface Block<R, A, B> {
    java.lang.Object run(java.lang.Float a, java.lang.Float b);

Root case

Root case is ObjCBlockPlugin.resolveMethodType method. It take folowing arguments for class BlockTest (Case 1) and Block (Setups):

Type t:                            R
Type[] resolvedArgs:               [T extends Object (TypeVariable), Integer, FLoat]
TypeVariable<?>[] typeParameters:  [R, A, B]

Problem here is that it tries to resolve all TypeVariable types using following scheme:

  • find parameter index in typeParameters by name – 0 in this case;
  • get its value from type parameters: t = typeParameters[index] - T in this case;
  • resolve this value by recursively calling resolveMethodType(t) - fill fail as there is no T in typeParameters: [R, A, B]

And problems here:

  • it can’t resolve any argument parameter, other than in typeParameters (but its wrong by itself);
  • even if name matches – it will pick argument by typeParameters.indexOf(t.name) which will cause resolution of not related type, and wrong result (case 4);
  • several arguments name matche but their position doesn’t match ones in typeParameter this will cause recursion and StackOverflow exception;

The fix


Idea of fix – is not have any TypeVariable in resovedArgs. For this all resolved arguments are initialy being resolved to their java bounds, as result parameter types resolveMethodType will not recursively resolve TypeVariable. But insted if TypeVariable is passed it expects it to be one of typeParameters and return already resoved value from resolvedArgs by it index. Otherwise CompilerException will be thrown.