[metadata] Fields whose types are gparams with a reference type constraint aren't blittlable. (mono/mono#15761)
* [metadata] Fields whose types are gparams with a reference type constraint
aren't blittlable.
Don't try to layout the field to find out if it's blittable.
For gshared gparams, follow the blittability of the constraint.
Fixes certain recursive examples.
```
using System;
namespace TestRecursiveType
{
class Program
{
static void Main(string[] args)
{
SubClass subC = new SubClass();
Console.WriteLine(subC.GetTest());
}
}
public struct ValueTest<U>
{
// When U is instantiated with T, from BaseClass, we know it'll be a
// reference field, so we know the instantiation ValueTest<T> won't
// be blittable.
public readonly U value;
}
public abstract class BaseClass<T> where T : BaseClass<T>
{
public ValueTest<T> valueTest = default(ValueTest<T>);
}
public class SubClass : BaseClass<SubClass>
{
private String test = "test";
public string GetTest()
{
return test;
}
}
}
```
Fixes https://github.com/mono/mono/issues/15760
---
The failure is happening when we are doing mono_class_setup_fields ("BaseClass<T>") which needs to decide for each field whether it is blittable or not. So therefore we are trying to decide if ValueTest<T> (that is: the ValueTest<U> field inside BaseClass<T>) is blittable or not.
So we instantiate U with T.
Now to decide whether VaueTest<T> is blittable or not, we look at every field.
So then we look at T value.
To decide if T is blittable we first check if it's a reference type.
That check is currently inadequate for generic parameters - what the PR adds is the ability to see if theres a T : class constraint or a T : C constraint - where C is some class. As soon as we know that T's constraint will force it to be a reference type we can definitely say that T won't be blittable without having to initialize C, at all.
Previously, Mono would see that T is some kind of type for which it couldn't definitively decide that it's a reference type and it would call: mono_class_setup_fields (field_class) which would then try to setup the fields of the parent class BaseClass<T>. And that would hit the recursion check.
Commit migrated from https://github.com/mono/mono/commit/
04517d3a3955c5a4a899d88c4af7987b2b277101