We have the following set of problems:\n\nArrays implement interfaces that are invariant but behave like covariant.\nThose are IList\`1, ICollection\`1, IEnumerable\`1\n\nArrays of primitive types are type equivalent based on their underlying type.\nThis means int[], uint[] and IntEnum[] are all interchangeable. And so is casting among their interfaces.\nMeaning this is valid: `(IList<IntEnum>)(object)new int[1]\`.\n\nFinally, the way we implement IEnumerator\`1 for arrays forces it to behave just like the other 3 interfaces.\n\nImplementation:\n\nIntroduce MonoClass::is_array_special_interface, set for all the above interfaces. This allow fast checking of the interfaces in question.\n\nmono_class_is_assignable_from now includes the array casting rules.\n\nChange mono_class_interface_offset_with_variance to take arrays into account when looking for a candidate iface.\n\nThe JIT implements casting of those interfaces using the cast with cache wrapper.\n\nFinally, to handle the weird primitive rules, set the cast_class of sbyte, ushort, uint and ulong to their same-size buddies.\nThis makes it easier for the casting code to resolve this problem.\n\nProblems:\n\nCasting performance is terrible, anywhere from 60% to 1000% slower on a micro-benchmark.\n Can be improved by extending our casting wrapper to handle those interfaces (probably would have to give up inlining as they would be huge)\n\nThe code in domain.c is icky, but not sure where to put it otherwise.\n\nIEnumerator could be solved in Array.cs by not forcing it to be magic as well. Meaning the folowing\n\n\`\`\`\nobject array = new int[1];\nvar a = array as IList<int>;\nvar b = array as IList<uint>;\n\na.GetEnumerator().GetType () != b.GetEnumerator().GetType ();\n\`\`\`\n\nThe last line is false today but it's harmless to change it to avoid the casting penalty for such central type.
(manually escaped backticks, for the purposes of displaying properly in this GH issue)
Backticks are needed for code blocks in GH (so it's entirely reasonable to include them), and are also part of the spec for .NET object interfaces, so we tend to hit this quite often.
https://github.com/jenkinsci/ghprb-plugin/blob/master/src/main/java/org/jenkinsci/plugins/ghprb/GhprbTrigger.java#L391-L393 doesn't seem to handle backticks, so the following PR description can cause a build to fail:
We have the following set of problems:\n\nArrays implement interfaces that are invariant but behave like covariant.\nThose are IList\`1, ICollection\`1, IEnumerable\`1\n\nArrays of primitive types are type equivalent based on their underlying type.\nThis means int[], uint[] and IntEnum[] are all interchangeable. And so is casting among their interfaces.\nMeaning this is valid: `(IList<IntEnum>)(object)new int[1]\`.\n\nFinally, the way we implement IEnumerator\`1 for arrays forces it to behave just like the other 3 interfaces.\n\nImplementation:\n\nIntroduce MonoClass::is_array_special_interface, set for all the above interfaces. This allow fast checking of the interfaces in question.\n\nmono_class_is_assignable_from now includes the array casting rules.\n\nChange mono_class_interface_offset_with_variance to take arrays into account when looking for a candidate iface.\n\nThe JIT implements casting of those interfaces using the cast with cache wrapper.\n\nFinally, to handle the weird primitive rules, set the cast_class of sbyte, ushort, uint and ulong to their same-size buddies.\nThis makes it easier for the casting code to resolve this problem.\n\nProblems:\n\nCasting performance is terrible, anywhere from 60% to 1000% slower on a micro-benchmark.\n Can be improved by extending our casting wrapper to handle those interfaces (probably would have to give up inlining as they would be huge)\n\nThe code in domain.c is icky, but not sure where to put it otherwise.\n\nIEnumerator could be solved in Array.cs by not forcing it to be magic as well. Meaning the folowing\n\n\`\`\`\nobject array = new int[1];\nvar a = array as IList<int>;\nvar b = array as IList<uint>;\n\na.GetEnumerator().GetType () != b.GetEnumerator().GetType ();\n\`\`\`\n\nThe last line is false today but it's harmless to change it to avoid the casting penalty for such central type.
(manually escaped backticks, for the purposes of displaying properly in this GH issue)
Backticks are needed for code blocks in GH (so it's entirely reasonable to include them), and are also part of the spec for .NET object interfaces, so we tend to hit this quite often.