public void UnmanagedTypeModreqIsCopiedToOverrides_Interface_Explicit_Compilation()
        {
            var reference = CompileAndVerify(@"
public interface Parent
{
    string M<T>() where T : unmanaged;
}
public class Child : Parent
{
    string Parent.M<T>() => ""Child"";
}", symbolValidator: module =>
            {
                var parentTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single();
                Assert.True(parentTypeParameter.HasValueTypeConstraint);
                Assert.True(parentTypeParameter.HasUnmanagedTypeConstraint);

                AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, parentTypeParameter, module.ContainingAssembly.Name);

                var childTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("Parent.M").TypeParameters.Single();
                Assert.True(childTypeParameter.HasValueTypeConstraint);
                Assert.True(childTypeParameter.HasUnmanagedTypeConstraint);

                AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, childTypeParameter, module.ContainingAssembly.Name);
            });

            CompileAndVerify(@"
class Program
{
    public static void Main()
    {
        Parent obj = new Child();
        System.Console.WriteLine(obj.M<int>());
    }
}", references: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child");
        }
        public void UnmanagedTypeModreqIsCopiedToLambda_Reference()
        {
            var reference = CompileAndVerify(@"
public delegate T D<T>() where T : unmanaged;
public class TestRef
{
    public static void Print<T>(D<T> lambda) where T : unmanaged
    {
        System.Console.WriteLine(lambda());
    }
}", symbolValidator: module =>
            {
                var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("D`1").TypeParameters.Single();
                Assert.True(typeParameter.HasValueTypeConstraint);
                Assert.True(typeParameter.HasUnmanagedTypeConstraint);
                Assert.False(typeParameter.HasConstructorConstraint);   // .ctor  is an artifact of emit, we will ignore it on importing.

                AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name);
            });


            CompileAndVerify(@"
public class Program
{
    static void Test<T>(T arg)  where T : unmanaged
    {
        TestRef.Print(() => arg);
    }
    
    public static void Main()
    {
        Test(5);
    }
}",
                             expectedOutput: "5",
                             references: new[] { reference.Compilation.EmitToImageReference() },
                             options: TestOptions.ReleaseExe.WithMetadataImportOptions(MetadataImportOptions.All),
                             symbolValidator: module =>
            {
                var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Program").GetTypeMember("<>c__DisplayClass0_0").TypeParameters.Single();
                Assert.True(typeParameter.HasValueTypeConstraint);
                Assert.True(typeParameter.HasUnmanagedTypeConstraint);
                Assert.False(typeParameter.HasConstructorConstraint);      // .ctor  is an artifact of emit, we will ignore it on importing.

                AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name);
            });
        }
        public void UnmanagedTypeModreqIsCopiedToOverrides_Virtual_Reference()
        {
            var parent = CompileAndVerify(@"
public class Parent
{
    public virtual string M<T>() where T : unmanaged => ""Parent"";
}", symbolValidator: module =>
            {
                var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single();
                Assert.True(typeParameter.HasValueTypeConstraint);
                Assert.True(typeParameter.HasUnmanagedTypeConstraint);

                AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name);
            });


            var child = CompileAndVerify(@"
public class Child : Parent
{
    public override string M<T>() => ""Child"";
}", references: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module =>
            {
                var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single();
                Assert.True(typeParameter.HasValueTypeConstraint);
                Assert.True(typeParameter.HasUnmanagedTypeConstraint);

                AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name);
            });

            CompileAndVerify(@"
class Program
{
    public static void Main()
    {
        System.Console.WriteLine(new Parent().M<int>());
        System.Console.WriteLine(new Child().M<int>());
    }
}", references: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: @"
Parent
Child");
        }
        public void UnmanagedTypeModreqIsCopiedToLambda_Compilation()
        {
            CompileAndVerify(@"
public delegate T D<T>() where T : unmanaged;
public class TestRef
{
    public static void Print<T>(D<T> lambda) where T : unmanaged
    {
        System.Console.WriteLine(lambda());
    }
}
public class Program
{
    static void Test<T>(T arg)  where T : unmanaged
    {
        TestRef.Print(() => arg);
    }
    
    public static void Main()
    {
        Test(5);
    }
}",
                             expectedOutput: "5",
                             options: TestOptions.ReleaseExe.WithMetadataImportOptions(MetadataImportOptions.All),
                             symbolValidator: module =>
            {
                var delegateTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("D`1").TypeParameters.Single();
                Assert.True(delegateTypeParameter.HasValueTypeConstraint);
                Assert.True(delegateTypeParameter.HasUnmanagedTypeConstraint);

                AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, delegateTypeParameter, module.ContainingAssembly.Name);

                var lambdaTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Program").GetTypeMember("<>c__DisplayClass0_0").TypeParameters.Single();
                Assert.True(lambdaTypeParameter.HasValueTypeConstraint);
                Assert.True(lambdaTypeParameter.HasUnmanagedTypeConstraint);

                AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, lambdaTypeParameter, module.ContainingAssembly.Name);
            });
        }