From 5866fabb8ffe6cbdb17e46902d6b96900ab5937b Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Tue, 16 Jul 2024 04:49:28 -0700 Subject: [PATCH] Additional tests for `ref struct interfaces` feature (#74282) Closes #73557. Closes #73555. Closes #73554. --- .../Test/Emit3/RefStructInterfacesTests.cs | 238 +++++++++++++++++- 1 file changed, 234 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs b/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs index daf2a13da9baa..9ff6e678248d2 100644 --- a/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs @@ -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([UnscopedRef] scoped T x) + where T : IEnumerable, IAdd, new(), allows ref struct + { + } + + static void Test2([UnscopedRef] scoped S y) + { + } +} + +interface IAdd +{ + void Add(int x); +} + +ref struct S : IEnumerable +{ + public IEnumerator 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([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] @@ -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] @@ -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(out T x) + where T : allows ref struct; + + protected abstract S Test2(out S y); + + protected abstract T Test3(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(out T x); + + protected abstract override S Test2(out S y); + + protected abstract override T Test3(out T x); + + protected abstract override S Test4(out S y); +} + +abstract class Derived2 : Base +{ + protected abstract override T Test1(scoped out T x); + + protected abstract override S Test2(scoped out S y); + + protected abstract override T Test3(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(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 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(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(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 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(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 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 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 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(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() where T : allows ref struct + { + DTest1 d01 = C1.Test1; + DTest2 d02 = C1.Test2; + DTest3 d03 = C1.Test1; + DTest4 d04 = C1.Test2; + + DTest1 d11 = C2.Test1; + DTest2 d12 = C2.Test2; + DTest3 d13 = C2.Test1; + DTest4 d14 = C2.Test2; + } +} + +delegate void DTest1(scoped T x, out T z) where T : allows ref struct; + +delegate void DTest2(scoped S y, out S z); + +delegate void DTest3(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 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(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'. + // DTest1 d01 = C1.Test1; + Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, "C1.Test1").WithArguments("x", "DTest1").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.