// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis.CSharp
{
internal partial class AsyncRewriter : StateMachineRewriter
{
///
/// This rewriter rewrites an async-iterator method. See async-streams.md for design overview.
///
private sealed class AsyncIteratorRewriter : AsyncRewriter
{
private FieldSymbol _promiseOfValueOrEndField; // this struct implements the IValueTaskSource logic
private FieldSymbol _currentField; // stores the current/yielded value
private FieldSymbol _disposeModeField; // whether the state machine is in dispose mode (ie. skipping all logic except that in `catch` and `finally`, yielding no new elements)
private FieldSymbol _combinedTokensField; // CancellationTokenSource for combining tokens
// true if the iterator implements IAsyncEnumerable,
// false if it implements IAsyncEnumerator
private readonly bool _isEnumerable;
internal AsyncIteratorRewriter(
BoundStatement body,
MethodSymbol method,
int methodOrdinal,
AsyncStateMachine stateMachineType,
VariableSlotAllocator slotAllocatorOpt,
TypeCompilationState compilationState,
DiagnosticBag diagnostics)
: base(body, method, methodOrdinal, stateMachineType, slotAllocatorOpt, compilationState, diagnostics)
{
Debug.Assert(!TypeSymbol.Equals(method.IteratorElementTypeWithAnnotations.Type, null, TypeCompareKind.ConsiderEverything2));
_isEnumerable = method.IsAsyncReturningIAsyncEnumerable(method.DeclaringCompilation);
Debug.Assert(_isEnumerable != method.IsAsyncReturningIAsyncEnumerator(method.DeclaringCompilation));
}
protected override void VerifyPresenceOfRequiredAPIs(DiagnosticBag bag)
{
base.VerifyPresenceOfRequiredAPIs(bag);
if (_isEnumerable)
{
EnsureWellKnownMember(WellKnownMember.System_Collections_Generic_IAsyncEnumerable_T__GetAsyncEnumerator, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_CancellationToken__Equals, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_CancellationTokenSource__CreateLinkedTokenSource, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_CancellationTokenSource__Token, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_CancellationTokenSource__Dispose, bag);
}
EnsureWellKnownMember(WellKnownMember.System_Collections_Generic_IAsyncEnumerator_T__MoveNextAsync, bag);
EnsureWellKnownMember(WellKnownMember.System_Collections_Generic_IAsyncEnumerator_T__get_Current, bag);
EnsureWellKnownMember(WellKnownMember.System_IAsyncDisposable__DisposeAsync, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_ValueTask_T__ctorSourceAndToken, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_ValueTask_T__ctorValue, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_ValueTask__ctor, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__GetResult, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__GetStatus, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__get_Version, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__OnCompleted, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__Reset, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__SetException, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__SetResult, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_IValueTaskSource_T__GetResult, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_IValueTaskSource_T__GetStatus, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_IValueTaskSource_T__OnCompleted, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_IValueTaskSource__GetResult, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_IValueTaskSource__GetStatus, bag);
EnsureWellKnownMember(WellKnownMember.System_Threading_Tasks_Sources_IValueTaskSource__OnCompleted, bag);
}
protected override void GenerateMethodImplementations()
{
// IAsyncStateMachine methods and constructor
base.GenerateMethodImplementations();
if (_isEnumerable)
{
// IAsyncEnumerable
GenerateIAsyncEnumerableImplementation_GetAsyncEnumerator();
}
// IAsyncEnumerator
GenerateIAsyncEnumeratorImplementation_MoveNextAsync();
GenerateIAsyncEnumeratorImplementation_Current();
// IValueTaskSource
GenerateIValueTaskSourceBoolImplementation_GetResult();
GenerateIValueTaskSourceBoolImplementation_GetStatus();
GenerateIValueTaskSourceBoolImplementation_OnCompleted();
// IValueTaskSource
GenerateIValueTaskSourceImplementation_GetResult();
GenerateIValueTaskSourceImplementation_GetStatus();
GenerateIValueTaskSourceImplementation_OnCompleted();
// IAsyncDisposable
GenerateIAsyncDisposable_DisposeAsync();
}
protected override bool PreserveInitialParameterValuesAndThreadId
=> _isEnumerable;
protected override void GenerateControlFields()
{
// the fields are initialized from entry-point method (which replaces the async-iterator method), so they need to be public
base.GenerateControlFields();
NamedTypeSymbol boolType = F.SpecialType(SpecialType.System_Boolean);
// Add a field: ManualResetValueTaskSourceLogic promiseOfValueOrEnd
_promiseOfValueOrEndField = F.StateMachineField(
F.WellKnownType(WellKnownType.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T).Construct(boolType),
GeneratedNames.MakeAsyncIteratorPromiseOfValueOrEndFieldName(), isPublic: true);
// the element type may contain method type parameters, which are now alpha-renamed into type parameters of the generated class
TypeSymbol elementType = ((AsyncStateMachine)stateMachineType).IteratorElementType;
// Add a field: T current
_currentField = F.StateMachineField(elementType, GeneratedNames.MakeIteratorCurrentFieldName());
// Add a field: bool disposeMode
_disposeModeField = F.StateMachineField(boolType, GeneratedNames.MakeDisposeModeFieldName());
if (_isEnumerable && this.method.Parameters.Any(p => p is SourceComplexParameterSymbol { HasEnumeratorCancellationAttribute: true }))
{
// Add a field: CancellationTokenSource combinedTokens
_combinedTokensField = F.StateMachineField(
F.WellKnownType(WellKnownType.System_Threading_CancellationTokenSource),
GeneratedNames.MakeAsyncIteratorCombinedTokensFieldName());
}
}
protected override void GenerateConstructor()
{
// Produces:
// .ctor(int state)
// {
// this.state = state;
// this.initialThreadId = {managedThreadId};
// this.builder = System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create();
// }
Debug.Assert(stateMachineType.Constructor is IteratorConstructor);
F.CurrentFunction = stateMachineType.Constructor;
var bodyBuilder = ArrayBuilder.GetInstance();
bodyBuilder.Add(F.BaseInitialization());
bodyBuilder.Add(F.Assignment(F.InstanceField(stateField), F.Parameter(F.CurrentFunction.Parameters[0]))); // this.state = state;
var managedThreadId = MakeCurrentThreadId();
if (managedThreadId != null && (object)initialThreadIdField != null)
{
// this.initialThreadId = {managedThreadId};
bodyBuilder.Add(F.Assignment(F.InstanceField(initialThreadIdField), managedThreadId));
}
// this.builder = System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create();
bodyBuilder.Add(GenerateCreateAndAssignBuilder());
bodyBuilder.Add(F.Return());
F.CloseMethod(F.Block(bodyBuilder.ToImmutableAndFree()));
bodyBuilder = null;
}
private BoundExpressionStatement GenerateCreateAndAssignBuilder()
{
// Produce:
// this.builder = System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create();
return F.Assignment(
F.InstanceField(_builderField),
F.StaticCall(
null,
_asyncMethodBuilderMemberCollection.CreateBuilder));
}
protected override void InitializeStateMachine(ArrayBuilder bodyBuilder, NamedTypeSymbol frameType, LocalSymbol stateMachineLocal)
{
// var stateMachineLocal = new {StateMachineType}({initialState})
int initialState = _isEnumerable ? StateMachineStates.FinishedStateMachine : StateMachineStates.InitialAsyncIteratorStateMachine;
bodyBuilder.Add(
F.Assignment(
F.Local(stateMachineLocal),
F.New(stateMachineType.Constructor.AsMember(frameType), F.Literal(initialState))));
}
protected override BoundStatement InitializeParameterField(MethodSymbol getEnumeratorMethod, ParameterSymbol parameter, BoundExpression resultParameter, BoundExpression parameterProxy)
{
BoundStatement result;
if (_combinedTokensField is object &&
parameter is SourceComplexParameterSymbol { HasEnumeratorCancellationAttribute: true } &&
parameter.Type.Equals(F.Compilation.GetWellKnownType(WellKnownType.System_Threading_CancellationToken), TypeCompareKind.ConsiderEverything))
{
// For a parameter of type CancellationToken with [EnumeratorCancellation]
// if (this.parameterProxy.Equals(default))
// {
// result.parameter = token;
// }
// else if (token.Equals(this.parameterProxy) || token.Equals(default))
// {
// result.parameter = this.parameterProxy;
// }
// else
// {
// result.combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(this.parameterProxy, token);
// result.parameter = combinedTokens.Token;
// }
BoundParameter tokenParameter = F.Parameter(getEnumeratorMethod.Parameters[0]);
BoundFieldAccess combinedTokens = F.Field(F.This(), _combinedTokensField);
result = F.If(
// if (this.parameterProxy.Equals(default))
F.Call(parameterProxy, WellKnownMember.System_Threading_CancellationToken__Equals, F.Default(parameterProxy.Type)),
// result.parameter = token;
thenClause: F.Assignment(resultParameter, tokenParameter),
elseClauseOpt: F.If(
// else if (token.Equals(this.parameterProxy) || token.Equals(default))
F.LogicalOr(
F.Call(tokenParameter, WellKnownMember.System_Threading_CancellationToken__Equals, parameterProxy),
F.Call(tokenParameter, WellKnownMember.System_Threading_CancellationToken__Equals, F.Default(tokenParameter.Type))),
// result.parameter = this.parameterProxy;
thenClause: F.Assignment(resultParameter, parameterProxy),
elseClauseOpt: F.Block(
// result.combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(this.parameterProxy, token);
F.Assignment(combinedTokens, F.StaticCall(WellKnownMember.System_Threading_CancellationTokenSource__CreateLinkedTokenSource, parameterProxy, tokenParameter)),
// result.parameter = result.combinedTokens.Token;
F.Assignment(resultParameter, F.Property(combinedTokens, WellKnownMember.System_Threading_CancellationTokenSource__Token)))));
}
else
{
// For parameters that don't have [EnumeratorCancellation], initialize their parameter fields
// result.parameter = this.parameterProxy;
result = F.Assignment(resultParameter, parameterProxy);
}
return result;
}
protected override BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType)
{
// return local;
return F.Block(F.Return(F.Local(stateMachineVariable)));
}
///
/// Generates the `ValueTask<bool> MoveNextAsync()` method.
///
[SuppressMessage("Style", "VSTHRD200:Use \"Async\" suffix for async methods", Justification = "Standard naming convention for generating 'IAsyncEnumerator.MoveNextAsync'")]
private void GenerateIAsyncEnumeratorImplementation_MoveNextAsync()
{
// Produce:
// if (state == StateMachineStates.FinishedStateMachine)
// {
// return default;
// }
// _valueOrEndPromise.Reset();
// var inst = this;
// _builder.Start(ref inst);
// var version = _valueOrEndPromise.Version;
// if (_valueOrEndPromise.GetStatus(version) == ValueTaskSourceStatus.Succeeded)
// {
// return new ValueTask(_valueOrEndPromise.GetResult(version));
// }
// return new ValueTask(this, version);
NamedTypeSymbol IAsyncEnumeratorOfElementType =
F.WellKnownType(WellKnownType.System_Collections_Generic_IAsyncEnumerator_T)
.Construct(_currentField.Type);
MethodSymbol IAsyncEnumerableOfElementType_MoveNextAsync = F.WellKnownMethod(WellKnownMember.System_Collections_Generic_IAsyncEnumerator_T__MoveNextAsync)
.AsMember(IAsyncEnumeratorOfElementType);
var promiseType = (NamedTypeSymbol)_promiseOfValueOrEndField.Type;
MethodSymbol promise_GetStatus = F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__GetStatus)
.AsMember(promiseType);
MethodSymbol promise_GetResult = F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__GetResult)
.AsMember(promiseType);
var moveNextAsyncReturnType = (NamedTypeSymbol)IAsyncEnumerableOfElementType_MoveNextAsync.ReturnType;
MethodSymbol valueTaskT_ctorValue = F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ValueTask_T__ctorValue)
.AsMember(moveNextAsyncReturnType);
MethodSymbol valueTaskT_ctor = F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ValueTask_T__ctorSourceAndToken)
.AsMember(moveNextAsyncReturnType);
// The implementation doesn't depend on the method body of the iterator method.
OpenMethodImplementation(IAsyncEnumerableOfElementType_MoveNextAsync, hasMethodBodyDependency: false);
GetPartsForStartingMachine(out BoundExpressionStatement callReset,
out LocalSymbol instSymbol,
out BoundStatement instAssignment,
out BoundExpressionStatement startCall,
out MethodSymbol promise_get_Version);
BoundStatement ifFinished = F.If(
// if (state == StateMachineStates.FinishedStateMachine)
F.IntEqual(F.InstanceField(stateField), F.Literal(StateMachineStates.FinishedStateMachine)),
// return default;
thenClause: F.Return(F.Default(moveNextAsyncReturnType)));
// var version = _valueOrEndPromise.Version;
var versionSymbol = F.SynthesizedLocal(F.SpecialType(SpecialType.System_Int16));
var versionLocal = F.Local(versionSymbol);
var versionInit = F.Assignment(versionLocal, F.Call(F.Field(F.This(), _promiseOfValueOrEndField), promise_get_Version));
var ifPromiseReady = F.If(
// if (_valueOrEndPromise.GetStatus(version) == ValueTaskSourceStatus.Succeeded)
F.IntEqual(
F.Call(F.Field(F.This(), _promiseOfValueOrEndField), promise_GetStatus, versionLocal),
F.Literal(1)),
// return new ValueTask(_valueOrEndPromise.GetResult(version));
thenClause: F.Return(F.New(valueTaskT_ctorValue, F.Call(F.Field(F.This(), _promiseOfValueOrEndField), promise_GetResult, versionLocal))));
// return new ValueTask(this, version);
// Note: we fall back to this slower method of returning when the promise doesn't yet have a value.
// This method of returning relies on two interface calls (`IValueTaskSource.GetStatus(version)` and `IValueTaskSource.GetResult(version)`).
var returnStatement = F.Return(F.New(valueTaskT_ctor, F.This(), versionLocal));
F.CloseMethod(F.Block(
ImmutableArray.Create(instSymbol, versionSymbol),
ifFinished,
callReset, // _promiseOfValueOrEnd.Reset();
instAssignment, // var inst = this;
startCall, // _builder.Start(ref inst);
versionInit,
ifPromiseReady,
returnStatement));
}
///
/// Prepares most of the parts for MoveNextAsync() and DisposeAsync() methods.
///
private void GetPartsForStartingMachine(out BoundExpressionStatement callReset, out LocalSymbol instSymbol, out BoundStatement instAssignment,
out BoundExpressionStatement startCall, out MethodSymbol promise_get_Version)
{
// Produce the following parts:
// - _promiseOfValueOrEnd.Reset();
// - var inst = this;
// - _builder.Start(ref inst);
// - _valueOrEndPromise.Version
// _promiseOfValueOrEnd.Reset();
BoundFieldAccess promiseField = F.InstanceField(_promiseOfValueOrEndField);
var resetMethod = (MethodSymbol)F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__Reset, isOptional: true)
.SymbolAsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
callReset = F.ExpressionStatement(F.Call(promiseField, resetMethod));
// _builder.Start(ref inst);
Debug.Assert(!_asyncMethodBuilderMemberCollection.CheckGenericMethodConstraints);
MethodSymbol startMethod = _asyncMethodBuilderMemberCollection.Start.Construct(this.stateMachineType);
instSymbol = F.SynthesizedLocal(this.stateMachineType);
// var inst = this;
var instLocal = F.Local(instSymbol);
instAssignment = F.Assignment(instLocal, F.This());
// _builder.Start(ref inst);
startCall = F.ExpressionStatement(
F.Call(
F.InstanceField(_builderField),
startMethod,
ImmutableArray.Create(instLocal)));
// _valueOrEndPromise.Version
promise_get_Version = F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__get_Version)
.AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
}
///
/// Generates the `ValueTask IAsyncDisposable.DisposeAsync()` method.
/// The DisposeAsync method should not be called from states -1 (running) or 0-and-up (awaits).
///
[SuppressMessage("Style", "VSTHRD200:Use \"Async\" suffix for async methods", Justification = "Standard naming convention for generating 'IAsyncDisposable.DisposeAsync'")]
private void GenerateIAsyncDisposable_DisposeAsync()
{
// Produce:
// if (state >= StateMachineStates.NotStartedStateMachine /* -3 */)
// {
// throw new NotSupportedException();
// }
// if (state == StateMachineStates.FinishedStateMachine /* -2 */)
// {
// return default;
// }
// disposeMode = true;
// _valueOrEndPromise.Reset();
// var inst = this;
// _builder.Start(ref inst);
// return new ValueTask(this, _valueOrEndPromise.Version);
MethodSymbol IAsyncDisposable_DisposeAsync = F.WellKnownMethod(WellKnownMember.System_IAsyncDisposable__DisposeAsync);
// The implementation doesn't depend on the method body of the iterator method.
OpenMethodImplementation(IAsyncDisposable_DisposeAsync, hasMethodBodyDependency: false);
TypeSymbol returnType = IAsyncDisposable_DisposeAsync.ReturnType;
GetPartsForStartingMachine(out BoundExpressionStatement callReset,
out LocalSymbol instSymbol,
out BoundStatement instAssignment,
out BoundExpressionStatement startCall,
out MethodSymbol promise_get_Version);
BoundStatement ifInvalidState = F.If(
// if (state >= StateMachineStates.NotStartedStateMachine /* -1 */)
F.IntGreaterThanOrEqual(F.InstanceField(stateField), F.Literal(StateMachineStates.NotStartedStateMachine)),
// throw new NotSupportedException();
thenClause: F.Throw(F.New(F.WellKnownType(WellKnownType.System_NotSupportedException))));
BoundStatement ifFinished = F.If(
// if (state == StateMachineStates.FinishedStateMachine)
F.IntEqual(F.InstanceField(stateField), F.Literal(StateMachineStates.FinishedStateMachine)),
// return default;
thenClause: F.Return(F.Default(returnType)));
MethodSymbol valueTask_ctor =
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_ValueTask__ctor)
.AsMember((NamedTypeSymbol)IAsyncDisposable_DisposeAsync.ReturnType);
// return new ValueTask(this, _valueOrEndPromise.Version);
var returnStatement = F.Return(F.New(valueTask_ctor, F.This(), F.Call(F.InstanceField(_promiseOfValueOrEndField), promise_get_Version)));
F.CloseMethod(F.Block(
ImmutableArray.Create(instSymbol),
ifInvalidState,
ifFinished,
F.Assignment(F.InstanceField(_disposeModeField), F.Literal(true)), // disposeMode = true;
callReset, // _promiseOfValueOrEnd.Reset();
instAssignment, // var inst = this;
startCall, // _builder.Start(ref inst);
returnStatement));
}
///
/// Generates the Current property.
///
private void GenerateIAsyncEnumeratorImplementation_Current()
{
// Produce the implementation for `T Current { get; }`:
// return _current;
NamedTypeSymbol IAsyncEnumeratorOfElementType =
F.WellKnownType(WellKnownType.System_Collections_Generic_IAsyncEnumerator_T)
.Construct(_currentField.Type);
MethodSymbol IAsyncEnumerableOfElementType_get_Current =
F.WellKnownMethod(WellKnownMember.System_Collections_Generic_IAsyncEnumerator_T__get_Current)
.AsMember(IAsyncEnumeratorOfElementType);
OpenPropertyImplementation(IAsyncEnumerableOfElementType_get_Current);
F.CloseMethod(F.Block(F.Return(F.InstanceField(_currentField))));
}
private void GenerateIValueTaskSourceBoolImplementation_GetResult()
{
// Produce the implementation for `bool IValueTaskSource.GetResult(short token)`:
// return _valueOrEndPromise.GetResult(token);
NamedTypeSymbol IValueTaskSourceOfBool =
F.WellKnownType(WellKnownType.System_Threading_Tasks_Sources_IValueTaskSource_T)
.Construct(F.SpecialType(SpecialType.System_Boolean));
MethodSymbol IValueTaskSourceOfBool_GetResult =
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_IValueTaskSource_T__GetResult)
.AsMember(IValueTaskSourceOfBool);
MethodSymbol promise_GetResult =
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__GetResult)
.AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
// The implementation doesn't depend on the method body of the iterator method.
OpenMethodImplementation(IValueTaskSourceOfBool_GetResult, hasMethodBodyDependency: false);
// return this._valueOrEndPromise.GetResult(token);
F.CloseMethod(F.Return(
F.Call(F.InstanceField(_promiseOfValueOrEndField), promise_GetResult, F.Parameter(IValueTaskSourceOfBool_GetResult.Parameters[0]))));
}
private void GenerateIValueTaskSourceBoolImplementation_GetStatus()
{
// Produce the implementation for `ValueTaskSourceStatus IValueTaskSource.GetStatus(short token)`:
// return this._valueOrEndPromise.GetStatus(token);
NamedTypeSymbol IValueTaskSourceOfBool =
F.WellKnownType(WellKnownType.System_Threading_Tasks_Sources_IValueTaskSource_T)
.Construct(F.SpecialType(SpecialType.System_Boolean));
MethodSymbol IValueTaskSourceOfBool_GetStatus =
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_IValueTaskSource_T__GetStatus)
.AsMember(IValueTaskSourceOfBool);
MethodSymbol promise_GetStatus =
F.WellKnownMethod(WellKnownMember.System_Threading_Tasks_Sources_ManualResetValueTaskSourceCore_T__GetStatus)
.AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
// The implementation doesn't depend on the method body of the iterator method.
OpenMethodImplementation(IValueTaskSourceOfBool_GetStatus, hasMethodBodyDependency: false);
// return this._valueOrEndPromise.GetStatus(token);
F.CloseMethod(F.Return(
F.Call(F.InstanceField(_promiseOfValueOrEndField), promise_GetStatus, F.Parameter(IValueTaskSourceOfBool_GetStatus.Parameters[0]))));
}
private void GenerateIValueTaskSourceBoolImplementation_OnCompleted()
{
// Produce the implementation for `void IValueTaskSource.OnCompleted(Action