Strange Matrix Reflection on iOS

So I’m hitting a hit compilation error on iOS that I don’t quite understand. The function being called:

public PropertyMetadata ConstructPropertyMetadata(Type propertyType, string name, string category, string 
description, long propertyId, bool isSerialized, bool canHaveTemplate, object defaultValue)
{
	Type metadataGenericType = typeof(PropertyMetadata<>).MakeGenericType(propertyType);
	PropertyMetadata retVal = (PropertyMetadata)Activator.CreateInstance(
		metadataGenericType,
		new object[] { name, category, description, propertyId,
			isSerialized, canHaveTemplate, defaultValue });
	return retVal;
}

When called on iOS with most types it works fine, however when called with Matrix as the type (basically typeof(Matrix), “”, “”, “”, 1, true, true, Matrix.Identity) it fails with the following error:

Attempting to JIT compile method ‘(wrapper runtime-invoke) :runtime_invoke_void__this___object_object_object_long_byte_byte_Matrix (object,intptr,intptr,intptr)’ while running in aot-only mode. See https://developer.xamarin.com/guides/ios/advanced_topics/limitations/ for more information.
(System.ExecutionEngineException)

I figured it might have something to do with Matrix being a struct, but Vector2/Vector3/Vector4 look very similar and are successful when calling this method with their types. My only thought is that Matrix might be getting translated to something weird under the covers, and was wondering if anyone knew anything about this. Also I have linking off, and the constructor for PropertyMetadata with a type of Matrix is explicitly called in the code, so it should be compiling a definition for it.

PropertyMetadata looks something like this:

public abstract class PropertyMetadata
{
    public string Name { get; private set; }
    public string Category { get; private set; }
    public string Description { get; private set; }
    public long PropertyId { get; private set; }
    public bool IsSerialized { get; private set; }
    public bool CanHaveTemplate { get; private set; }
    public object DefaultValue { get; protected set; }

    protected PropertyMetadata(
        string name, string category, string description, long propertyId, bool isSerialized,
        bool canHaveTemplate, object defaultValue)
    {
        Name = name;
        Category = category;
        Description = description;
        PropertyId = propertyId;
        IsSerialized = isSerialized;
        CanHaveTemplate = canHaveTemplate;
        DefaultValue = defaultValue;
    }
}

public class PropertyMetadata<T> : PropertyMetadata
{
    public T DefaultValueTyped { get { return (T)DefaultValue; } set { DefaultValue = value; } }

    public PropertyMetadata(string name, string category, string description, 
        long propertyId, bool isSerialized, bool canHaveTemplate, T defaultValue)
        : base(name, category, description, propertyId, isSerialized, canHaveTemplate, defaultValue)
    {
    
    }

    public PropertyMetadata(string name, string category, string description,
        long propertyId, bool isSerialized, bool canHaveTemplate, object defaultValue)
        : this(name, category, description, propertyId, isSerialized, canHaveTemplate, (T)defaultValue)
    {

    }
}

Does anyone have any thoughts? I figured I’d post here before heading over to the Xamarin forums.

No other code explicitly calls that constructor, so the code was stripped by the linker to save space. You are calling the constructor by reflection, and the linker cannot determine that the constructor is used.

That’s what I thought too, except a) Linking is turned off so that shouldn’t happen, and b) I added the following lines in the code to no effect:

        PropertyMetadata<Matrix> m;
        m = new PropertyMetadata<Matrix>("m", "", "", 2, false, true, (object)Matrix.Identity);
        m = new PropertyMetadata<Matrix>("m", "", "", 2, false, true, Matrix.Identity);
        Matrix m1 = new Matrix(Vector4.One, Vector4.One, Vector4.One, Vector4.One);
        m1 = new Matrix(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
        m1 = Matrix.Identity;
        
        PropertyMetadata retVal1 = (PropertyMetadata)Activator.CreateInstance(
            typeof(PropertyMetadata<Vector4>),
            new object[] { "m2", "", "", 2,
                true, true, Vector4.One });
        PropertyMetadata retVal = (PropertyMetadata)Activator.CreateInstance(
            typeof(PropertyMetadata<Matrix>),
            new object[] { "m", "", "", 1,
                true, true, Matrix.Identity });

The call with Vector4 passes, the one with Matrix still fails (even though there are no explicity calls to PropertyMetadata anywhere).

As an update, I used reflection to look at both PropertyMetadata and PropertyMetadata at runtime, and they both have all of their constructors. Looking at the error again:

Attempting to JIT compile method ‘(wrapper runtime-invoke) :runtime_invoke_void__this___object_object_object_long_byte_byte_Matrix (object,intptr,intptr,intptr)’ while running in aot-only mode. See https://developer.xamarin.com/guides/ios/advanced_topics/limitations/ for more information.

The method it’s trying to JIT compile could relate the constructor of PropertyMetadata, but I’m not sure what the last bit (object, intptr, intptr, intrptr) is trying to do. I’m probably going to take this over to the xamarin forums at this point.