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

Check result type of awaiter

上级 5a6e9166
......@@ -101,7 +101,7 @@ finally
### Detailed design for async-iterator methods
An async-iterator method is replaced by a kick-off method, which initializes a state machine. It does not start running the state machine (unlike kick-off methods for regular async method).
The kick-off method method is marked with both `AsyncStateMachineAttribute` and `IteratorStateMachineAttribute`.
The kick-off method method is marked with `AsyncIteratorStateMachineAttribute`.
The state machine for an enumerable async-iterator method primarily implements `IAsyncEnumerable<T>` and `IAsyncEnumerator<T>`.
For an enumerator async-iterator, it only implements `IAsyncEnumerator<T>`.
......
......@@ -210,6 +210,12 @@ private BoundForEachStatement BindForEachPartsWorker(DiagnosticBag diagnostics,
{
BoundExpression placeholder = new BoundAwaitableValuePlaceholder(_syntax.Expression, builder.MoveNextMethod?.ReturnType.TypeSymbol ?? CreateErrorType());
awaitInfo = BindAwaitInfo(placeholder, _syntax.Expression, _syntax.AwaitKeyword.GetLocation(), diagnostics, ref hasErrors);
if (!hasErrors && awaitInfo.GetResult?.ReturnType.SpecialType != SpecialType.System_Boolean)
{
diagnostics.Add(ErrorCode.ERR_BadGetAsyncEnumerator, _syntax.Expression.Location, collectionExpr.Type, GetAsyncEnumeratorMethodName);
hasErrors = true;
}
}
TypeSymbol iterationVariableType;
......
......@@ -567,11 +567,10 @@ public int Current
}
}";
var comp = CreateCompilationWithMscorlib46(source);
// TODO
comp.VerifyDiagnostics(
// (6,33): error CS8412: Asynchronous foreach requires that the return type 'C.Enumerator' of 'C.GetAsyncEnumerator(CancellationToken)' must have a suitable public 'MoveNextAsync' method and public 'Current' property
// (6,33): error CS8412: Asynchronous foreach requires that the return type 'C' of 'GetAsyncEnumerator' must have a suitable public 'MoveNextAsync' method and public 'Current' property
// await foreach (var i in new C())
Diagnostic(ErrorCode.ERR_BadGetAsyncEnumerator, "new C()").WithArguments("C.Enumerator", "C.GetAsyncEnumerator(System.Threading.CancellationToken)").WithLocation(6, 33)
Diagnostic(ErrorCode.ERR_BadGetAsyncEnumerator, "new C()").WithArguments("C", "GetAsyncEnumerator").WithLocation(6, 33)
);
}
......@@ -604,11 +603,10 @@ public int Current
}
}";
var comp = CreateCompilationWithMscorlib46(source);
// TODO
comp.VerifyDiagnostics(
// (6,33): error CS8412: Asynchronous foreach requires that the return type 'C.Enumerator' of 'C.GetAsyncEnumerator(CancellationToken)' must have a suitable public 'MoveNextAsync' method and public 'Current' property
// (6,33): error CS8412: Asynchronous foreach requires that the return type 'C' of 'GetAsyncEnumerator' must have a suitable public 'MoveNextAsync' method and public 'Current' property
// await foreach (var i in new C())
Diagnostic(ErrorCode.ERR_BadGetAsyncEnumerator, "new C()").WithArguments("C.Enumerator", "C.GetAsyncEnumerator(System.Threading.CancellationToken)").WithLocation(6, 33)
Diagnostic(ErrorCode.ERR_BadGetAsyncEnumerator, "new C()").WithArguments("C", "GetAsyncEnumerator").WithLocation(6, 33)
);
}
......@@ -1983,7 +1981,7 @@ public async Task<bool> MoveNextAsync()
i = i + 100; // Note: side-effects of async methods in structs are lost
return more;
}
public async ValueTask DisposeAsync() => throw null;
public ValueTask DisposeAsync() => throw null;
}
}";
var comp = CreateCompilationWithTasksExtensions(source + s_IAsyncEnumerable, options: TestOptions.DebugExe);
......@@ -2069,7 +2067,8 @@ static async Task Main()
{
await foreach (var i in new C())
{
Write(""SKIPPED"");
Write($""Item({i}) "");
break;
}
Write($""Done"");
}
......@@ -2079,7 +2078,7 @@ public AsyncEnumerator GetAsyncEnumerator(System.Threading.CancellationToken tok
}
public class AsyncEnumerator : System.IAsyncDisposable
{
public int Current => throw null;
public int Current => 1;
public Awaitable MoveNextAsync()
{
return new Awaitable();
......@@ -2098,14 +2097,13 @@ public class Awaitable
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public bool IsCompleted { get { return true; } }
public bool GetResult() { Write(""GetResult ""); return false; }
public bool GetResult() { return true; }
public void OnCompleted(System.Action continuation) { }
}
}";
var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable }, options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
// TODO
var v = CompileAndVerify(comp, expectedOutput: "GetResult Dispose Done");
var v = CompileAndVerify(comp, expectedOutput: "Item(1) Dispose Done");
var tree = comp.SyntaxTrees.First();
var model = (SyntaxTreeSemanticModel)comp.GetSemanticModel(tree, ignoreAccessibility: false);
......
......@@ -3807,14 +3807,14 @@ static async System.Threading.Tasks.Task Main(System.Collections.Generic.IAsyncE
";
// https://github.com/dotnet/roslyn/issues/30362 how do we flag `await`?
string expectedOperationTree = @"
IForEachLoopOperation (LoopKind.ForEach, Continue Label Id: 0, Exit Label Id: 1) (OperationKind.Loop, Type: null, IsInvalid) (Syntax: 'await forea ... }')
IForEachLoopOperation (LoopKind.ForEach, Continue Label Id: 0, Exit Label Id: 1) (OperationKind.Loop, Type: null) (Syntax: 'await forea ... }')
Locals: Local_1: System.String value
LoopControlVariable:
IVariableDeclaratorOperation (Symbol: System.String value) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'string')
Initializer:
null
Collection:
IParameterReferenceOperation: pets (OperationKind.ParameterReference, Type: System.Collections.Generic.IAsyncEnumerable<System.String>, IsInvalid) (Syntax: 'pets')
IParameterReferenceOperation: pets (OperationKind.ParameterReference, Type: System.Collections.Generic.IAsyncEnumerable<System.String>) (Syntax: 'pets')
Body:
IBlockOperation (1 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'System.Cons ... ine(value);')
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册