From 57f05a3c12e332f8408a878852b46237632aaf67 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Mon, 28 Oct 2024 18:05:02 -0700 Subject: [PATCH] Add tests for `unmanaged` constraint (#75629) Related to #75620. --- .../Semantics/GenericConstraintsTests.cs | 181 +++++++++++++++++- 1 file changed, 180 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index b80cafc4cad8..69fc5fd11681 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3662,7 +3662,7 @@ public struct YourStruct where T : unmanaged } [Fact] - public void UnmanagedExpandingTypeArgumentConstraintViolation() + public void UnmanagedExpandingTypeArgumentConstraintViolation_01() { var code = @" public struct MyStruct @@ -3689,6 +3689,157 @@ public struct YourStruct where T : unmanaged Assert.False(compilation.GetMember("YourStruct").IsManagedTypeNoUseSiteDiagnostics); } + [Fact] + public void UnmanagedExpandingTypeArgumentConstraintViolation_02() + { + var code = @" +public struct MyStruct +{ + public string s; + public YourStruct>> field; +} + +public struct YourStruct where T : unmanaged +{ + public T field; +} +"; + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + compilation.VerifyDiagnostics( + // (5,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(5, 46), + // (5,46): error CS8377: The type 'MyStruct>' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'YourStruct' + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct", "T", "MyStruct>").WithLocation(5, 46)); + + Assert.True(compilation.GetMember("MyStruct").IsManagedTypeNoUseSiteDiagnostics); + Assert.False(compilation.GetMember("YourStruct").IsManagedTypeNoUseSiteDiagnostics); + } + + [Fact] + public void UnmanagedExpandingTypeArgumentConstraintViolation_03() + { + var code = @" +public struct MyStruct +{ + public YourStruct>> field {get;set;} + public string s; +} + +public struct YourStruct where T : unmanaged +{ + public T field; +} +"; + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + compilation.VerifyDiagnostics( + // (4,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(4, 46), + // (4,46): error CS8377: The type 'MyStruct>' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'YourStruct' + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct", "T", "MyStruct>").WithLocation(4, 46)); + + Assert.True(compilation.GetMember("MyStruct").IsManagedTypeNoUseSiteDiagnostics); + Assert.False(compilation.GetMember("YourStruct").IsManagedTypeNoUseSiteDiagnostics); + } + + [Fact] + public void UnmanagedExpandingTypeArgumentConstraintViolation_04() + { + var code = @" +public struct MyStruct +{ + public string s; + public YourStruct>> field {get;set;} +} + +public struct YourStruct where T : unmanaged +{ + public T field; +} +"; + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + compilation.VerifyDiagnostics( + // (5,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(5, 46), + // (5,46): error CS8377: The type 'MyStruct>' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'YourStruct' + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct", "T", "MyStruct>").WithLocation(5, 46)); + + Assert.True(compilation.GetMember("MyStruct").IsManagedTypeNoUseSiteDiagnostics); + Assert.False(compilation.GetMember("YourStruct").IsManagedTypeNoUseSiteDiagnostics); + } + + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/75620")] + [WorkItem("https://github.com/dotnet/roslyn/issues/75620")] + public void UnmanagedExpandingTypeArgumentConstraintViolation_05() + { + var code = @" +#pragma warning disable CS0067 // The event 'MyStruct.field' is never used + +public struct MyStruct +{ + public event YourStruct>> field; + public string s; +} + +public struct YourStruct where T : unmanaged +{ + public T field; +} +"; + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + + compilation.VerifyDiagnostics( + // (6,52): error CS0066: 'MyStruct.field': event must be of a delegate type + // public event YourStruct>> field; + Diagnostic(ErrorCode.ERR_EventNotDelegate, "field").WithArguments("MyStruct.field").WithLocation(6, 52), + // (6,52): error CS8377: The type 'MyStruct>' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'YourStruct' + // public event YourStruct>> field; + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct", "T", "MyStruct>").WithLocation(6, 52) + ); + + Assert.True(compilation.GetMember("MyStruct").IsManagedTypeNoUseSiteDiagnostics); + Assert.False(compilation.GetMember("YourStruct").IsManagedTypeNoUseSiteDiagnostics); + } + + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/75620")] + [WorkItem("https://github.com/dotnet/roslyn/issues/75620")] + public void UnmanagedExpandingTypeArgumentConstraintViolation_06() + { + var code = @" +#pragma warning disable CS0067 // The event 'MyStruct.field' is never used + +public struct MyStruct +{ + public string s; + public event YourStruct>> field; +} + +public struct YourStruct where T : unmanaged +{ + public T field; +} +"; + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + compilation.VerifyDiagnostics( + // (4,52): error CS0066: 'MyStruct.field': event must be of a delegate type + // public event YourStruct>> field; + Diagnostic(ErrorCode.ERR_EventNotDelegate, "field").WithArguments("MyStruct.field").WithLocation(4, 52), + // (5,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(5, 46), + // (5,46): error CS8377: The type 'MyStruct>' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'YourStruct' + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct", "T", "MyStruct>").WithLocation(5, 46)); + + Assert.True(compilation.GetMember("MyStruct").IsManagedTypeNoUseSiteDiagnostics); + Assert.False(compilation.GetMember("YourStruct").IsManagedTypeNoUseSiteDiagnostics); + } + [Fact] public void UnmanagedRecursiveTypeArgumentConstraintViolation_02() { @@ -3717,6 +3868,34 @@ public struct YourStruct where T : unmanaged Assert.True(compilation.GetMember("YourStruct").IsManagedTypeNoUseSiteDiagnostics); } + [Fact] + public void UnmanagedRecursiveTypeArgumentConstraintViolation_03() + { + var code = @" +public struct MyStruct +{ + public YourStruct>> field; +} + +public struct YourStruct where T : unmanaged +{ + public string s; + public T field; +} +"; + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + compilation.VerifyDiagnostics( + // (4,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(4, 46), + // (4,46): error CS8377: The type 'MyStruct>' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'YourStruct' + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct", "T", "MyStruct>").WithLocation(4, 46)); + + Assert.True(compilation.GetMember("MyStruct").IsManagedTypeNoUseSiteDiagnostics); + Assert.True(compilation.GetMember("YourStruct").IsManagedTypeNoUseSiteDiagnostics); + } + [Fact] public void NestedGenericStructContainingPointer() {