Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for unmanaged constraint #75629

Merged
merged 1 commit into from
Oct 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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