Created attachment 24232 [details]
Description of Problem:
In the constraint of the parameter T2 it is written that it must be subclass of Foo<Τ3>. Therefore, the Type.IsAssignableFrom must return true for T2 and Foo<T3>. But it returns false. But if you comment out the tenth line ("where T1 : T2"), then the function returns true. In MS.NET Type.IsAssignableFrom always returns true for T2 and Foo<T3>.
Steps to reproduce the problem:
1. Compile "test.cs"
2. Run "test.exe"
"False" in console.
"True" in console.
How often does this happen?
Thank you very much for the very reproductible test case. I could reproduce as expected on Mono 188.8.131.52 (2017-04/ef39d08) as well as on .NET.
I can reproduce with Mono 184.108.40.206 (2017-06/6425f06)
I think this is happening because make_generic_param_class () calls mono_class_setup_supertypes (). make_generic_param_class () is ultimately called from mono_class_from_mono_type () which is, in turn, called on "T2" when loading the constraint "where T1 : T2". We load constraints in the order of the generic parameter to which they apply (ie "where T1 : C1" before "where T2 : C2"). For example if the reproduction example is modified to
class GenericClass <T1, T2, T3, T4> where T4 : T2 where T2 : Foo<T3>
then typeof(Foo<T3>).IsAssignableFrom(typeof(T4)) does return True as expected.
It's not totally clear to me yet if I can just delay setting up the supertypes array in make_generic_param_class or if we need to be a lot more careful about creating a generic param MonoClass from a MonoType as a side-effect of loading the constraints.
The simple fix doesn't work: just processing the constraints in metadata.c get_constraints() is enough to cause the later type variables to be created before they've had their constraints attached.
I'm now working on two-phase creation of MonoClass-es for type variables: (1) create barebones typevariables; (2) create the constraints; (3) attach the constraints to the type variables and finish initialization.
For the record, we also get typeof (Foo<T3>).IsAssignableFrom(typeof(T1)) wrong, and for a new (but related) reason:
- our code that computes the parent class of a generic param (in mono_class_from_generic_parameter_internal ()) just checks whether the first constraint is not an interface and makes that the parent object, otherwise System.Object is the parent. (This is already wrong an naive, if a gparam has multiple constraints, but even so...)
- MONO_CLASS_IS_INTERFACE() assumes that any type variable is an interface.
- T2 cannot be an interface because it derives from a class (Foo<T3>) that is definitely not an interface.
To get this right we need to set MonoClass:parent to the (at most 1) MonoClass that *must* be a non-interface class. And we must know that gparams like T2 that derive from a class can never be interfaces.
Fixed on mono master https://github.com/mono/mono/commit/fa62f916a3c02931eb6d5f72e07b9aa37b477171
Fixed on mono 2017-08 https://github.com/mono/mono/commit/cfe2428963efce3b5130e9ce70d8b2f0a6410872
Notice (2018-05-21): bugzilla.xamarin.com will be
switching to read-only mode on Thursday, 2018-05-25 22:00 UTC.
Please join us on
Visual Studio Developer Community and
GitHub to continue tracking
issues. Bugzilla will remain available for reference in read-only mode.
We will continue to work on open Bugzilla bugs and copy them to the new
locations as needed for follow-up. The See Also field
on each Bugzilla bug will be updated with a link to its new location
After Bugzilla is read-only, if you have new information to add for a
bug that does not yet have a matching issue on Developer Community or
GitHub, you can create a follow-up issue in the new location. Copy and
paste the title and description from this bug, and then add your new
details. You can get a pre-formatted version of the title and
In special cases you might also want the comments:
Our sincere thanks to everyone who has contributed on this bug tracker
over the years. Thanks also for your understanding as we make these
adjustments and improvements for the future.