Bug 54485 - Creating an open generic type with recurrent constraint fails
Summary: Creating an open generic type with recurrent constraint fails
Status: RESOLVED FIXED
Alias: None
Product: Runtime
Classification: Mono
Component: Reflection (show other bugs)
Version: 4.8.0 (C9)
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Aleksey Kliger
URL:
Depends on:
Blocks:
 
Reported: 2017-04-05 13:11 UTC by mholenko
Modified: 2017-05-30 18:35 UTC (History)
3 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Code exposing the error (346 bytes, text/x-csharp)
2017-04-05 13:11 UTC, mholenko
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

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.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description mholenko 2017-04-05 13:11:41 UTC
Created attachment 21213 [details]
Code exposing the error

Creating an open generic type with constraints fails with "Invalid generic arguments" on mono 4.8.0 (Stable 4.8.0.520/8f6d0f6 Wed Mar 15 16:18:35 UTC 2017), but works fine on .NET 4.6.01055.

Steps to reproduce:
===================

Using source attached:

mcs Example.cs
mono Example.exe

Expected output:
----------------

Test.B`1[Test.A`1[X]]

Actual output:
--------------

Unhandled Exception:
System.ArgumentException: Invalid generic arguments
Parameter name: typeArguments
  at (wrapper managed-to-native) System.RuntimeType:MakeGenericType (System.Type,System.Type[])
  at System.RuntimeType.MakeGenericType (System.Type[] instantiation) [0x000ef] in <f712f98eb8e445c8918edaf595bbe465>:0 
  at Test.MainClass.Main (System.String[] args) [0x00000] in <b2390977f2dd4b7fbda925e78df816c9>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: Invalid generic arguments
Parameter name: typeArguments
  at (wrapper managed-to-native) System.RuntimeType:MakeGenericType (System.Type,System.Type[])
  at System.RuntimeType.MakeGenericType (System.Type[] instantiation) [0x000ef] in <f712f98eb8e445c8918edaf595bbe465>:0 
  at Test.MainClass.Main (System.String[] args) [0x00000] in <b2390977f2dd4b7fbda925e78df816c9>:0 


What is more, when trying to reproduce the case in Mono C# Shell there is an exception printed, but after that creating a type works:

csharp> public class B<Y> where Y: B<Y> {}
csharp> public class A<X>: B<A<X>> {}
Mono.CSharp.InternalErrorException: (1,15): A<X> ---> System.NullReferenceException: Object reference not set to an instance of an object
  at Mono.CSharp.TypeParameterSpec.get_HasTypeConstraint () [0x00006] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.TypeParameterSpec.InflateConstraints[T] (Mono.CSharp.TypeParameterSpec[] tparams, System.Func`2[T,TResult] inflatorFactory, T arg) [0x00018] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.InflatedTypeSpec.get_Constraints () [0x00017] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.GenericTypeExpr.ResolveAsType (Mono.CSharp.IMemberContext mc, System.Boolean allowUnboundTypeArguments) [0x00071] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.SimpleName.ResolveAsTypeOrNamespace (Mono.CSharp.IMemberContext mc, System.Boolean allowUnboundTypeArguments) [0x0005a] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.FullNamedExpression.ResolveAsType (Mono.CSharp.IMemberContext mc, System.Boolean allowUnboundTypeArguments) [0x00000] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.TypeArguments.Resolve (Mono.CSharp.IMemberContext ec, System.Boolean allowUnbound) [0x00050] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.GenericTypeExpr.ResolveAsType (Mono.CSharp.IMemberContext mc, System.Boolean allowUnboundTypeArguments) [0x00012] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.SimpleName.ResolveAsTypeOrNamespace (Mono.CSharp.IMemberContext mc, System.Boolean allowUnboundTypeArguments) [0x0005a] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.FullNamedExpression.ResolveAsType (Mono.CSharp.IMemberContext mc, System.Boolean allowUnboundTypeArguments) [0x00000] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.TypeDefinition.ResolveBaseTypes (Mono.CSharp.FullNamedExpression& base_class) [0x0003e] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.Class.ResolveBaseTypes (Mono.CSharp.FullNamedExpression& base_class) [0x00000] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.TypeDefinition.DoDefineBaseType () [0x00000] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.TypeDefinition.DefineBaseTypes () [0x0001d] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.TypeDefinition.DoDefineContainer () [0x00000] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.TypeContainer.DefineContainer () [0x00014] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.TypeContainer.DefineContainer () [0x0003e] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
   --- End of inner exception stack trace ---
  at Mono.CSharp.TypeContainer.DefineContainer () [0x00064] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
  at Mono.CSharp.TypeContainer.DefineContainer () [0x0003e] in <e7dbdd719df1414e9c0c444e78d0c901>:0 
csharp> typeof(B<>).MakeGenericType(typeof(A<>))                                                                                                                                                                    B`1[A`1[X]]
Comment 1 Aleksey Kliger 2017-04-17 19:48:10 UTC
In verify.c, is_valid_generic_instantiation() is returning FALSE while trying to verify whether "class B<Y> where Y : B<Y>" may be instantiated with A`1 (class A<X> : B<A<X>>).

Specifically, it is checking whether B<A`1> (a generic instance) is assignable from A`1 (a generic type definition).  The fast parent check fails because the gtd A`1 has as a parent the generic instantiation B<A<X> > (ie the type argument to B`1 is the generic instance A<X>, not the gtd A`1) and that is not the same MonoClass* as B instantiated with A`1.
Comment 2 Aleksey Kliger 2017-04-21 20:30:11 UTC
Fixed on mono master https://github.com/mono/mono/commit/a1cabeee67e60ce0a2399edfae7a3def696e7272

We now expand any uninstantiated generic type definition that appears in the type arguments of another generic instantiation.  (ie we change Foo`2<Bar`1, int> into Foo`2<Bar`1<X>, int> where "X" is the generic parameter from the generic container of Bar`1).
Comment 3 mholenko 2017-05-25 08:47:22 UTC
It seems that the problem is still present in mono 5.0.0 (Stable 5.0.0.100/9667aa6 Thu May 11 14:48:10 UTC 2017).
Comment 4 Aleksey Kliger 2017-05-30 14:22:46 UTC
Apologies.  This was kind of a high-risk fix right before the 5.0.* release, so it missed the train.  I'll work on a version for mono's 2017-04 branch (likely to be the 5.2.* release)
Comment 5 Aleksey Kliger 2017-05-30 18:35:31 UTC
Fixed on mono 2017-04 https://github.com/mono/mono/commit/28625fda3ee4b838a2c2d45d6784d6754e243af0