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)

See Also:
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

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

Note You need to log in before you can comment on or make changes to this bug.