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

Additional tests for ref struct interfaces feature #74282

Merged
merged 1 commit into from
Jul 16, 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
238 changes: 234 additions & 4 deletions src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21288,8 +21288,50 @@ public void Add(int x){}
// static void Test2([UnscopedRef] params scoped S y)
Diagnostic(ErrorCode.ERR_UnscopedScoped, "UnscopedRef").WithLocation(12, 24)
);
}

[Fact]
[WorkItem("https://github.com/dotnet/roslyn/issues/73557")]
public void UnscopedRef_03()
{
var sourceA =
@"
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;

// https://github.com/dotnet/roslyn/issues/73557: Consider testing similar scenario without params
public class Helper
{
static void Test1<T>([UnscopedRef] scoped T x)
where T : IEnumerable<int>, IAdd, new(), allows ref struct
{
}

static void Test2([UnscopedRef] scoped S y)
{
}
}

interface IAdd
{
void Add(int x);
}

ref struct S : IEnumerable<int>
{
public IEnumerator<int> GetEnumerator() => throw null;
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;
public void Add(int x){}
}
";
var comp = CreateCompilation(sourceA, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics);
comp.VerifyDiagnostics(
// (7,27): error CS9063: UnscopedRefAttribute cannot be applied to this parameter because it is unscoped by default.
// static void Test1<T>([UnscopedRef] scoped T x)
Diagnostic(ErrorCode.ERR_UnscopedRefAttributeUnsupportedTarget, "UnscopedRef").WithLocation(7, 27),
// (12,24): error CS9063: UnscopedRefAttribute cannot be applied to this parameter because it is unscoped by default.
// static void Test2([UnscopedRef] scoped S y)
Diagnostic(ErrorCode.ERR_UnscopedRefAttributeUnsupportedTarget, "UnscopedRef").WithLocation(12, 24)
);
}

[Fact]
Expand Down Expand Up @@ -21851,8 +21893,6 @@ ref struct S
// protected abstract override S Test2(S y);
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "Test2").WithArguments("y").WithLocation(14, 35)
);

// https://github.com/dotnet/roslyn/issues/73555: Consider testing similar scenario with implicitly scoped parameter
}

[Fact]
Expand Down Expand Up @@ -21895,8 +21935,198 @@ ref struct S
// protected abstract override void Test2(S y, out S z);
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "Test2").WithArguments("y").WithLocation(14, 38)
);
}

[Fact]
[WorkItem("https://github.com/dotnet/roslyn/issues/73555")]
public void MissingScopedInOverride_03()
{
var src = @"
abstract class Base
{
protected abstract T Test1<T>(out T x)
where T : allows ref struct;

protected abstract S Test2(out S y);

protected abstract T Test3<T>(scoped out T x)
where T : allows ref struct;

protected abstract S Test4(scoped out S y);
}

// https://github.com/dotnet/roslyn/issues/73554: Consider testing ERR_ScopedMismatchInParameterOfPartial and ERR_ScopedMismatchInParameterOfTarget.
abstract class Derived1 : Base
{
protected abstract override T Test1<T>(out T x);

protected abstract override S Test2(out S y);

protected abstract override T Test3<T>(out T x);

protected abstract override S Test4(out S y);
}

abstract class Derived2 : Base
{
protected abstract override T Test1<T>(scoped out T x);

protected abstract override S Test2(scoped out S y);

protected abstract override T Test3<T>(scoped out T x);

protected abstract override S Test4(scoped out S y);
}

ref struct S
{
}
";

var comp = CreateCompilation(src, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics);
comp.VerifyEmitDiagnostics();
}

[Fact]
[WorkItem("https://github.com/dotnet/roslyn/issues/73554")]
public void MissingScopedInPartial_01()
{
var src = @"
partial class C1
{
private partial void Test1<T>(scoped T x, out T z) where T : allows ref struct;

private partial void Test2(scoped S y, out S z);
}

partial class C1
{
private partial void Test1<T>(T x, out T z) where T : allows ref struct => throw null;

private partial void Test2(S y, out S z) => throw null;
}

partial class C2
{
private partial void Test3<T>(scoped T x, out T z) where T : allows ref struct;

private partial void Test4(scoped S y, out S z);
}

partial class C2
{
private partial void Test3<T>(scoped T x, out T z) where T : allows ref struct => throw null;

private partial void Test4(scoped S y, out S z) => throw null;
}


partial class C3
{
private partial void Test5<T>(T x, out T z) where T : allows ref struct;

private partial void Test6(S y, out S z);
}

partial class C3
{
private partial void Test5<T>(scoped T x, out T z) where T : allows ref struct => throw null;

private partial void Test6(scoped S y, out S z) => throw null;
}

partial class C4
{
private partial void Test7<T>(T x, out T z) where T : allows ref struct;

private partial void Test8(S y, out S z);
}

partial class C4
{
private partial void Test7<T>(T x, out T z) where T : allows ref struct => throw null;

private partial void Test8(S y, out S z) => throw null;
}

ref struct S
{
}
";

var comp = CreateCompilation(src, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics);
comp.VerifyDiagnostics(
// (11,26): error CS8988: The 'scoped' modifier of parameter 'x' doesn't match partial definition.
// private partial void Test1<T>(T x, out T z) where T : allows ref struct => throw null;
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfPartial, "Test1").WithArguments("x").WithLocation(11, 26),
// (13,26): error CS8988: The 'scoped' modifier of parameter 'y' doesn't match partial definition.
// private partial void Test2(S y, out S z) => throw null;
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfPartial, "Test2").WithArguments("y").WithLocation(13, 26),
// (40,26): error CS8988: The 'scoped' modifier of parameter 'x' doesn't match partial definition.
// private partial void Test5<T>(scoped T x, out T z) where T : allows ref struct => throw null;
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfPartial, "Test5").WithArguments("x").WithLocation(40, 26),
// (42,26): error CS8988: The 'scoped' modifier of parameter 'y' doesn't match partial definition.
// private partial void Test6(scoped S y, out S z) => throw null;
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfPartial, "Test6").WithArguments("y").WithLocation(42, 26)
);
}

[Fact]
[WorkItem("https://github.com/dotnet/roslyn/issues/73554")]
public void MissingScopedInDelegateTarget_01()
{
var src = @"
class Program
{
static void Test<T>() where T : allows ref struct
{
DTest1<T> d01 = C1.Test1;
DTest2 d02 = C1.Test2;
DTest3<T> d03 = C1.Test1;
DTest4 d04 = C1.Test2;

DTest1<T> d11 = C2.Test1;
DTest2 d12 = C2.Test2;
DTest3<T> d13 = C2.Test1;
DTest4 d14 = C2.Test2;
}
}

delegate void DTest1<T>(scoped T x, out T z) where T : allows ref struct;

delegate void DTest2(scoped S y, out S z);

delegate void DTest3<T>(T x, out T z) where T : allows ref struct;

delegate void DTest4(S y, out S z);

class C1
{
public static void Test1<T>(T x, out T z) where T : allows ref struct => throw null;

public static void Test2(S y, out S z) => throw null;
}

class C2
{
public static void Test1<T>(scoped T x, out T z) where T : allows ref struct => throw null;

public static void Test2(scoped S y, out S z) => throw null;
}

ref struct S
{
}
";

var comp = CreateCompilation(src, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics);
comp.VerifyDiagnostics(
// (6,25): error CS8986: The 'scoped' modifier of parameter 'x' doesn't match target 'DTest1<T>'.
// DTest1<T> d01 = C1.Test1;
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, "C1.Test1").WithArguments("x", "DTest1<T>").WithLocation(6, 25),
// (7,22): error CS8986: The 'scoped' modifier of parameter 'y' doesn't match target 'DTest2'.
// DTest2 d02 = C1.Test2;
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, "C1.Test2").WithArguments("y", "DTest2").WithLocation(7, 22)
);
}

[Fact(Skip = "https://github.com/dotnet/roslyn/issues/73553")] // Enable once we get support for 'byreflike' in IL.
Expand Down
Loading