Skip to content

Commit

Permalink
Verify that ref-in-async errors are not downgraded to warnings in uns…
Browse files Browse the repository at this point in the history
…afe context (#73490)
  • Loading branch information
jjonescz authored May 17, 2024
1 parent 16426ba commit 05e5ec7
Showing 1 changed file with 209 additions and 0 deletions.
209 changes: 209 additions & 0 deletions src/Compilers/CSharp/Test/Emit3/RefUnsafeInIteratorAndAsyncTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,114 @@ async Task M(int x)
Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(8, 30));
}

[Fact]
public void Await_RefLocal_Across_Unsafe_01()
{
var source = """
using System.Threading.Tasks;
class C
{
async Task M(int x)
{
unsafe
{
ref int y = ref x;
await Task.Yield();
System.Console.Write(y);
}
}
}
""";

CreateCompilation(source, parseOptions: TestOptions.Regular12, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (8,21): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// ref int y = ref x;
Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(8, 21),
// (9,13): error CS4004: Cannot await in an unsafe context
// await Task.Yield();
Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await Task.Yield()").WithLocation(9, 13));

var expectedDiagnostics = new[]
{
// (9,13): error CS4004: Cannot await in an unsafe context
// await Task.Yield();
Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await Task.Yield()").WithLocation(9, 13)
};

CreateCompilation(source, parseOptions: TestOptions.RegularNext, options: TestOptions.UnsafeReleaseDll).VerifyEmitDiagnostics(expectedDiagnostics);
CreateCompilation(source, options: TestOptions.UnsafeReleaseDll).VerifyEmitDiagnostics(expectedDiagnostics);
}

[Fact]
public void Await_RefLocal_Across_Unsafe_02()
{
var source = """
using System.Threading.Tasks;
unsafe class C
{
async Task M(int x)
{
ref int y = ref x;
await Task.Yield();
System.Console.Write(y);
}
}
""";

CreateCompilation(source, parseOptions: TestOptions.Regular12, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (6,17): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// ref int y = ref x;
Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(6, 17),
// (7,9): error CS4004: Cannot await in an unsafe context
// await Task.Yield();
Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await Task.Yield()").WithLocation(7, 9));

var expectedDiagnostics = new[]
{
// (7,9): error CS4004: Cannot await in an unsafe context
// await Task.Yield();
Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await Task.Yield()").WithLocation(7, 9)
};

CreateCompilation(source, parseOptions: TestOptions.RegularNext, options: TestOptions.UnsafeReleaseDll).VerifyEmitDiagnostics(expectedDiagnostics);
CreateCompilation(source, options: TestOptions.UnsafeReleaseDll).VerifyEmitDiagnostics(expectedDiagnostics);
}

[Fact]
public void Await_RefLocal_Across_Unsafe_03()
{
var source = """
using System.Threading.Tasks;
class C
{
async Task M(int x)
{
ref int y = ref x;
await Task.Yield();
unsafe
{
System.Console.Write(y);
}
}
}
""";

CreateCompilation(source, parseOptions: TestOptions.Regular12, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (6,17): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// ref int y = ref x;
Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(6, 17));

var expectedDiagnostics = new[]
{
// (10,34): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary.
// System.Console.Write(y);
Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(10, 34)
};

CreateCompilation(source, parseOptions: TestOptions.RegularNext, options: TestOptions.UnsafeReleaseDll).VerifyEmitDiagnostics(expectedDiagnostics);
CreateCompilation(source, options: TestOptions.UnsafeReleaseDll).VerifyEmitDiagnostics(expectedDiagnostics);
}

[Fact]
public void Await_RefLocal_Across_Reassign()
{
Expand Down Expand Up @@ -290,6 +398,39 @@ async Task M(int x)
Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "y").WithArguments("System.Span<int>").WithLocation(9, 23));
}

[Fact]
public void Await_RefStruct_Across_Unsafe()
{
var source = """
using System;
using System.Threading.Tasks;
class C
{
async Task M(int x)
{
Span<int> y = new(ref x);
await Task.Yield();
unsafe { Console.Write(y.ToString()); }
}
}
""";

CreateCompilation(source, parseOptions: TestOptions.Regular12, options: TestOptions.UnsafeReleaseDll, targetFramework: TargetFramework.Net70).VerifyDiagnostics(
// (7,9): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// Span<int> y = new(ref x);
Diagnostic(ErrorCode.ERR_FeatureInPreview, "Span<int>").WithArguments("ref and unsafe in async and iterator methods").WithLocation(7, 9));

var expectedDiagnostics = new[]
{
// (9,32): error CS4007: Instance of type 'System.Span<int>' cannot be preserved across 'await' or 'yield' boundary.
// unsafe { Console.Write(y.ToString()); }
Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "y").WithArguments("System.Span<int>").WithLocation(9, 32)
};

CreateCompilation(source, parseOptions: TestOptions.RegularNext, options: TestOptions.UnsafeReleaseDll, targetFramework: TargetFramework.Net70).VerifyEmitDiagnostics(expectedDiagnostics);
CreateCompilation(source, options: TestOptions.UnsafeReleaseDll, targetFramework: TargetFramework.Net70).VerifyEmitDiagnostics(expectedDiagnostics);
}

[Fact]
public void Await_RefStruct_Across_Reassign()
{
Expand Down Expand Up @@ -413,6 +554,41 @@ IEnumerable<int> M(int x)
Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(8, 30));
}

[Fact]
public void YieldReturn_RefLocal_Across_Unsafe()
{
var source = """
using System.Collections.Generic;
class C
{
IEnumerable<int> M(int x)
{
ref int y = ref x;
yield return 1;
unsafe { System.Console.Write(y); }
}
}
""";

CreateCompilation(source, parseOptions: TestOptions.Regular12, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (6,17): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// ref int y = ref x;
Diagnostic(ErrorCode.ERR_FeatureInPreview, "y").WithArguments("ref and unsafe in async and iterator methods").WithLocation(6, 17),
// (8,9): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// unsafe { System.Console.Write(y); }
Diagnostic(ErrorCode.ERR_FeatureInPreview, "unsafe").WithArguments("ref and unsafe in async and iterator methods").WithLocation(8, 9));

var expectedDiagnostics = new[]
{
// (8,39): error CS9217: A 'ref' local cannot be preserved across 'await' or 'yield' boundary.
// unsafe { System.Console.Write(y); }
Diagnostic(ErrorCode.ERR_RefLocalAcrossAwait, "y").WithLocation(8, 39)
};

CreateCompilation(source, parseOptions: TestOptions.RegularNext, options: TestOptions.UnsafeReleaseDll).VerifyEmitDiagnostics(expectedDiagnostics);
CreateCompilation(source, options: TestOptions.UnsafeReleaseDll).VerifyEmitDiagnostics(expectedDiagnostics);
}

[Fact]
public void YieldReturn_RefLocal_Across_Indexer()
{
Expand Down Expand Up @@ -642,6 +818,39 @@ IEnumerable<int> M(int x)
Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "y").WithArguments("System.Span<int>").WithLocation(9, 23));
}

[Fact]
public void YieldReturn_RefStruct_Across_Unsafe()
{
var source = """
using System;
using System.Collections.Generic;
class C
{
IEnumerable<int> M(int x)
{
Span<int> y = new(ref x);
yield return -1;
unsafe { Console.Write(y.ToString()); }
}
}
""";

CreateCompilation(source, parseOptions: TestOptions.Regular12, options: TestOptions.UnsafeReleaseDll, targetFramework: TargetFramework.Net70).VerifyDiagnostics(
// (9,9): error CS8652: The feature 'ref and unsafe in async and iterator methods' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// unsafe { Console.Write(y.ToString()); }
Diagnostic(ErrorCode.ERR_FeatureInPreview, "unsafe").WithArguments("ref and unsafe in async and iterator methods").WithLocation(9, 9));

var expectedDiagnostics = new[]
{
// (9,32): error CS4007: Instance of type 'System.Span<int>' cannot be preserved across 'await' or 'yield' boundary.
// unsafe { Console.Write(y.ToString()); }
Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "y").WithArguments("System.Span<int>").WithLocation(9, 32)
};

CreateCompilation(source, parseOptions: TestOptions.RegularNext, options: TestOptions.UnsafeReleaseDll, targetFramework: TargetFramework.Net70).VerifyEmitDiagnostics(expectedDiagnostics);
CreateCompilation(source, options: TestOptions.UnsafeReleaseDll, targetFramework: TargetFramework.Net70).VerifyEmitDiagnostics(expectedDiagnostics);
}

[Fact]
public void YieldReturn_RefStruct_Across_Indexer()
{
Expand Down

0 comments on commit 05e5ec7

Please sign in to comment.