Skip to content

Commit

Permalink
Additional tests for ref struct interfaces feature (#74282)
Browse files Browse the repository at this point in the history
Closes #73557.
Closes #73555.
Closes #73554.
  • Loading branch information
AlekseyTs authored Jul 16, 2024
1 parent 432b124 commit 5866fab
Showing 1 changed file with 234 additions and 4 deletions.
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 @@ -21321,8 +21321,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 @@ -21875,8 +21917,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 @@ -21919,8 +21959,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

0 comments on commit 5866fab

Please sign in to comment.