提交 b67a05c9 编写于 作者: J Julien Couvreur

Check LangVer. Report missing ValueTask

上级 f57c4676
......@@ -193,6 +193,15 @@ private BoundStatement BindFixedStatementParts(FixedStatementSyntax node, Diagno
boundBody);
}
private void CheckRequiredLangVersionForAsyncIteratorMethods(DiagnosticBag diagnostics)
{
var symbol = this.ContainingMemberOrLambda as MethodSymbol;
if (symbol.IsAsync)
{
MessageID.IDS_FeatureAsyncStreams.CheckFeatureAvailability(availableVersion: Compilation.LanguageVersion, diagnostics: diagnostics, errorLocation: symbol.Locations[0]);
}
}
private BoundStatement BindYieldReturnStatement(YieldStatementSyntax node, DiagnosticBag diagnostics)
{
var binder = this;
......@@ -228,6 +237,7 @@ private BoundStatement BindYieldReturnStatement(YieldStatementSyntax node, Diagn
Error(diagnostics, ErrorCode.ERR_YieldNotAllowedInScript, node.YieldKeyword);
}
CheckRequiredLangVersionForAsyncIteratorMethods(diagnostics);
return new BoundYieldReturnStatement(node, argument);
}
......@@ -243,6 +253,7 @@ private BoundStatement BindYieldBreakStatement(YieldStatementSyntax node, Diagno
}
GetIteratorElementType(node, diagnostics);
CheckRequiredLangVersionForAsyncIteratorMethods(diagnostics);
return new BoundYieldBreakStatement(node);
}
......
......@@ -506,7 +506,7 @@ private BoundForEachStatement BindForEachPartsWorker(DiagnosticBag diagnostics,
private bool GetAwaitDisposeAsyncInfo(ref ForEachEnumeratorInfo.Builder builder, DiagnosticBag diagnostics)
{
bool hasErrors = false;
BoundExpression placeholder = new BoundAwaitableValuePlaceholder(_syntax.Expression, Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_ValueTask));
BoundExpression placeholder = new BoundAwaitableValuePlaceholder(_syntax.Expression, this.GetWellKnownType(WellKnownType.System_Threading_Tasks_ValueTask, diagnostics, this._syntax));
builder.DisposeAwaitableInfo = BindAwaitInfo(placeholder, _syntax.Expression, _syntax.AwaitKeyword.GetLocation(), diagnostics, ref hasErrors);
return hasErrors;
}
......
......@@ -164,7 +164,7 @@ internal enum MessageID
IDS_FeatureAltInterpolatedVerbatimStrings = MessageBase + 12745,
IDS_FeatureCoalesceAssignmentExpression = MessageBase + 12746,
IDS_FeatureUnconstrainedTypeParameterInNullCoalescingOperator = MessageBase + 12747,
IDS_FeatureAsyncStreams = MessageBase + 12777, // PROTOTYPE(async-streams) Compact IDs
IDS_FeatureAsyncStreams = MessageBase + 12748,
}
// Message IDs may refer to strings that need to be localized.
......@@ -214,6 +214,15 @@ internal static string RequiredFeature(this MessageID feature)
}
}
internal static void CheckFeatureAvailability(this MessageID feature, LanguageVersion availableVersion, DiagnosticBag diagnostics, Location errorLocation)
{
LanguageVersion requiredVersion = feature.RequiredVersion();
if (requiredVersion > availableVersion)
{
diagnostics.Add(availableVersion.GetErrorCode(), errorLocation, feature.Localize(), new CSharpRequiredLanguageVersion(requiredVersion));
}
}
internal static LanguageVersion RequiredVersion(this MessageID feature)
{
// Based on CSourceParser::GetFeatureUsage from SourceParser.cpp.
......
......@@ -21,7 +21,6 @@ internal sealed class AsyncStateMachine : StateMachineTypeSymbol
public AsyncStateMachine(VariableSlotAllocator variableAllocatorOpt, TypeCompilationState compilationState, MethodSymbol asyncMethod, int asyncMethodOrdinal, TypeKind typeKind)
: base(variableAllocatorOpt, compilationState, asyncMethod, asyncMethodOrdinal)
{
// TODO: report use-site errors on these types
_typeKind = typeKind;
CSharpCompilation compilation = asyncMethod.DeclaringCompilation;
var interfaces = ArrayBuilder<NamedTypeSymbol>.GetInstance();
......
......@@ -39,6 +39,62 @@ public interface IAsyncDisposable
}
";
[Fact]
public void TestWithCSharp7_3()
{
string source = @"
using System.Collections.Generic;
class C : IAsyncEnumerable<int>
{
public static async System.Threading.Tasks.Task Main()
{
foreach await (int i in new C())
{
}
}
IAsyncEnumerator<int> IAsyncEnumerable<int>.GetAsyncEnumerator()
=> throw null;
}";
var comp = CreateCompilationWithTasksExtensions(new[] { source, s_interfaces }, parseOptions: TestOptions.Regular7_3);
comp.VerifyDiagnostics(
// (7,17): error CS8370: Feature 'async streams' is not available in C# 7.3. Please use language version 8.0 or greater.
// foreach await (int i in new C())
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "await").WithArguments("async streams", "8.0").WithLocation(7, 17)
);
}
[Fact]
public void TestWithMissingValueTask()
{
string lib_cs = @"
using System.Collections.Generic;
public class C : IAsyncEnumerable<int>
{
IAsyncEnumerator<int> IAsyncEnumerable<int>.GetAsyncEnumerator()
=> throw null;
}";
var lib = CreateCompilationWithTasksExtensions(new[] { lib_cs, s_interfaces });
lib.VerifyDiagnostics();
string source = @"
class D
{
public static async System.Threading.Tasks.Task Main()
{
foreach await (int i in new C()) { }
}
}
";
var comp = CreateCompilationWithTasksExtensions(source, references: new[] { lib.EmitToImageReference() });
comp.MakeTypeMissing(WellKnownType.System_Threading_Tasks_ValueTask);
comp.VerifyDiagnostics(
// (6,9): error CS0518: Predefined type 'System.Threading.Tasks.ValueTask' is not defined or imported
// foreach await (int i in new C()) { }
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "foreach await (int i in new C()) { }").WithArguments("System.Threading.Tasks.ValueTask").WithLocation(6, 9)
);
}
[Fact]
public void TestWithTwoIAsyncEnumerableImplementations()
{
......
......@@ -22,21 +22,6 @@ internal enum Instruction
[CompilerTrait(CompilerFeature.AsyncStreams)]
public class CodeGenAsyncIteratorTests : EmitMetadataTestBase
{
// PROTOTYPE(async-streams) Add more tests:
// Test with yield or await in try/catch/finally
// More tests with exception thrown
// There is a case in GetIteratorElementType with IsDirectlyInIterator that relates to speculation, needs testing
// yield break disallowed in finally and top-level script (see BindYieldBreakStatement); same for yield return (see BindYieldReturnStatement)
// binding for yield return (BindYieldReturnStatement) validates escape rules, needs testing
// test yield in async lambda (still error)
// test with IAsyncEnumerable<dynamic>
// other tests with dynamic?
// test should cover both case with AwaitOnCompleted and AwaitUnsafeOnCompleted
// test `async IAsyncEnumerable<int> M() { return TaskLike(); }`
// Can we avoid making IAsyncEnumerable<T> special from the start? Making mark it with an attribute like we did for task-like?
// Do some manual validation on debugging scenarios, including with exceptions (thrown after yield and after await).
// Test with one or both or the threadID APIs missing.
private void VerifyMissingMember(WellKnownMember member, params DiagnosticDescription[] expected)
{
var lib = CreateCompilationWithTasksExtensions(s_common);
......@@ -71,6 +56,30 @@ class C
comp.VerifyEmitDiagnostics(expected);
}
[Fact]
public void AsyncIteratorInCSharp7_3()
{
string source = @"
class C
{
static async System.Collections.Generic.IAsyncEnumerable<int> M()
{
await System.Threading.Tasks.Task.CompletedTask;
yield return 4;
yield break;
}
}";
var comp = CreateCompilationWithTasksExtensions(new[] { source, s_common }, parseOptions: TestOptions.Regular7_3);
comp.VerifyDiagnostics(
// (4,67): error CS8370: Feature 'async streams' is not available in C# 7.3. Please use language version 8.0 or greater.
// static async System.Collections.Generic.IAsyncEnumerable<int> M()
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M").WithArguments("async streams", "8.0").WithLocation(4, 67),
// (4,67): error CS8370: Feature 'async streams' is not available in C# 7.3. Please use language version 8.0 or greater.
// static async System.Collections.Generic.IAsyncEnumerable<int> M()
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M").WithArguments("async streams", "8.0").WithLocation(4, 67)
);
}
[Fact]
public void RefStructElementType()
{
......@@ -100,6 +109,34 @@ static async System.Threading.Tasks.Task Main()
);
}
[Fact]
public void ReturningIAsyncEnumerable()
{
string source = @"
class C
{
static System.Collections.Generic.IAsyncEnumerable<int> M2()
{
return M();
}
static async System.Collections.Generic.IAsyncEnumerable<int> M()
{
await System.Threading.Tasks.Task.CompletedTask;
yield return 42;
}
}";
var comp = CreateCompilationWithTasksExtensions(new[] { source, s_common });
comp.VerifyDiagnostics();
var m2 = comp.GlobalNamespace.GetMember<MethodSymbol>("C.M2");
Assert.False(m2.IsAsync);
Assert.False(m2.IsIterator);
var m = comp.GlobalNamespace.GetMember<MethodSymbol>("C.M");
Assert.True(m.IsAsync);
Assert.True(m.IsIterator);
}
[Fact]
public void AttributesSynthesized()
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册