Skip to content

Commit

Permalink
Add tests for unmanaged constraint (#75629)
Browse files Browse the repository at this point in the history
Related to #75620.
  • Loading branch information
AlekseyTs authored Oct 29, 2024
1 parent 502d0ec commit 57f05a3
Showing 1 changed file with 180 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -3662,7 +3662,7 @@ public struct YourStruct<T> where T : unmanaged
}

[Fact]
public void UnmanagedExpandingTypeArgumentConstraintViolation()
public void UnmanagedExpandingTypeArgumentConstraintViolation_01()
{
var code = @"
public struct MyStruct<T>
Expand All @@ -3689,6 +3689,157 @@ public struct YourStruct<T> where T : unmanaged
Assert.False(compilation.GetMember<NamedTypeSymbol>("YourStruct").IsManagedTypeNoUseSiteDiagnostics);
}

[Fact]
public void UnmanagedExpandingTypeArgumentConstraintViolation_02()
{
var code = @"
public struct MyStruct<T>
{
public string s;
public YourStruct<MyStruct<MyStruct<T>>> field;
}
public struct YourStruct<T> where T : unmanaged
{
public T field;
}
";
var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll);
compilation.VerifyDiagnostics(
// (5,46): error CS0523: Struct member 'MyStruct<T>.field' of type 'YourStruct<MyStruct<MyStruct<T>>>' causes a cycle in the struct layout
// public YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct<T>.field", "YourStruct<MyStruct<MyStruct<T>>>").WithLocation(5, 46),
// (5,46): error CS8377: The type 'MyStruct<MyStruct<T>>' 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<T>'
// public YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct<T>", "T", "MyStruct<MyStruct<T>>").WithLocation(5, 46));

Assert.True(compilation.GetMember<NamedTypeSymbol>("MyStruct").IsManagedTypeNoUseSiteDiagnostics);
Assert.False(compilation.GetMember<NamedTypeSymbol>("YourStruct").IsManagedTypeNoUseSiteDiagnostics);
}

[Fact]
public void UnmanagedExpandingTypeArgumentConstraintViolation_03()
{
var code = @"
public struct MyStruct<T>
{
public YourStruct<MyStruct<MyStruct<T>>> field {get;set;}
public string s;
}
public struct YourStruct<T> where T : unmanaged
{
public T field;
}
";
var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll);
compilation.VerifyDiagnostics(
// (4,46): error CS0523: Struct member 'MyStruct<T>.field' of type 'YourStruct<MyStruct<MyStruct<T>>>' causes a cycle in the struct layout
// public YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct<T>.field", "YourStruct<MyStruct<MyStruct<T>>>").WithLocation(4, 46),
// (4,46): error CS8377: The type 'MyStruct<MyStruct<T>>' 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<T>'
// public YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct<T>", "T", "MyStruct<MyStruct<T>>").WithLocation(4, 46));

Assert.True(compilation.GetMember<NamedTypeSymbol>("MyStruct").IsManagedTypeNoUseSiteDiagnostics);
Assert.False(compilation.GetMember<NamedTypeSymbol>("YourStruct").IsManagedTypeNoUseSiteDiagnostics);
}

[Fact]
public void UnmanagedExpandingTypeArgumentConstraintViolation_04()
{
var code = @"
public struct MyStruct<T>
{
public string s;
public YourStruct<MyStruct<MyStruct<T>>> field {get;set;}
}
public struct YourStruct<T> where T : unmanaged
{
public T field;
}
";
var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll);
compilation.VerifyDiagnostics(
// (5,46): error CS0523: Struct member 'MyStruct<T>.field' of type 'YourStruct<MyStruct<MyStruct<T>>>' causes a cycle in the struct layout
// public YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct<T>.field", "YourStruct<MyStruct<MyStruct<T>>>").WithLocation(5, 46),
// (5,46): error CS8377: The type 'MyStruct<MyStruct<T>>' 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<T>'
// public YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct<T>", "T", "MyStruct<MyStruct<T>>").WithLocation(5, 46));

Assert.True(compilation.GetMember<NamedTypeSymbol>("MyStruct").IsManagedTypeNoUseSiteDiagnostics);
Assert.False(compilation.GetMember<NamedTypeSymbol>("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<T>.field' is never used
public struct MyStruct<T>
{
public event YourStruct<MyStruct<MyStruct<T>>> field;
public string s;
}
public struct YourStruct<T> where T : unmanaged
{
public T field;
}
";
var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll);

compilation.VerifyDiagnostics(
// (6,52): error CS0066: 'MyStruct<T>.field': event must be of a delegate type
// public event YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_EventNotDelegate, "field").WithArguments("MyStruct<T>.field").WithLocation(6, 52),
// (6,52): error CS8377: The type 'MyStruct<MyStruct<T>>' 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<T>'
// public event YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct<T>", "T", "MyStruct<MyStruct<T>>").WithLocation(6, 52)
);

Assert.True(compilation.GetMember<NamedTypeSymbol>("MyStruct").IsManagedTypeNoUseSiteDiagnostics);
Assert.False(compilation.GetMember<NamedTypeSymbol>("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<T>.field' is never used
public struct MyStruct<T>
{
public string s;
public event YourStruct<MyStruct<MyStruct<T>>> field;
}
public struct YourStruct<T> where T : unmanaged
{
public T field;
}
";
var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll);
compilation.VerifyDiagnostics(
// (4,52): error CS0066: 'MyStruct<T>.field': event must be of a delegate type
// public event YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_EventNotDelegate, "field").WithArguments("MyStruct<T>.field").WithLocation(4, 52),
// (5,46): error CS0523: Struct member 'MyStruct<T>.field' of type 'YourStruct<MyStruct<MyStruct<T>>>' causes a cycle in the struct layout
// public YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct<T>.field", "YourStruct<MyStruct<MyStruct<T>>>").WithLocation(5, 46),
// (5,46): error CS8377: The type 'MyStruct<MyStruct<T>>' 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<T>'
// public YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct<T>", "T", "MyStruct<MyStruct<T>>").WithLocation(5, 46));

Assert.True(compilation.GetMember<NamedTypeSymbol>("MyStruct").IsManagedTypeNoUseSiteDiagnostics);
Assert.False(compilation.GetMember<NamedTypeSymbol>("YourStruct").IsManagedTypeNoUseSiteDiagnostics);
}

[Fact]
public void UnmanagedRecursiveTypeArgumentConstraintViolation_02()
{
Expand Down Expand Up @@ -3717,6 +3868,34 @@ public struct YourStruct<T> where T : unmanaged
Assert.True(compilation.GetMember<NamedTypeSymbol>("YourStruct").IsManagedTypeNoUseSiteDiagnostics);
}

[Fact]
public void UnmanagedRecursiveTypeArgumentConstraintViolation_03()
{
var code = @"
public struct MyStruct<T>
{
public YourStruct<MyStruct<MyStruct<T>>> field;
}
public struct YourStruct<T> 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<T>.field' of type 'YourStruct<MyStruct<MyStruct<T>>>' causes a cycle in the struct layout
// public YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct<T>.field", "YourStruct<MyStruct<MyStruct<T>>>").WithLocation(4, 46),
// (4,46): error CS8377: The type 'MyStruct<MyStruct<T>>' 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<T>'
// public YourStruct<MyStruct<MyStruct<T>>> field;
Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct<T>", "T", "MyStruct<MyStruct<T>>").WithLocation(4, 46));

Assert.True(compilation.GetMember<NamedTypeSymbol>("MyStruct").IsManagedTypeNoUseSiteDiagnostics);
Assert.True(compilation.GetMember<NamedTypeSymbol>("YourStruct").IsManagedTypeNoUseSiteDiagnostics);
}

[Fact]
public void NestedGenericStructContainingPointer()
{
Expand Down

0 comments on commit 57f05a3

Please sign in to comment.