diff --git a/eng/Versions.props b/eng/Versions.props
index 59017cb7ada3d..e9b51a29fbeee 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -93,8 +93,8 @@
0.8.31-beta
1.0.35
1.4.0
- 1.1.0-beta2-21528-01
- 1.1.0-beta2-21528-01
+ 1.1.0-beta2-22273-03
+ 1.1.0-beta2-22273-03
17.0.0-beta1.21524.1
1.7.0-beta-21528-01
5.0.0
diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
index 505f9aebffbcf..7478bf5a2d924 100644
--- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
+++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
@@ -264,6 +264,7 @@ private static MethodSymbol GetEntryPoint(CSharpCompilation compilation, PEModul
VariableSlotAllocator lazyVariableSlotAllocator = null;
var lambdaDebugInfoBuilder = ArrayBuilder.GetInstance();
var closureDebugInfoBuilder = ArrayBuilder.GetInstance();
+ var stateMachineStateDebugInfoBuilder = ArrayBuilder.GetInstance();
StateMachineTypeSymbol stateMachineTypeOpt = null;
const int methodOrdinal = -1;
@@ -280,6 +281,7 @@ private static MethodSymbol GetEntryPoint(CSharpCompilation compilation, PEModul
ref lazyVariableSlotAllocator,
lambdaDebugInfoBuilder,
closureDebugInfoBuilder,
+ stateMachineStateDebugInfoBuilder,
out stateMachineTypeOpt);
Debug.Assert((object)lazyVariableSlotAllocator == null);
@@ -287,9 +289,11 @@ private static MethodSymbol GetEntryPoint(CSharpCompilation compilation, PEModul
Debug.Assert(dynamicAnalysisSpans.IsEmpty);
Debug.Assert(lambdaDebugInfoBuilder.IsEmpty());
Debug.Assert(closureDebugInfoBuilder.IsEmpty());
+ Debug.Assert(stateMachineStateDebugInfoBuilder.IsEmpty());
lambdaDebugInfoBuilder.Free();
closureDebugInfoBuilder.Free();
+ stateMachineStateDebugInfoBuilder.Free();
if (emitMethodBodies)
{
@@ -300,6 +304,7 @@ private static MethodSymbol GetEntryPoint(CSharpCompilation compilation, PEModul
loweredBody,
ImmutableArray.Empty,
ImmutableArray.Empty,
+ ImmutableArray.Empty,
stateMachineTypeOpt: null,
variableSlotAllocatorOpt: null,
diagnostics: diagnostics,
@@ -698,6 +703,7 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
return;
}
+ var stateMachineStateDebugInfoBuilder = ArrayBuilder.GetInstance();
var oldImportChain = compilationState.CurrentImportChain;
try
{
@@ -727,13 +733,13 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
{
// Local functions can be iterators as well as be async (lambdas can only be async), so we need to lower both iterators and async
IteratorStateMachine iteratorStateMachine;
- BoundStatement loweredBody = IteratorRewriter.Rewrite(methodWithBody.Body, method, methodOrdinal, variableSlotAllocatorOpt, compilationState, diagnosticsThisMethod, out iteratorStateMachine);
+ BoundStatement loweredBody = IteratorRewriter.Rewrite(methodWithBody.Body, method, methodOrdinal, stateMachineStateDebugInfoBuilder, variableSlotAllocatorOpt, compilationState, diagnosticsThisMethod, out iteratorStateMachine);
StateMachineTypeSymbol stateMachine = iteratorStateMachine;
if (!loweredBody.HasErrors)
{
AsyncStateMachine asyncStateMachine;
- loweredBody = AsyncRewriter.Rewrite(loweredBody, method, methodOrdinal, variableSlotAllocatorOpt, compilationState, diagnosticsThisMethod, out asyncStateMachine);
+ loweredBody = AsyncRewriter.Rewrite(loweredBody, method, methodOrdinal, stateMachineStateDebugInfoBuilder, variableSlotAllocatorOpt, compilationState, diagnosticsThisMethod, out asyncStateMachine);
Debug.Assert((object)iteratorStateMachine == null || (object)asyncStateMachine == null);
stateMachine = stateMachine ?? asyncStateMachine;
@@ -751,6 +757,7 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
loweredBody,
ImmutableArray.Empty,
ImmutableArray.Empty,
+ stateMachineStateDebugInfoBuilder.ToImmutable(),
stateMachine,
variableSlotAllocatorOpt,
diagnosticsThisMethod,
@@ -784,11 +791,14 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
{
Debug.Assert(emittedBody is null);
}
+
+ stateMachineStateDebugInfoBuilder.Clear();
}
}
finally
{
compilationState.CurrentImportChain = oldImportChain;
+ stateMachineStateDebugInfoBuilder.Free();
}
}
@@ -868,6 +878,7 @@ private void CompileFieldLikeEventAccessor(SourceEventSymbol eventSymbol, bool i
boundBody,
ImmutableArray.Empty,
ImmutableArray.Empty,
+ ImmutableArray.Empty,
stateMachineTypeOpt: null,
variableSlotAllocatorOpt: null,
diagnostics: diagnosticsThisMethod,
@@ -1185,6 +1196,7 @@ forSemanticModel.Syntax is { } semanticModelSyntax &&
StateMachineTypeSymbol stateMachineTypeOpt = null;
var lambdaDebugInfoBuilder = ArrayBuilder.GetInstance();
var closureDebugInfoBuilder = ArrayBuilder.GetInstance();
+ var stateMachineStateDebugInfoBuilder = ArrayBuilder.GetInstance();
BoundStatement loweredBodyOpt = null;
try
@@ -1204,6 +1216,7 @@ forSemanticModel.Syntax is { } semanticModelSyntax &&
ref lazyVariableSlotAllocator,
lambdaDebugInfoBuilder,
closureDebugInfoBuilder,
+ stateMachineStateDebugInfoBuilder,
out stateMachineTypeOpt);
Debug.Assert(loweredBodyOpt != null);
@@ -1256,6 +1269,7 @@ forSemanticModel.Syntax is { } semanticModelSyntax &&
ref lazyVariableSlotAllocator,
lambdaDebugInfoBuilder,
closureDebugInfoBuilder,
+ stateMachineStateDebugInfoBuilder,
out initializerStateMachineTypeOpt);
processedInitializers.LoweredInitializers = lowered;
@@ -1316,6 +1330,7 @@ forSemanticModel.Syntax is { } semanticModelSyntax &&
boundBody,
lambdaDebugInfoBuilder.ToImmutable(),
closureDebugInfoBuilder.ToImmutable(),
+ stateMachineStateDebugInfoBuilder.ToImmutable(),
stateMachineTypeOpt,
lazyVariableSlotAllocator,
diagsForCurrentMethod,
@@ -1336,6 +1351,7 @@ forSemanticModel.Syntax is { } semanticModelSyntax &&
{
lambdaDebugInfoBuilder.Free();
closureDebugInfoBuilder.Free();
+ stateMachineStateDebugInfoBuilder.Free();
}
}
finally
@@ -1359,6 +1375,7 @@ internal static BoundStatement LowerBodyOrInitializer(
ref VariableSlotAllocator lazyVariableSlotAllocator,
ArrayBuilder lambdaDebugInfoBuilder,
ArrayBuilder closureDebugInfoBuilder,
+ ArrayBuilder stateMachineStateDebugInfoBuilder,
out StateMachineTypeSymbol stateMachineTypeOpt)
{
Debug.Assert(compilationState.ModuleBuilderOpt != null);
@@ -1413,10 +1430,7 @@ internal static BoundStatement LowerBodyOrInitializer(
return loweredBody;
}
- if (lazyVariableSlotAllocator == null)
- {
- lazyVariableSlotAllocator = compilationState.ModuleBuilderOpt.TryCreateVariableSlotAllocator(method, method, diagnostics.DiagnosticBag);
- }
+ lazyVariableSlotAllocator ??= compilationState.ModuleBuilderOpt.TryCreateVariableSlotAllocator(method, method, diagnostics.DiagnosticBag);
BoundStatement bodyWithoutLambdas = loweredBody;
if (sawLambdas || sawLocalFunctions)
@@ -1441,7 +1455,7 @@ internal static BoundStatement LowerBodyOrInitializer(
return bodyWithoutLambdas;
}
- BoundStatement bodyWithoutIterators = IteratorRewriter.Rewrite(bodyWithoutLambdas, method, methodOrdinal, lazyVariableSlotAllocator, compilationState, diagnostics,
+ BoundStatement bodyWithoutIterators = IteratorRewriter.Rewrite(bodyWithoutLambdas, method, methodOrdinal, stateMachineStateDebugInfoBuilder, lazyVariableSlotAllocator, compilationState, diagnostics,
out IteratorStateMachine iteratorStateMachine);
if (bodyWithoutIterators.HasErrors)
@@ -1449,7 +1463,7 @@ internal static BoundStatement LowerBodyOrInitializer(
return bodyWithoutIterators;
}
- BoundStatement bodyWithoutAsync = AsyncRewriter.Rewrite(bodyWithoutIterators, method, methodOrdinal, lazyVariableSlotAllocator, compilationState, diagnostics,
+ BoundStatement bodyWithoutAsync = AsyncRewriter.Rewrite(bodyWithoutIterators, method, methodOrdinal, stateMachineStateDebugInfoBuilder, lazyVariableSlotAllocator, compilationState, diagnostics,
out AsyncStateMachine asyncStateMachine);
Debug.Assert((object)iteratorStateMachine == null || (object)asyncStateMachine == null);
@@ -1474,6 +1488,7 @@ private static MethodBody GenerateMethodBody(
BoundStatement block,
ImmutableArray lambdaDebugInfo,
ImmutableArray closureDebugInfo,
+ ImmutableArray stateMachineStateDebugInfos,
StateMachineTypeSymbol stateMachineTypeOpt,
VariableSlotAllocator variableSlotAllocatorOpt,
BindingDiagnosticBag diagnostics,
@@ -1623,6 +1638,7 @@ private static MethodBody GenerateMethodBody(
stateMachineHoistedLocalScopes,
stateMachineHoistedLocalSlots,
stateMachineAwaiterSlots,
+ StateMachineStatesDebugInfo.Create(variableSlotAllocatorOpt, stateMachineStateDebugInfos),
moveNextBodyDebugInfoOpt,
dynamicAnalysisDataOpt);
}
diff --git a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpDefinitionMap.cs b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpDefinitionMap.cs
index 893d1b9130241..024eafe5e7b33 100644
--- a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpDefinitionMap.cs
+++ b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpDefinitionMap.cs
@@ -192,17 +192,8 @@ protected override ImmutableArray GetLocalSlotMapFromMetadata(Stan
return result;
}
- protected override ITypeSymbolInternal? TryGetStateMachineType(EntityHandle methodHandle)
- {
- string typeName;
- if (_metadataDecoder.Module.HasStringValuedAttribute(methodHandle, AttributeDescription.AsyncStateMachineAttribute, out typeName) ||
- _metadataDecoder.Module.HasStringValuedAttribute(methodHandle, AttributeDescription.IteratorStateMachineAttribute, out typeName))
- {
- return _metadataDecoder.GetTypeSymbolForSerializedType(typeName);
- }
-
- return null;
- }
+ protected override ITypeSymbolInternal? TryGetStateMachineType(MethodDefinitionHandle methodHandle)
+ => _metadataDecoder.Module.HasStateMachineAttribute(methodHandle, out var typeName) ? _metadataDecoder.GetTypeSymbolForSerializedType(typeName) : null;
///
/// Match local declarations to names to generate a map from
diff --git a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncExceptionHandlerRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncExceptionHandlerRewriter.cs
index e070c6be33c39..d8c903fd0d847 100644
--- a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncExceptionHandlerRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncExceptionHandlerRewriter.cs
@@ -135,13 +135,7 @@ public override BoundNode VisitTryStatement(BoundTryStatement node)
var tryStatementSyntax = node.Syntax;
// If you add a syntax kind to the assertion below, please also ensure
// that the scenario has been tested with Edit-and-Continue.
- Debug.Assert(
- tryStatementSyntax.IsKind(SyntaxKind.TryStatement) ||
- tryStatementSyntax.IsKind(SyntaxKind.UsingStatement) ||
- tryStatementSyntax.IsKind(SyntaxKind.ForEachStatement) ||
- tryStatementSyntax.IsKind(SyntaxKind.ForEachVariableStatement) ||
- tryStatementSyntax.IsKind(SyntaxKind.LocalDeclarationStatement) ||
- tryStatementSyntax.IsKind(SyntaxKind.LockStatement));
+ Debug.Assert(SyntaxBindingUtilities.BindsToTryStatement(tryStatementSyntax));
BoundStatement finalizedRegion;
BoundBlock rewrittenFinally;
@@ -711,7 +705,7 @@ public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatemen
private AwaitFinallyFrame PushFrame(BoundTryStatement statement)
{
- var newFrame = new AwaitFinallyFrame(_currentAwaitFinallyFrame, _analysis.Labels(statement), (StatementSyntax)statement.Syntax);
+ var newFrame = new AwaitFinallyFrame(_currentAwaitFinallyFrame, _analysis.Labels(statement), statement.Syntax);
_currentAwaitFinallyFrame = newFrame;
return newFrame;
}
@@ -890,7 +884,7 @@ private sealed class AwaitFinallyFrame
public readonly HashSet LabelsOpt;
// the try or using-await statement the frame is associated with
- private readonly StatementSyntax _statementSyntaxOpt;
+ private readonly SyntaxNode _syntaxOpt;
// proxy labels for branches leaving the frame.
// we build this on demand once we encounter leaving branches.
@@ -909,20 +903,16 @@ public AwaitFinallyFrame()
// root frame
}
- public AwaitFinallyFrame(AwaitFinallyFrame parent, HashSet labelsOpt, StatementSyntax statementSyntax)
+ public AwaitFinallyFrame(AwaitFinallyFrame parent, HashSet labelsOpt, SyntaxNode syntax)
{
Debug.Assert(parent != null);
- Debug.Assert(statementSyntax != null);
+ Debug.Assert(syntax != null);
- Debug.Assert(statementSyntax.Kind() == SyntaxKind.TryStatement ||
- (statementSyntax.Kind() == SyntaxKind.UsingStatement && ((UsingStatementSyntax)statementSyntax).AwaitKeyword != default) ||
- (statementSyntax.Kind() == SyntaxKind.ForEachStatement && ((CommonForEachStatementSyntax)statementSyntax).AwaitKeyword != default) ||
- (statementSyntax.Kind() == SyntaxKind.ForEachVariableStatement && ((CommonForEachStatementSyntax)statementSyntax).AwaitKeyword != default) ||
- (statementSyntax.Kind() == SyntaxKind.LocalDeclarationStatement && ((LocalDeclarationStatementSyntax)statementSyntax).AwaitKeyword != default));
+ Debug.Assert(SyntaxBindingUtilities.BindsToTryStatement(syntax));
this.ParentOpt = parent;
this.LabelsOpt = labelsOpt;
- _statementSyntaxOpt = statementSyntax;
+ _syntaxOpt = syntax;
}
public bool IsRoot()
@@ -983,8 +973,8 @@ public LabelSymbol ProxyReturnIfNeeded(
returnValue = this.returnValue;
if (returnValue == null)
{
- Debug.Assert(_statementSyntaxOpt != null);
- this.returnValue = returnValue = new SynthesizedLocal(containingMethod, TypeWithAnnotations.Create(valueOpt.Type), SynthesizedLocalKind.AsyncMethodReturnValue, _statementSyntaxOpt);
+ Debug.Assert(_syntaxOpt != null);
+ this.returnValue = returnValue = new SynthesizedLocal(containingMethod, TypeWithAnnotations.Create(valueOpt.Type), SynthesizedLocalKind.AsyncMethodReturnValue, _syntaxOpt);
}
}
diff --git a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncIteratorMethodToStateMachineRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncIteratorMethodToStateMachineRewriter.cs
index 704f12678935d..6a5506952a903 100644
--- a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncIteratorMethodToStateMachineRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncIteratorMethodToStateMachineRewriter.cs
@@ -41,9 +41,9 @@ internal sealed class AsyncIteratorMethodToStateMachineRewriter : AsyncMethodToS
private readonly LabelSymbol _exprReturnLabelTrue;
///
- /// States for `yield return` are decreasing from -3.
+ /// States for `yield return` are decreasing from .
///
- private int _nextYieldReturnState = StateMachineStates.InitialAsyncIteratorStateMachine; // -3
+ private readonly ResumableStateMachineStateAllocator _iteratorStateAllocator;
internal AsyncIteratorMethodToStateMachineRewriter(MethodSymbol method,
int methodOrdinal,
@@ -55,20 +55,40 @@ internal AsyncIteratorMethodToStateMachineRewriter(MethodSymbol method,
IReadOnlySet hoistedVariables,
IReadOnlyDictionary nonReusableLocalProxies,
SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals,
+ ArrayBuilder stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
int nextFreeHoistedLocalSlot,
BindingDiagnosticBag diagnostics)
: base(method, methodOrdinal, asyncMethodBuilderMemberCollection, F,
state, builder, hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals,
- slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics)
+ stateMachineStateDebugInfoBuilder, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics)
{
Debug.Assert(asyncIteratorInfo != null);
_asyncIteratorInfo = asyncIteratorInfo;
_currentDisposalLabel = _exprReturnLabel;
_exprReturnLabelTrue = F.GenerateLabel("yieldReturn");
+
+ _iteratorStateAllocator = new ResumableStateMachineStateAllocator(
+ slotAllocatorOpt,
+ firstState: StateMachineStates.FirstResumableAsyncIteratorState,
+ increasing: false);
}
+#nullable enable
+ protected override BoundStatement? GenerateMissingStateDispatch()
+ {
+ var asyncDispatch = base.GenerateMissingStateDispatch();
+
+ var iteratorDispatch = _iteratorStateAllocator.GenerateThrowMissingStateDispatch(F, F.Local(cachedState), CodeAnalysisResources.EncCannotResumeSuspendedIteratorMethod);
+ if (iteratorDispatch == null)
+ {
+ return asyncDispatch;
+ }
+
+ return (asyncDispatch != null) ? F.Block(asyncDispatch, iteratorDispatch) : iteratorDispatch;
+ }
+#nullable disable
protected override BoundStatement GenerateSetResultCall()
{
// ... _exprReturnLabel: ...
@@ -197,7 +217,7 @@ protected override BoundBinaryOperator ShouldEnterFinallyBlock()
// We don't care about state = -2 (method already completed)
// So we only want to enter the finally when the state is -1
- return F.IntEqual(F.Local(cachedState), F.Literal(StateMachineStates.NotStartedStateMachine));
+ return F.IntEqual(F.Local(cachedState), F.Literal(StateMachineStates.NotStartedOrRunningState));
}
#region Visitors
@@ -216,9 +236,7 @@ protected override BoundStatement VisitBody(BoundStatement body)
// this.state = cachedState = -1;
// ... rewritten body
- var initialState = _nextYieldReturnState--;
- Debug.Assert(initialState == -3);
- AddState(initialState, out GeneratedLabelSymbol resumeLabel);
+ AddState(StateMachineStates.InitialAsyncIteratorState, out GeneratedLabelSymbol resumeLabel);
var rewrittenBody = (BoundStatement)Visit(body);
@@ -226,7 +244,7 @@ protected override BoundStatement VisitBody(BoundStatement body)
return F.Block(
F.Label(resumeLabel), // initialStateResumeLabel:
GenerateJumpToCurrentDisposalLabel(), // if (disposeMode) goto _exprReturnLabel;
- GenerateSetBothStates(StateMachineStates.NotStartedStateMachine), // this.state = cachedState = -1;
+ GenerateSetBothStates(StateMachineStates.NotStartedOrRunningState), // this.state = cachedState = -1;
rewrittenBody);
}
@@ -245,8 +263,7 @@ public override BoundNode VisitYieldReturnStatement(BoundYieldReturnStatement no
// _promiseOfValueOrEnd.SetResult(true);
// return;
- var stateNumber = _nextYieldReturnState--;
- AddState(stateNumber, out GeneratedLabelSymbol resumeLabel);
+ AddResumableState(_iteratorStateAllocator, node.Syntax, out var stateNumber, out GeneratedLabelSymbol resumeLabel);
var rewrittenExpression = (BoundExpression)Visit(node.Expression);
var blockBuilder = ArrayBuilder.GetInstance();
@@ -271,7 +288,7 @@ public override BoundNode VisitYieldReturnStatement(BoundYieldReturnStatement no
blockBuilder.Add(
// this.state = cachedState = NotStartedStateMachine
- GenerateSetBothStates(StateMachineStates.NotStartedStateMachine));
+ GenerateSetBothStates(StateMachineStates.NotStartedOrRunningState));
Debug.Assert(_currentDisposalLabel is object); // no yield return allowed inside a finally
blockBuilder.Add(
diff --git a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncMethodToStateMachineRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncMethodToStateMachineRewriter.cs
index 54d51eeb76004..65634991addeb 100644
--- a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncMethodToStateMachineRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncMethodToStateMachineRewriter.cs
@@ -74,10 +74,11 @@ internal AsyncMethodToStateMachineRewriter(
IReadOnlySet hoistedVariables,
IReadOnlyDictionary nonReusableLocalProxies,
SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals,
+ ArrayBuilder stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
int nextFreeHoistedLocalSlot,
BindingDiagnosticBag diagnostics)
- : base(F, method, state, hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics)
+ : base(F, method, state, hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics)
{
_method = method;
_asyncMethodBuilderMemberCollection = asyncMethodBuilderMemberCollection;
@@ -120,6 +121,12 @@ private FieldSymbol GetAwaiterField(TypeSymbol awaiterType)
return result;
}
+ protected sealed override string EncMissingStateMessage
+ => CodeAnalysisResources.EncCannotResumeSuspendedAsyncMethod;
+
+ protected sealed override int FirstIncreasingResumableState
+ => StateMachineStates.FirstResumableAsyncState;
+
///
/// Generate the body for MoveNext().
///
@@ -143,7 +150,7 @@ internal void GenerateMoveNext(BoundStatement body, MethodSymbol moveNextMethod)
F.Block(ImmutableArray.Empty,
// switch (state) ...
F.HiddenSequencePoint(),
- Dispatch(),
+ Dispatch(isOutermost: true),
// [body]
rewrittenBody
),
@@ -154,7 +161,7 @@ internal void GenerateMoveNext(BoundStatement body, MethodSymbol moveNextMethod)
bodyBuilder.Add(F.Label(_exprReturnLabel));
// this.state = finishedState
- var stateDone = F.Assignment(F.Field(F.This(), stateField), F.Literal(StateMachineStates.FinishedStateMachine));
+ var stateDone = F.Assignment(F.Field(F.This(), stateField), F.Literal(StateMachineStates.FinishedState));
var block = body.Syntax as BlockSyntax;
if (block == null)
{
@@ -228,7 +235,7 @@ protected BoundCatchBlock GenerateExceptionHandling(LocalSymbol exceptionLocal,
// _state = finishedState;
BoundStatement assignFinishedState =
- F.ExpressionStatement(F.AssignmentExpression(F.Field(F.This(), stateField), F.Literal(StateMachineStates.FinishedStateMachine)));
+ F.ExpressionStatement(F.AssignmentExpression(F.Field(F.This(), stateField), F.Literal(StateMachineStates.FinishedState)));
// builder.SetException(ex); OR if (this.combinedTokens != null) this.combinedTokens.Dispose(); _promiseOfValueOrEnd.SetException(ex);
BoundStatement callSetException = GenerateSetExceptionCall(exceptionLocal);
@@ -436,7 +443,7 @@ private BoundExpression GenerateGetIsCompleted(LocalSymbol awaiterTemp, MethodSy
private BoundBlock GenerateAwaitForIncompleteTask(LocalSymbol awaiterTemp)
{
- AddState(out int stateNumber, out GeneratedLabelSymbol resumeLabel);
+ AddResumableState(awaiterTemp.GetDeclaratorSyntax(), out int stateNumber, out GeneratedLabelSymbol resumeLabel);
TypeSymbol awaiterFieldType = awaiterTemp.Type.IsVerifierReference()
? F.SpecialType(SpecialType.System_Object)
@@ -490,7 +497,7 @@ private BoundBlock GenerateAwaitForIncompleteTask(LocalSymbol awaiterTemp)
blockBuilder.Add(
// this.state = cachedState = NotStartedStateMachine
- GenerateSetBothStates(StateMachineStates.NotStartedStateMachine));
+ GenerateSetBothStates(StateMachineStates.NotStartedOrRunningState));
return F.Block(blockBuilder.ToImmutableAndFree());
}
diff --git a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.AsyncIteratorRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.AsyncIteratorRewriter.cs
index e445aec99d928..d65f85549dbca 100644
--- a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.AsyncIteratorRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.AsyncIteratorRewriter.cs
@@ -36,10 +36,11 @@ internal AsyncIteratorRewriter(
MethodSymbol method,
int methodOrdinal,
AsyncStateMachine stateMachineType,
+ ArrayBuilder stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
TypeCompilationState compilationState,
BindingDiagnosticBag diagnostics)
- : base(body, method, methodOrdinal, stateMachineType, slotAllocatorOpt, compilationState, diagnostics)
+ : base(body, method, methodOrdinal, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics)
{
Debug.Assert(!TypeSymbol.Equals(method.IteratorElementTypeWithAnnotations.Type, null, TypeCompareKind.ConsiderEverything2));
@@ -194,7 +195,7 @@ private BoundExpressionStatement GenerateCreateAndAssignBuilder()
protected override void InitializeStateMachine(ArrayBuilder bodyBuilder, NamedTypeSymbol frameType, LocalSymbol stateMachineLocal)
{
// var stateMachineLocal = new {StateMachineType}({initialState})
- int initialState = _isEnumerable ? StateMachineStates.FinishedStateMachine : StateMachineStates.InitialAsyncIteratorStateMachine;
+ int initialState = _isEnumerable ? StateMachineStates.FinishedState : StateMachineStates.InitialAsyncIteratorState;
bodyBuilder.Add(
F.Assignment(
F.Local(stateMachineLocal),
@@ -322,7 +323,7 @@ private void GenerateIAsyncEnumeratorImplementation_MoveNextAsync()
BoundStatement ifFinished = F.If(
// if (state == StateMachineStates.FinishedStateMachine)
- F.IntEqual(F.InstanceField(stateField), F.Literal(StateMachineStates.FinishedStateMachine)),
+ F.IntEqual(F.InstanceField(stateField), F.Literal(StateMachineStates.FinishedState)),
// return default;
thenClause: F.Return(F.Default(moveNextAsyncReturnType)));
@@ -432,13 +433,13 @@ private void GenerateIAsyncDisposable_DisposeAsync()
BoundStatement ifInvalidState = F.If(
// if (state >= StateMachineStates.NotStartedStateMachine /* -1 */)
- F.IntGreaterThanOrEqual(F.InstanceField(stateField), F.Literal(StateMachineStates.NotStartedStateMachine)),
+ F.IntGreaterThanOrEqual(F.InstanceField(stateField), F.Literal(StateMachineStates.NotStartedOrRunningState)),
// 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)),
+ F.IntEqual(F.InstanceField(stateField), F.Literal(StateMachineStates.FinishedState)),
// return default;
thenClause: F.Return(F.Default(returnType)));
@@ -650,7 +651,7 @@ private void GenerateIAsyncEnumerableImplementation_GetAsyncEnumerator()
.AsMember(IAsyncEnumerableOfElementType);
BoundExpression managedThreadId = null;
- GenerateIteratorGetEnumerator(IAsyncEnumerableOfElementType_GetEnumerator, ref managedThreadId, initialState: StateMachineStates.InitialAsyncIteratorStateMachine);
+ GenerateIteratorGetEnumerator(IAsyncEnumerableOfElementType_GetEnumerator, ref managedThreadId, initialState: StateMachineStates.InitialAsyncIteratorState);
}
protected override void GenerateResetInstance(ArrayBuilder builder, int initialState)
@@ -697,6 +698,7 @@ protected override void GenerateMoveNext(SynthesizedImplementationMethod moveNex
hoistedVariables: hoistedVariables,
nonReusableLocalProxies: nonReusableLocalProxies,
synthesizedLocalOrdinals: synthesizedLocalOrdinals,
+ stateMachineStateDebugInfoBuilder,
slotAllocatorOpt: slotAllocatorOpt,
nextFreeHoistedLocalSlot: nextFreeHoistedLocalSlot,
diagnostics: diagnostics);
diff --git a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.cs
index d26488e5948d7..6616076c64846 100644
--- a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.cs
@@ -25,10 +25,11 @@ private AsyncRewriter(
MethodSymbol method,
int methodOrdinal,
AsyncStateMachine stateMachineType,
+ ArrayBuilder stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
TypeCompilationState compilationState,
BindingDiagnosticBag diagnostics)
- : base(body, method, stateMachineType, slotAllocatorOpt, compilationState, diagnostics)
+ : base(body, method, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics)
{
_constructedSuccessfully = AsyncMethodBuilderMemberCollection.TryCreate(F, method, this.stateMachineType.TypeMap, out _asyncMethodBuilderMemberCollection);
_methodOrdinal = methodOrdinal;
@@ -41,6 +42,7 @@ internal static BoundStatement Rewrite(
BoundStatement bodyWithAwaitLifted,
MethodSymbol method,
int methodOrdinal,
+ ArrayBuilder stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
TypeCompilationState compilationState,
BindingDiagnosticBag diagnostics,
@@ -73,8 +75,8 @@ internal static BoundStatement Rewrite(
compilationState.ModuleBuilderOpt.CompilationState.SetStateMachineType(method, stateMachineType);
AsyncRewriter rewriter = isAsyncEnumerableOrEnumerator
- ? new AsyncIteratorRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, slotAllocatorOpt, compilationState, diagnostics)
- : new AsyncRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, slotAllocatorOpt, compilationState, diagnostics);
+ ? new AsyncIteratorRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics)
+ : new AsyncRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics);
if (!rewriter.VerifyPresenceOfRequiredAPIs())
{
@@ -228,7 +230,7 @@ protected override BoundStatement GenerateStateMachineCreation(LocalSymbol state
bodyBuilder.Add(
F.Assignment(
F.Field(F.Local(stateMachineVariable), stateField.AsMember(frameType)),
- F.Literal(StateMachineStates.NotStartedStateMachine)));
+ F.Literal(StateMachineStates.NotStartedOrRunningState)));
// local.$builder.Start(ref local) -- binding to the method AsyncTaskMethodBuilder.Start()
var startMethod = methodScopeAsyncMethodBuilderMemberCollection.Start.Construct(frameType);
@@ -265,6 +267,7 @@ protected virtual void GenerateMoveNext(SynthesizedImplementationMethod moveNext
hoistedVariables: hoistedVariables,
nonReusableLocalProxies: nonReusableLocalProxies,
synthesizedLocalOrdinals: synthesizedLocalOrdinals,
+ stateMachineStateDebugInfoBuilder,
slotAllocatorOpt: slotAllocatorOpt,
nextFreeHoistedLocalSlot: nextFreeHoistedLocalSlot,
diagnostics: diagnostics);
diff --git a/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorMethodToStateMachineRewriter.IteratorFinallyFrame.cs b/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorMethodToStateMachineRewriter.IteratorFinallyFrame.cs
index d1acb500db5af..24656238528aa 100644
--- a/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorMethodToStateMachineRewriter.IteratorFinallyFrame.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorMethodToStateMachineRewriter.IteratorFinallyFrame.cs
@@ -57,7 +57,7 @@ public IteratorFinallyFrame(
public IteratorFinallyFrame()
{
- this.finalizeState = StateMachineStates.NotStartedStateMachine;
+ this.finalizeState = StateMachineStates.NotStartedOrRunningState;
}
public bool IsRoot()
diff --git a/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorMethodToStateMachineRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorMethodToStateMachineRewriter.cs
index 8de0bbf1aba92..2b647596d65c3 100644
--- a/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorMethodToStateMachineRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorMethodToStateMachineRewriter.cs
@@ -53,7 +53,7 @@ internal sealed partial class IteratorMethodToStateMachineRewriter : MethodToSta
/// The purpose of distinct finally states is to have enough information about
/// which finally handlers must run when we need to finalize iterator after a fault.
///
- private int _nextFinalizeState = StateMachineStates.FinishedStateMachine - 1; // -3
+ private int _nextFinalizeState;
internal IteratorMethodToStateMachineRewriter(
SyntheticBoundNodeFactory F,
@@ -63,14 +63,23 @@ internal IteratorMethodToStateMachineRewriter(
IReadOnlySet hoistedVariables,
IReadOnlyDictionary nonReusableLocalProxies,
SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals,
+ ArrayBuilder stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
int nextFreeHoistedLocalSlot,
BindingDiagnosticBag diagnostics)
- : base(F, originalMethod, state, hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics)
+ : base(F, originalMethod, state, hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics)
{
_current = current;
+
+ _nextFinalizeState = slotAllocatorOpt?.GetFirstUnusedStateMachineState(increasing: false) ?? StateMachineStates.FirstIteratorFinalizeState;
}
+ protected override string EncMissingStateMessage
+ => CodeAnalysisResources.EncCannotResumeSuspendedIteratorMethod;
+
+ protected override int FirstIncreasingResumableState
+ => StateMachineStates.FirstResumableIteratorState;
+
internal void GenerateMoveNextAndDispose(BoundStatement body, SynthesizedImplementationMethod moveNextMethod, SynthesizedImplementationMethod disposeMethod)
{
// scan body for yielding try blocks
@@ -86,9 +95,7 @@ internal void GenerateMoveNextAndDispose(BoundStatement body, SynthesizedImpleme
///////////////////////////////////
F.CurrentFunction = moveNextMethod;
- int initialState;
- GeneratedLabelSymbol initialLabel;
- AddState(out initialState, out initialLabel);
+ AddState(StateMachineStates.InitialIteratorState, out GeneratedLabelSymbol initialLabel);
var newBody = (BoundStatement)Visit(body);
// switch(cachedState) {
@@ -108,10 +115,10 @@ internal void GenerateMoveNextAndDispose(BoundStatement body, SynthesizedImpleme
F.HiddenSequencePoint(),
F.Assignment(F.Local(cachedState), F.Field(F.This(), stateField)),
CacheThisIfNeeded(),
- Dispatch(),
+ Dispatch(isOutermost: true),
GenerateReturn(finished: true),
F.Label(initialLabel),
- F.Assignment(F.Field(F.This(), stateField), F.Literal(StateMachineStates.NotStartedStateMachine)),
+ F.Assignment(F.Field(F.This(), stateField), F.Literal(StateMachineStates.NotStartedOrRunningState)),
newBody);
//
@@ -321,9 +328,7 @@ public override BoundNode VisitYieldReturnStatement(BoundYieldReturnStatement no
// : ;
//
// this.state = finalizeState;
- int stateNumber;
- GeneratedLabelSymbol resumeLabel;
- AddState(out stateNumber, out resumeLabel);
+ AddResumableState(node.Syntax, out int stateNumber, out GeneratedLabelSymbol resumeLabel);
_currentFinallyFrame.AddState(stateNumber);
var rewrittenExpression = (BoundExpression)Visit(node.Expression);
@@ -453,11 +458,18 @@ public override BoundNode VisitTryStatement(BoundTryStatement node)
private IteratorFinallyFrame PushFrame(BoundTryStatement statement)
{
- var state = _nextFinalizeState--;
+ var syntax = statement.Syntax;
+
+ if (slotAllocatorOpt?.TryGetPreviousStateMachineState(syntax, out var finalizeState) != true)
+ {
+ finalizeState = _nextFinalizeState--;
+ }
+
+ AddStateDebugInfo(syntax, finalizeState);
- var finallyMethod = MakeSynthesizedFinally(state);
- var newFrame = new IteratorFinallyFrame(_currentFinallyFrame, state, finallyMethod, _yieldsInTryAnalysis.Labels(statement));
- newFrame.AddState(state);
+ var finallyMethod = MakeSynthesizedFinally(finalizeState);
+ var newFrame = new IteratorFinallyFrame(_currentFinallyFrame, finalizeState, finallyMethod, _yieldsInTryAnalysis.Labels(statement));
+ newFrame.AddState(finalizeState);
_currentFinallyFrame = newFrame;
return newFrame;
@@ -474,10 +486,10 @@ private bool ContainsYields(BoundTryStatement statement)
return _yieldsInTryAnalysis.ContainsYields(statement);
}
- private IteratorFinallyMethodSymbol MakeSynthesizedFinally(int state)
+ private IteratorFinallyMethodSymbol MakeSynthesizedFinally(int finalizeState)
{
var stateMachineType = (IteratorStateMachine)F.CurrentType;
- var finallyMethod = new IteratorFinallyMethodSymbol(stateMachineType, GeneratedNames.MakeIteratorFinallyMethodName(state));
+ var finallyMethod = new IteratorFinallyMethodSymbol(stateMachineType, GeneratedNames.MakeIteratorFinallyMethodName(finalizeState));
F.ModuleBuilderOpt.AddSynthesizedDefinition(stateMachineType, finallyMethod.GetCciAdapter());
return finallyMethod;
diff --git a/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorRewriter.cs
index 4c3ab2c33e4b2..a1429a11033e7 100644
--- a/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorRewriter.cs
@@ -30,10 +30,11 @@ private IteratorRewriter(
MethodSymbol method,
bool isEnumerable,
IteratorStateMachine stateMachineType,
+ ArrayBuilder stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
TypeCompilationState compilationState,
BindingDiagnosticBag diagnostics)
- : base(body, method, stateMachineType, slotAllocatorOpt, compilationState, diagnostics)
+ : base(body, method, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics)
{
// the element type may contain method type parameters, which are now alpha-renamed into type parameters of the generated class
_elementType = stateMachineType.ElementType;
@@ -48,6 +49,7 @@ internal static BoundStatement Rewrite(
BoundStatement body,
MethodSymbol method,
int methodOrdinal,
+ ArrayBuilder stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
TypeCompilationState compilationState,
BindingDiagnosticBag diagnostics,
@@ -80,7 +82,7 @@ internal static BoundStatement Rewrite(
stateMachineType = new IteratorStateMachine(slotAllocatorOpt, compilationState, method, methodOrdinal, isEnumerable, elementType);
compilationState.ModuleBuilderOpt.CompilationState.SetStateMachineType(method, stateMachineType);
- var rewriter = new IteratorRewriter(body, method, isEnumerable, stateMachineType, slotAllocatorOpt, compilationState, diagnostics);
+ var rewriter = new IteratorRewriter(body, method, isEnumerable, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics);
if (!rewriter.VerifyPresenceOfRequiredAPIs())
{
return body;
@@ -248,7 +250,7 @@ private void GenerateEnumerableImplementation(ref BoundExpression managedThreadI
var IEnumerableOfElementType_GetEnumerator = F.SpecialMethod(SpecialMember.System_Collections_Generic_IEnumerable_T__GetEnumerator).AsMember(IEnumerableOfElementType);
// generate GetEnumerator()
- var getEnumeratorGeneric = GenerateIteratorGetEnumerator(IEnumerableOfElementType_GetEnumerator, ref managedThreadId, StateMachineStates.FirstUnusedState);
+ var getEnumeratorGeneric = GenerateIteratorGetEnumerator(IEnumerableOfElementType_GetEnumerator, ref managedThreadId, StateMachineStates.InitialIteratorState);
// Generate IEnumerable.GetEnumerator
var getEnumerator = OpenMethodImplementation(IEnumerable_GetEnumerator);
@@ -285,7 +287,7 @@ protected override void InitializeStateMachine(ArrayBuilder body
{
// var stateMachineLocal = new IteratorImplementationClass(N)
// where N is either 0 (if we're producing an enumerator) or -2 (if we're producing an enumerable)
- int initialState = _isEnumerable ? StateMachineStates.FinishedStateMachine : StateMachineStates.FirstUnusedState;
+ int initialState = _isEnumerable ? StateMachineStates.FinishedState : StateMachineStates.InitialIteratorState;
bodyBuilder.Add(
F.Assignment(
F.Local(stateMachineLocal),
@@ -318,6 +320,7 @@ private void GenerateMoveNextAndDispose(
hoistedVariables,
nonReusableLocalProxies,
synthesizedLocalOrdinals,
+ stateMachineStateDebugInfoBuilder,
slotAllocatorOpt,
nextFreeHoistedLocalSlot,
diagnostics);
diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_UsingStatement.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_UsingStatement.cs
index 4a7083be57f42..41ecea365c121 100644
--- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_UsingStatement.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_UsingStatement.cs
@@ -186,7 +186,7 @@ private BoundBlock MakeExpressionUsingStatement(BoundUsingStatement node, BoundB
expressionStatement = _instrumenter.InstrumentUsingTargetCapture(node, expressionStatement);
}
- BoundStatement tryFinally = RewriteUsingStatementTryFinally(usingSyntax, tryBlock, boundTemp, usingSyntax.AwaitKeyword, node.AwaitOpt, node.PatternDisposeInfoOpt);
+ BoundStatement tryFinally = RewriteUsingStatementTryFinally(usingSyntax, usingSyntax, tryBlock, boundTemp, usingSyntax.AwaitKeyword, node.AwaitOpt, node.PatternDisposeInfoOpt);
// { ResourceType temp = expr; try { ... } finally { ... } }
return new BoundBlock(
@@ -229,7 +229,7 @@ private BoundBlock RewriteDeclarationUsingStatement(
if (boundLocal.ConstantValue == ConstantValue.Null)
{
//localSymbol will be declared by an enclosing block
- return BoundBlock.SynthesizedNoLocals(usingSyntax, rewrittenDeclaration, tryBlock);
+ return BoundBlock.SynthesizedNoLocals(declarationSyntax, rewrittenDeclaration, tryBlock);
}
if (localType.IsDynamic())
@@ -250,10 +250,10 @@ private BoundBlock RewriteDeclarationUsingStatement(
BoundAssignmentOperator tempAssignment;
BoundLocal boundTemp = _factory.StoreToTemp(tempInit, out tempAssignment, kind: SynthesizedLocalKind.Using);
- BoundStatement tryFinally = RewriteUsingStatementTryFinally(usingSyntax, tryBlock, boundTemp, awaitKeywordOpt, awaitOpt, patternDisposeInfo);
+ BoundStatement tryFinally = RewriteUsingStatementTryFinally(usingSyntax, declarationSyntax, tryBlock, boundTemp, awaitKeywordOpt, awaitOpt, patternDisposeInfo);
return new BoundBlock(
- syntax: usingSyntax,
+ syntax: declarationSyntax,
locals: ImmutableArray.Create(boundTemp.LocalSymbol), //localSymbol will be declared by an enclosing block
statements: ImmutableArray.Create(
rewrittenDeclaration,
@@ -262,14 +262,15 @@ private BoundBlock RewriteDeclarationUsingStatement(
}
else
{
- BoundStatement tryFinally = RewriteUsingStatementTryFinally(usingSyntax, tryBlock, boundLocal, awaitKeywordOpt, awaitOpt, patternDisposeInfo);
+ BoundStatement tryFinally = RewriteUsingStatementTryFinally(usingSyntax, declarationSyntax, tryBlock, boundLocal, awaitKeywordOpt, awaitOpt, patternDisposeInfo);
// localSymbol will be declared by an enclosing block
- return BoundBlock.SynthesizedNoLocals(usingSyntax, rewrittenDeclaration, tryFinally);
+ return BoundBlock.SynthesizedNoLocals(declarationSyntax, rewrittenDeclaration, tryFinally);
}
}
private BoundStatement RewriteUsingStatementTryFinally(
+ SyntaxNode typeSyntax,
SyntaxNode syntax,
BoundBlock tryBlock,
BoundLocal local,
@@ -352,7 +353,7 @@ private BoundStatement RewriteUsingStatementTryFinally(
if (isNullableValueType)
{
- MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(syntax, local.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
+ MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(typeSyntax, local.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
// local.GetValueOrDefault()
disposedExpression = BoundCall.Synthesized(syntax, local, getValueOrDefault);
}
@@ -362,7 +363,7 @@ private BoundStatement RewriteUsingStatementTryFinally(
disposedExpression = local;
}
- BoundExpression disposeCall = GenerateDisposeCall(syntax, disposedExpression, patternDisposeInfo, awaitOpt, awaitKeywordOpt);
+ BoundExpression disposeCall = GenerateDisposeCall(typeSyntax, syntax, disposedExpression, patternDisposeInfo, awaitOpt, awaitKeywordOpt);
// local.Dispose(); or await variant
BoundStatement disposeStatement = new BoundExpressionStatement(syntax, disposeCall);
@@ -419,6 +420,7 @@ private BoundStatement RewriteUsingStatementTryFinally(
}
private BoundExpression GenerateDisposeCall(
+ SyntaxNode typeSyntax,
SyntaxNode syntax,
BoundExpression disposedExpression,
MethodArgumentInfo? disposeInfo,
@@ -434,7 +436,7 @@ private BoundExpression GenerateDisposeCall(
if (awaitOpt is null)
{
// IDisposable.Dispose()
- Binder.TryGetSpecialTypeMember(_compilation, SpecialMember.System_IDisposable__Dispose, syntax, _diagnostics, out disposeMethod);
+ Binder.TryGetSpecialTypeMember(_compilation, SpecialMember.System_IDisposable__Dispose, typeSyntax, _diagnostics, out disposeMethod);
}
else
{
diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs
index b0fb061e344da..f9920cb65fbc8 100644
--- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs
@@ -22,11 +22,6 @@ internal abstract class MethodToStateMachineRewriter : MethodToClassRewriter
{
internal readonly MethodSymbol OriginalMethod;
- ///
- /// Generate return statements from the state machine method body.
- ///
- protected abstract BoundStatement GenerateReturn(bool finished);
-
protected readonly SyntheticBoundNodeFactory F;
///
@@ -56,7 +51,10 @@ internal abstract class MethodToStateMachineRewriter : MethodToClassRewriter
///
protected readonly LocalSymbol cachedThis;
- private int _nextState;
+ ///
+ /// Allocates resumable states, i.e. states that resume execution of the state machine after await expression or yield return.
+ ///
+ private readonly ResumableStateMachineStateAllocator _resumableStateAllocator;
///
/// For each distinct label, the set of states that need to be dispatched to that label.
@@ -90,6 +88,11 @@ internal abstract class MethodToStateMachineRewriter : MethodToClassRewriter
private readonly SynthesizedLocalOrdinalsDispenser _synthesizedLocalOrdinals;
private int _nextFreeHoistedLocalSlot;
+ ///
+ /// EnC support: the rewriter stores debug info for each await/yield in this builder.
+ ///
+ private readonly ArrayBuilder _stateDebugInfoBuilder;
+
// new:
public MethodToStateMachineRewriter(
SyntheticBoundNodeFactory F,
@@ -98,6 +101,7 @@ public MethodToStateMachineRewriter(
IReadOnlySet hoistedVariables,
IReadOnlyDictionary nonReusableLocalProxies,
SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals,
+ ArrayBuilder stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
int nextFreeHoistedLocalSlot,
BindingDiagnosticBag diagnostics)
@@ -135,8 +139,27 @@ public MethodToStateMachineRewriter(
BoundExpression thisProxyReplacement = thisProxy.Replacement(F.Syntax, frameType => F.This());
this.cachedThis = F.SynthesizedLocal(thisProxyReplacement.Type, syntax: F.Syntax, kind: SynthesizedLocalKind.FrameCache);
}
+
+ _stateDebugInfoBuilder = stateMachineStateDebugInfoBuilder;
+
+ // Use the first state number that is not used by any previous version of the state machine
+ // for the first added state that doesn't match any states of the previous state machine.
+ // Note the initial states of the previous and the current state machine are always the same.
+ // Note the previous state machine might not have any non-initial states.
+ _resumableStateAllocator = new ResumableStateMachineStateAllocator(
+ slotAllocatorOpt,
+ firstState: FirstIncreasingResumableState,
+ increasing: true);
}
+ protected abstract int FirstIncreasingResumableState { get; }
+ protected abstract string EncMissingStateMessage { get; }
+
+ ///
+ /// Generate return statements from the state machine method body.
+ ///
+ protected abstract BoundStatement GenerateReturn(bool finished);
+
protected override bool NeedsProxy(Symbol localOrParameter)
{
Debug.Assert(localOrParameter.Kind == SymbolKind.Local || localOrParameter.Kind == SymbolKind.Parameter);
@@ -175,33 +198,66 @@ protected override BoundExpression FramePointer(SyntaxNode syntax, NamedTypeSymb
F.Syntax = oldSyntax;
return result;
}
+#nullable enable
+ protected void AddResumableState(SyntaxNode awaitOrYieldReturnSyntax, out int stateNumber, out GeneratedLabelSymbol resumeLabel)
+ => AddResumableState(_resumableStateAllocator, awaitOrYieldReturnSyntax, out stateNumber, out resumeLabel);
- protected void AddState(out int stateNumber, out GeneratedLabelSymbol resumeLabel)
+ protected void AddResumableState(ResumableStateMachineStateAllocator allocator, SyntaxNode awaitOrYieldReturnSyntax, out int stateNumber, out GeneratedLabelSymbol resumeLabel)
{
- stateNumber = _nextState++;
+ stateNumber = allocator.AllocateState(awaitOrYieldReturnSyntax);
+ AddStateDebugInfo(awaitOrYieldReturnSyntax, stateNumber);
AddState(stateNumber, out resumeLabel);
}
+ protected void AddStateDebugInfo(SyntaxNode node, int stateNumber)
+ {
+ Debug.Assert(SyntaxBindingUtilities.BindsToResumableStateMachineState(node) || SyntaxBindingUtilities.BindsToTryStatement(node), $"Unexpected syntax: {node.Kind()}");
+
+ int syntaxOffset = CurrentMethod.CalculateLocalSyntaxOffset(node.SpanStart, node.SyntaxTree);
+ _stateDebugInfoBuilder.Add(new StateMachineStateDebugInfo(syntaxOffset, stateNumber));
+ }
+
protected void AddState(int stateNumber, out GeneratedLabelSymbol resumeLabel)
{
- if (_dispatches == null)
- {
- _dispatches = new Dictionary>();
- }
+ _dispatches ??= new Dictionary>();
resumeLabel = F.GenerateLabel("stateMachine");
- var states = new List();
- states.Add(stateNumber);
- _dispatches.Add(resumeLabel, states);
+ _dispatches.Add(resumeLabel, new List { stateNumber });
}
- protected BoundStatement Dispatch()
- {
- return F.Switch(F.Local(cachedState),
- (from kv in _dispatches orderby kv.Value[0] select F.SwitchSection(kv.Value, F.Goto(kv.Key))).ToImmutableArray()
- );
+ ///
+ /// Generates code that switches over states and jumps to the target labels listed in .
+ ///
+ ///
+ /// If this is the outermost state dispatch switching over all states of the state machine - i.e. not state dispatch generated for a try-block.
+ ///
+ protected BoundStatement Dispatch(bool isOutermost)
+ {
+ var sections = from kv in _dispatches orderby kv.Value[0] select F.SwitchSection(kv.Value, F.Goto(kv.Key));
+ var result = F.Switch(F.Local(cachedState), sections.ToImmutableArray());
+
+ // Suspension states that were generated for any previous generation of the state machine
+ // but are not present in the current version (awaits/yields have been deleted) need to be dispatched to a throw expression.
+ // When an instance of previous version of the state machine is suspended in a state that does not exist anymore
+ // in the current version dispatch that state to a throw expression. We do not know for sure where to resume in the new version of the method.
+ // Guessing would likely result in unexpected behavior. Resuming in an incorrect point might result in an execution of code that
+ // has already been executed or skipping code that initializes some user state.
+ if (isOutermost)
+ {
+ var missingStateDispatch = GenerateMissingStateDispatch();
+ if (missingStateDispatch != null)
+ {
+ result = F.Block(result, missingStateDispatch);
+ }
+ }
+
+ return result;
}
+ protected virtual BoundStatement? GenerateMissingStateDispatch()
+ => _resumableStateAllocator.GenerateThrowMissingStateDispatch(F, F.Local(cachedState), EncMissingStateMessage);
+
+#nullable disable
#if DEBUG
public override BoundNode VisitSequence(BoundSequence node)
{
@@ -775,7 +831,7 @@ public override BoundNode VisitTryStatement(BoundTryStatement node)
tryBlock = F.Block(
F.HiddenSequencePoint(),
- Dispatch(),
+ Dispatch(isOutermost: false),
tryBlock);
oldDispatches ??= new Dictionary>();
diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/ResumableStateMachineStateAllocator.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/ResumableStateMachineStateAllocator.cs
new file mode 100644
index 0000000000000..edb186992cd70
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/ResumableStateMachineStateAllocator.cs
@@ -0,0 +1,95 @@
+// 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;
+using System.Diagnostics;
+using Microsoft.CodeAnalysis.CodeGen;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ ///
+ /// Allocates resumable states, i.e. states that resume execution of the state machine after await expression or yield return.
+ ///
+ internal sealed class ResumableStateMachineStateAllocator
+ {
+ private readonly VariableSlotAllocator? _slotAllocator;
+ private readonly bool _increasing;
+ private readonly int _firstState;
+
+ ///
+ /// The number of the next generated resumable state (i.e. state that resumes execution of the state machine after await expression or yield return).
+ ///
+ private int _nextState;
+
+#if DEBUG
+ ///
+ /// EnC support: states in this state machine that were matched to states of the previous generation state machine.
+ ///
+ private BitVector _matchedStates = BitVector.Empty;
+#endif
+ ///
+ /// EnC support: number of states in this state machine that match states of the previous generation state machine.
+ ///
+ private int _matchedStateCount;
+
+ public ResumableStateMachineStateAllocator(VariableSlotAllocator? slotAllocator, int firstState, bool increasing)
+ {
+ _increasing = increasing;
+ _slotAllocator = slotAllocator;
+ _matchedStateCount = 0;
+ _firstState = firstState;
+ _nextState = slotAllocator?.GetFirstUnusedStateMachineState(increasing) ?? firstState;
+ }
+
+ public int AllocateState(SyntaxNode awaitOrYieldReturnSyntax)
+ {
+ Debug.Assert(SyntaxBindingUtilities.BindsToResumableStateMachineState(awaitOrYieldReturnSyntax));
+
+ int direction = _increasing ? +1 : -1;
+
+ if (_slotAllocator?.TryGetPreviousStateMachineState(awaitOrYieldReturnSyntax, out var stateNumber) == true)
+ {
+#if DEBUG
+ // two states of the new state machine should not match the same state of the previous machine:
+ Debug.Assert(!_matchedStates[stateNumber * direction]);
+ _matchedStates[stateNumber * direction] = true;
+#endif
+ _matchedStateCount++;
+ }
+ else
+ {
+ stateNumber = _nextState;
+ _nextState += direction;
+ }
+
+ return stateNumber;
+ }
+
+ ///
+ /// True if any of the states generated for any previous state machine has not been allocated in this version.
+ ///
+ public bool HasMissingStates
+ => _matchedStateCount < Math.Abs((_slotAllocator?.GetFirstUnusedStateMachineState(_increasing) ?? _firstState) - _firstState);
+
+ public BoundStatement? GenerateThrowMissingStateDispatch(SyntheticBoundNodeFactory f, BoundExpression cachedState, string message)
+ {
+ if (!HasMissingStates)
+ {
+ return null;
+ }
+
+ return f.If(
+ f.Binary(
+ _increasing ? BinaryOperatorKind.IntGreaterThanOrEqual : BinaryOperatorKind.IntLessThanOrEqual,
+ f.SpecialType(SpecialType.System_Boolean),
+ cachedState,
+ f.Literal(_firstState)),
+ f.Throw(
+ f.New(
+ f.WellKnownMethod(WellKnownMember.System_InvalidOperationException__ctorString),
+ f.StringLiteral(ConstantValue.Create(message)))));
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs
index 0616f66995d3a..0ef6f322a3bd2 100644
--- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs
@@ -25,6 +25,7 @@ internal abstract class StateMachineRewriter
protected readonly SynthesizedContainer stateMachineType;
protected readonly VariableSlotAllocator slotAllocatorOpt;
protected readonly SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals;
+ protected readonly ArrayBuilder stateMachineStateDebugInfoBuilder;
protected FieldSymbol stateField;
protected IReadOnlyDictionary nonReusableLocalProxies;
@@ -37,6 +38,7 @@ protected StateMachineRewriter(
BoundStatement body,
MethodSymbol method,
SynthesizedContainer stateMachineType,
+ ArrayBuilder stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
TypeCompilationState compilationState,
BindingDiagnosticBag diagnostics)
@@ -47,10 +49,12 @@ protected StateMachineRewriter(
Debug.Assert(compilationState != null);
Debug.Assert(diagnostics != null);
Debug.Assert(diagnostics.DiagnosticBag != null);
+ Debug.Assert(stateMachineStateDebugInfoBuilder.IsEmpty());
this.body = body;
this.method = method;
this.stateMachineType = stateMachineType;
+ this.stateMachineStateDebugInfoBuilder = stateMachineStateDebugInfoBuilder;
this.slotAllocatorOpt = slotAllocatorOpt;
this.synthesizedLocalOrdinals = new SynthesizedLocalOrdinalsDispenser();
this.diagnostics = diagnostics;
@@ -433,7 +437,7 @@ protected SynthesizedImplementationMethod GenerateIteratorGetEnumerator(MethodSy
makeIterator = F.If(
// if (this.state == -2 && this.initialThreadId == Thread.CurrentThread.ManagedThreadId)
condition: F.LogicalAnd(
- F.IntEqual(F.Field(F.This(), stateField), F.Literal(StateMachineStates.FinishedStateMachine)),
+ F.IntEqual(F.Field(F.This(), stateField), F.Literal(StateMachineStates.FinishedState)),
F.IntEqual(F.Field(F.This(), initialThreadIdField), managedThreadId)),
thenClause: F.Block(thenBuilder.ToImmutableAndFree()),
elseClauseOpt: makeIterator);
diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineStates.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineStates.cs
index debc8437de81e..2f17bf33c8c4b 100644
--- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineStates.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineStates.cs
@@ -2,17 +2,38 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#nullable disable
-
namespace Microsoft.CodeAnalysis.CSharp
{
internal static class StateMachineStates
{
- internal const int FinishedStateMachine = -2;
- internal const int NotStartedStateMachine = -1;
+ internal const int FirstIteratorFinalizeState = -3;
+
+ internal const int FinishedState = -2;
+ internal const int NotStartedOrRunningState = -1;
internal const int FirstUnusedState = 0;
- // used for async-iterators to distinguish initial state from running state (-1) so that DisposeAsync can throw in latter case
- internal const int InitialAsyncIteratorStateMachine = -3;
+ ///
+ /// First state in async state machine that is used to resume the machine after await.
+ ///
+ internal const int FirstResumableAsyncState = 0;
+
+ internal const int InitialIteratorState = 0;
+
+ ///
+ /// First state in iterator state machine that is used to resume the machine after yield return.
+ /// Initial state is not used to resume state machine that yielded.
+ ///
+ internal const int FirstResumableIteratorState = InitialIteratorState + 1;
+
+ ///
+ /// Used for async-iterators to distinguish initial state from so that DisposeAsync can throw in latter case.
+ ///
+ internal const int InitialAsyncIteratorState = -3;
+
+ ///
+ /// First state in async iterator state machine that is used to resume the machine after yield return.
+ /// Initial state is not used to resume state machine that yielded.
+ ///
+ internal const int FirstResumableAsyncIteratorState = InitialAsyncIteratorState - 1;
}
}
diff --git a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs
index 0e80a7df79155..520961b991669 100644
--- a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs
@@ -983,7 +983,9 @@ public BoundStatement Switch(BoundExpression ex, ImmutableArray.GetInstance();
var statements = ArrayBuilder.GetInstance();
statements.Add(null!); // placeholder at statements[0] for the dispatch
diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/GeneratedNames.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/GeneratedNames.cs
index bb89a163099c0..cf9acb4bcd6e0 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/GeneratedNames.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/GeneratedNames.cs
@@ -26,16 +26,14 @@ internal static string MakeBackingFieldName(string propertyName)
return "<" + propertyName + ">k__BackingField";
}
- internal static string MakeIteratorFinallyMethodName(int iteratorState)
- {
- // we can pick any name, but we will try to do
- // <>m__Finally1
- // <>m__Finally2
- // <>m__Finally3
- // . . .
- // that will roughly match native naming scheme and may also be easier when need to debug.
+ internal static string MakeIteratorFinallyMethodName(int finalizeState)
+ {
+ Debug.Assert(finalizeState < -2);
+
+ // It is important that the name is only derived from the finalizeState, so that when
+ // editing method during EnC the Finally methods corresponding to matching states have matching names.
Debug.Assert((char)GeneratedNameKind.IteratorFinallyMethod == 'm');
- return "<>m__Finally" + StringExtensions.GetNumeral(Math.Abs(iteratorState + 2));
+ return "<>m__Finally" + StringExtensions.GetNumeral(-(finalizeState + 2));
}
internal static string MakeStaticLambdaDisplayClassName(int methodOrdinal, int generation)
diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxBindingUtilities.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxBindingUtilities.cs
new file mode 100644
index 0000000000000..16800dd4ecb8e
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxBindingUtilities.cs
@@ -0,0 +1,27 @@
+// 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;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Microsoft.CodeAnalysis.CSharp.Syntax
+{
+ internal static class SyntaxBindingUtilities
+ {
+ public static bool BindsToResumableStateMachineState(SyntaxNode node)
+ => node.IsKind(SyntaxKind.YieldReturnStatement) ||
+ node.IsKind(SyntaxKind.AwaitExpression) ||
+ node is CommonForEachStatementSyntax { AwaitKeyword.RawKind: not 0 }
+ or VariableDeclaratorSyntax { Parent.Parent: UsingStatementSyntax { AwaitKeyword.RawKind: not 0 } or LocalDeclarationStatementSyntax { AwaitKeyword.RawKind: not 0 } }
+ or UsingStatementSyntax { Expression: not null, AwaitKeyword.RawKind: not 0 };
+
+ public static bool BindsToTryStatement(SyntaxNode node)
+ => node is VariableDeclaratorSyntax { Parent.Parent: UsingStatementSyntax { } or LocalDeclarationStatementSyntax { UsingKeyword.RawKind: not 0 } }
+ or UsingStatementSyntax { Expression: not null }
+ or CommonForEachStatementSyntax
+ or TryStatementSyntax
+ or LockStatementSyntax;
+ }
+}
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncEHTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncEHTests.cs
index 7d612c9e4f045..74d72686e20ea 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncEHTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncEHTests.cs
@@ -973,6 +973,10 @@ public static void Main()
+
+
+
+
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncLocalsTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncLocalsTests.cs
index ceecdf8225a84..d4349b1c7f0dd 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncLocalsTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncLocalsTests.cs
@@ -364,6 +364,14 @@ public async Task M(IDisposable disposable)
+
+
+
+
+
+
+
+
diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinuePdbTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinuePdbTests.cs
index 76f7d9a55e97e..5b12f12413060 100644
--- a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinuePdbTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinuePdbTests.cs
@@ -23,7 +23,7 @@ public class EditAndContinuePdbTests : EditAndContinueTestBase
[MemberData(nameof(ExternalPdbFormats))]
public void MethodExtents(DebugInformationFormat format)
{
- var source0 = MarkedSource(WithWindowsLineBreaks(@"#pragma checksum ""C:\Enc1.cs"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""1111111111111111111111111111111111111111""
+ var source0 = MarkedSource(@"#pragma checksum ""C:\Enc1.cs"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""1111111111111111111111111111111111111111""
using System;
public class C
@@ -52,9 +52,9 @@ void G()
};
}
}
-"), fileName: @"C:\Enc1.cs");
+", fileName: @"C:\Enc1.cs");
- var source1 = MarkedSource(WithWindowsLineBreaks(@"#pragma checksum ""C:\Enc1.cs"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""2222222222222222222222222222222222222222""
+ var source1 = MarkedSource(@"#pragma checksum ""C:\Enc1.cs"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""2222222222222222222222222222222222222222""
using System;
public class C
@@ -83,9 +83,9 @@ void G()
int E() => 1;
}
-"), fileName: @"C:\Enc1.cs");
+", fileName: @"C:\Enc1.cs");
- var source2 = MarkedSource(WithWindowsLineBreaks(@"#pragma checksum ""C:\Enc1.cs"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""3333333333333333333333333333333333333333""
+ var source2 = MarkedSource(@"#pragma checksum ""C:\Enc1.cs"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""3333333333333333333333333333333333333333""
using System;
public class C
@@ -116,7 +116,7 @@ void G()
int B() => 4;
}
-"), fileName: @"C:\Enc1.cs");
+", fileName: @"C:\Enc1.cs");
var compilation0 = CreateCompilation(source0.Tree, options: ComSafeDebugDll.WithMetadataImportOptions(MetadataImportOptions.All), assemblyName: "EncMethodExtents");
var compilation1 = compilation0.WithSource(source1.Tree);
diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueStateMachineTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueStateMachineTests.cs
index 4db804c90174b..de960ec8f4dac 100644
--- a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueStateMachineTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueStateMachineTests.cs
@@ -345,78 +345,78 @@ static IEnumerable F()
var v0 = CompileAndVerify(compilation0);
- using (var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData))
- {
- var method0 = compilation0.GetMember("C.F");
- var method1 = compilation1.GetMember("C.F");
+ using var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData);
+ var method0 = compilation0.GetMember("C.F");
+ var method1 = compilation1.GetMember("C.F");
- var generation0 = EmitBaseline.CreateInitialBaseline(md0, EmptyLocalsProvider);
- var diff1 = compilation1.EmitDifference(
- generation0,
- ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method0, method1)));
+ var generation0 = EmitBaseline.CreateInitialBaseline(md0, EmptyLocalsProvider);
+ var diff1 = compilation1.EmitDifference(
+ generation0,
+ ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method0, method1)));
- using (var md1 = diff1.GetMetadata())
- {
- CheckEncLogDefinitions(md1.Reader,
- Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
- Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
- Row(5, TableIndex.TypeDef, EditAndContinueOperation.Default),
- Row(1, TableIndex.PropertyMap, EditAndContinueOperation.Default),
- Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddField),
- Row(2, TableIndex.Field, EditAndContinueOperation.Default),
- Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddField),
- Row(3, TableIndex.Field, EditAndContinueOperation.Default),
- Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddField),
- Row(4, TableIndex.Field, EditAndContinueOperation.Default),
- Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(7, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(8, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(10, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(1, TableIndex.PropertyMap, EditAndContinueOperation.AddProperty),
- Row(1, TableIndex.Property, EditAndContinueOperation.Default),
- Row(1, TableIndex.PropertyMap, EditAndContinueOperation.AddProperty),
- Row(2, TableIndex.Property, EditAndContinueOperation.Default),
- Row(3, TableIndex.MethodDef, EditAndContinueOperation.AddParameter),
- Row(1, TableIndex.Param, EditAndContinueOperation.Default),
- Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(8, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(11, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(12, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(1, TableIndex.MethodSemantics, EditAndContinueOperation.Default),
- Row(2, TableIndex.MethodSemantics, EditAndContinueOperation.Default),
- Row(1, TableIndex.MethodImpl, EditAndContinueOperation.Default),
- Row(2, TableIndex.MethodImpl, EditAndContinueOperation.Default),
- Row(3, TableIndex.MethodImpl, EditAndContinueOperation.Default),
- Row(4, TableIndex.MethodImpl, EditAndContinueOperation.Default),
- Row(5, TableIndex.MethodImpl, EditAndContinueOperation.Default),
- Row(6, TableIndex.MethodImpl, EditAndContinueOperation.Default),
- Row(7, TableIndex.MethodImpl, EditAndContinueOperation.Default),
- Row(2, TableIndex.NestedClass, EditAndContinueOperation.Default),
- Row(1, TableIndex.InterfaceImpl, EditAndContinueOperation.Default),
- Row(2, TableIndex.InterfaceImpl, EditAndContinueOperation.Default),
- Row(3, TableIndex.InterfaceImpl, EditAndContinueOperation.Default),
- Row(4, TableIndex.InterfaceImpl, EditAndContinueOperation.Default),
- Row(5, TableIndex.InterfaceImpl, EditAndContinueOperation.Default));
- }
- }
+ diff1.VerifySynthesizedMembers(
+ "C: {d__0#1}",
+ "C.d__0#1: {<>1__state, <>2__current, <>l__initialThreadId, System.IDisposable.Dispose, MoveNext, System.Collections.Generic.IEnumerator.get_Current, System.Collections.IEnumerator.Reset, System.Collections.IEnumerator.get_Current, System.Collections.Generic.IEnumerable.GetEnumerator, System.Collections.IEnumerable.GetEnumerator, System.Collections.Generic.IEnumerator.Current, System.Collections.IEnumerator.Current}");
+
+ using var md1 = diff1.GetMetadata();
+ CheckEncLogDefinitions(md1.Reader,
+ Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
+ Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.Default),
+ Row(1, TableIndex.PropertyMap, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddField),
+ Row(2, TableIndex.Field, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddField),
+ Row(3, TableIndex.Field, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddField),
+ Row(4, TableIndex.Field, EditAndContinueOperation.Default),
+ Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(7, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(8, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(5, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(10, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(1, TableIndex.PropertyMap, EditAndContinueOperation.AddProperty),
+ Row(1, TableIndex.Property, EditAndContinueOperation.Default),
+ Row(1, TableIndex.PropertyMap, EditAndContinueOperation.AddProperty),
+ Row(2, TableIndex.Property, EditAndContinueOperation.Default),
+ Row(3, TableIndex.MethodDef, EditAndContinueOperation.AddParameter),
+ Row(1, TableIndex.Param, EditAndContinueOperation.Default),
+ Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(8, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(10, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(11, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(12, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(13, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(1, TableIndex.MethodSemantics, EditAndContinueOperation.Default),
+ Row(2, TableIndex.MethodSemantics, EditAndContinueOperation.Default),
+ Row(1, TableIndex.MethodImpl, EditAndContinueOperation.Default),
+ Row(2, TableIndex.MethodImpl, EditAndContinueOperation.Default),
+ Row(3, TableIndex.MethodImpl, EditAndContinueOperation.Default),
+ Row(4, TableIndex.MethodImpl, EditAndContinueOperation.Default),
+ Row(5, TableIndex.MethodImpl, EditAndContinueOperation.Default),
+ Row(6, TableIndex.MethodImpl, EditAndContinueOperation.Default),
+ Row(7, TableIndex.MethodImpl, EditAndContinueOperation.Default),
+ Row(2, TableIndex.NestedClass, EditAndContinueOperation.Default),
+ Row(1, TableIndex.InterfaceImpl, EditAndContinueOperation.Default),
+ Row(2, TableIndex.InterfaceImpl, EditAndContinueOperation.Default),
+ Row(3, TableIndex.InterfaceImpl, EditAndContinueOperation.Default),
+ Row(4, TableIndex.InterfaceImpl, EditAndContinueOperation.Default),
+ Row(5, TableIndex.InterfaceImpl, EditAndContinueOperation.Default));
}
[Fact]
@@ -447,49 +447,49 @@ static async Task F()
var v0 = CompileAndVerify(compilation0);
- using (var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData))
- {
- var method0 = compilation0.GetMember("C.F");
- var method1 = compilation1.GetMember("C.F");
+ using var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData);
+ var method0 = compilation0.GetMember("C.F");
+ var method1 = compilation1.GetMember("C.F");
- var generation0 = EmitBaseline.CreateInitialBaseline(md0, EmptyLocalsProvider);
- var diff1 = compilation1.EmitDifference(
- generation0,
- ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method0, method1)));
+ var generation0 = EmitBaseline.CreateInitialBaseline(md0, v0.CreateSymReader().GetEncMethodDebugInfo);
+ var diff1 = compilation1.EmitDifference(
+ generation0,
+ ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method0, method1)));
- using (var md1 = diff1.GetMetadata())
- {
- CheckEncLogDefinitions(md1.Reader,
- Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
- Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
- Row(3, TableIndex.TypeDef, EditAndContinueOperation.Default),
- Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddField),
- Row(1, TableIndex.Field, EditAndContinueOperation.Default),
- Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddField),
- Row(2, TableIndex.Field, EditAndContinueOperation.Default),
- Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddField),
- Row(3, TableIndex.Field, EditAndContinueOperation.Default),
- Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddField),
- Row(4, TableIndex.Field, EditAndContinueOperation.Default),
- Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
- Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(5, TableIndex.MethodDef, EditAndContinueOperation.AddParameter),
- Row(1, TableIndex.Param, EditAndContinueOperation.Default),
- Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(1, TableIndex.MethodImpl, EditAndContinueOperation.Default),
- Row(2, TableIndex.MethodImpl, EditAndContinueOperation.Default),
- Row(1, TableIndex.NestedClass, EditAndContinueOperation.Default),
- Row(1, TableIndex.InterfaceImpl, EditAndContinueOperation.Default));
- }
- }
+ diff1.VerifySynthesizedMembers(
+ "C.d__0#1: {<>1__state, <>t__builder, <>s__1, <>u__1, MoveNext, SetStateMachine}",
+ "C: {d__0#1}");
+
+ using var md1 = diff1.GetMetadata();
+ CheckEncLogDefinitions(md1.Reader,
+ Row(2, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
+ Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
+ Row(3, TableIndex.TypeDef, EditAndContinueOperation.Default),
+ Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddField),
+ Row(1, TableIndex.Field, EditAndContinueOperation.Default),
+ Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddField),
+ Row(2, TableIndex.Field, EditAndContinueOperation.Default),
+ Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddField),
+ Row(3, TableIndex.Field, EditAndContinueOperation.Default),
+ Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddField),
+ Row(4, TableIndex.Field, EditAndContinueOperation.Default),
+ Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddMethod),
+ Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(5, TableIndex.MethodDef, EditAndContinueOperation.AddParameter),
+ Row(1, TableIndex.Param, EditAndContinueOperation.Default),
+ Row(4, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(5, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(1, TableIndex.MethodImpl, EditAndContinueOperation.Default),
+ Row(2, TableIndex.MethodImpl, EditAndContinueOperation.Default),
+ Row(1, TableIndex.NestedClass, EditAndContinueOperation.Default),
+ Row(1, TableIndex.InterfaceImpl, EditAndContinueOperation.Default));
}
[Fact]
@@ -571,28 +571,26 @@ static Task F()
var v0 = CompileAndVerify(compilation0);
- using (var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData))
- {
- var method0 = compilation0.GetMember("C.F");
- var method1 = compilation1.GetMember("C.F");
-
- var generation0 = EmitBaseline.CreateInitialBaseline(md0, EmptyLocalsProvider);
- var diff1 = compilation1.EmitDifference(
- generation0,
- ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method0, method1)));
+ using var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData);
+ var method0 = compilation0.GetMember("C.F");
+ var method1 = compilation1.GetMember("C.F");
- using (var md1 = diff1.GetMetadata())
- {
- CheckAttributes(md1.Reader,
- new CustomAttributeRow(Handle(0, TableIndex.MethodDef), Handle(0, TableIndex.MemberRef)), // row id 0 == delete
- new CustomAttributeRow(Handle(0, TableIndex.MethodDef), Handle(0, TableIndex.MemberRef))); // row id 0 == delete
+ var generation0 = EmitBaseline.CreateInitialBaseline(md0, EmptyLocalsProvider);
+ var diff1 = compilation1.EmitDifference(
+ generation0,
+ ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method0, method1)));
- CheckEncLogDefinitions(md1.Reader,
- Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
- Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), // Delete AsyncStateMachineAttribute
- Row(2, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Delete DebuggerStepThroughAttribute
- }
+ using (var md1 = diff1.GetMetadata())
+ {
+ CheckAttributes(md1.Reader,
+ new CustomAttributeRow(Handle(0, TableIndex.MethodDef), Handle(0, TableIndex.MemberRef)), // row id 0 == delete
+ new CustomAttributeRow(Handle(0, TableIndex.MethodDef), Handle(0, TableIndex.MemberRef))); // row id 0 == delete
+
+ CheckEncLogDefinitions(md1.Reader,
+ Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
+ Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default), // Delete AsyncStateMachineAttribute
+ Row(2, TableIndex.CustomAttribute, EditAndContinueOperation.Default)); // Delete DebuggerStepThroughAttribute
}
}
@@ -644,53 +642,50 @@ static async Task F(int a)
var v0 = CompileAndVerify(compilation0);
- using (var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData))
- {
- var methodShort0 = compilation0.GetMembers("C.F").Single(m => m.ToTestDisplayString() == "System.Threading.Tasks.Task C.F(System.Int16 a)");
- var methodShort1 = compilation1.GetMembers("C.F").Single(m => m.ToTestDisplayString() == "System.Threading.Tasks.Task C.F(System.Int16 a)");
+ using var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData);
+ var methodShort0 = compilation0.GetMembers("C.F").Single(m => m.ToTestDisplayString() == "System.Threading.Tasks.Task C.F(System.Int16 a)");
+ var methodShort1 = compilation1.GetMembers("C.F").Single(m => m.ToTestDisplayString() == "System.Threading.Tasks.Task C.F(System.Int16 a)");
- var methodInt0 = compilation0.GetMembers("C.F").Single(m => m.ToTestDisplayString() == "System.Threading.Tasks.Task C.F(System.Int32 a)");
- var methodInt1 = compilation1.GetMembers("C.F").Single(m => m.ToTestDisplayString() == "System.Threading.Tasks.Task C.F(System.Int32 a)");
+ var methodInt0 = compilation0.GetMembers("C.F").Single(m => m.ToTestDisplayString() == "System.Threading.Tasks.Task C.F(System.Int32 a)");
+ var methodInt1 = compilation1.GetMembers("C.F").Single(m => m.ToTestDisplayString() == "System.Threading.Tasks.Task C.F(System.Int32 a)");
- var methodLong0 = compilation0.GetMembers("C.F").Single(m => m.ToTestDisplayString() == "System.Threading.Tasks.Task C.F(System.Int64 a)");
- var methodLong1 = compilation1.GetMembers("C.F").Single(m => m.ToTestDisplayString() == "System.Threading.Tasks.Task C.F(System.Int64 a)");
+ var methodLong0 = compilation0.GetMembers("C.F").Single(m => m.ToTestDisplayString() == "System.Threading.Tasks.Task C.F(System.Int64 a)");
+ var methodLong1 = compilation1.GetMembers("C.F").Single(m => m.ToTestDisplayString() == "System.Threading.Tasks.Task C.F(System.Int64 a)");
- var generation0 = EmitBaseline.CreateInitialBaseline(md0, EmptyLocalsProvider);
- var diff1 = compilation1.EmitDifference(
- generation0,
- ImmutableArray.Create(
- SemanticEdit.Create(SemanticEditKind.Update, methodShort0, methodShort1, preserveLocalVariables: true),
- SemanticEdit.Create(SemanticEditKind.Update, methodInt0, methodInt1, preserveLocalVariables: true),
- SemanticEdit.Create(SemanticEditKind.Update, methodLong0, methodLong1, preserveLocalVariables: true)
- ));
+ var generation0 = EmitBaseline.CreateInitialBaseline(md0, v0.CreateSymReader().GetEncMethodDebugInfo);
+ var diff1 = compilation1.EmitDifference(
+ generation0,
+ ImmutableArray.Create(
+ SemanticEdit.Create(SemanticEditKind.Update, methodShort0, methodShort1, preserveLocalVariables: true),
+ SemanticEdit.Create(SemanticEditKind.Update, methodInt0, methodInt1, preserveLocalVariables: true),
+ SemanticEdit.Create(SemanticEditKind.Update, methodLong0, methodLong1, preserveLocalVariables: true)
+ ));
- using (var md1 = diff1.GetMetadata())
- {
- // notice no TypeDefs, FieldDefs
- CheckEncLogDefinitions(md1.Reader,
- Row(7, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
- Row(8, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
- Row(9, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
- Row(10, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
- Row(11, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
- Row(12, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
- Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(1, TableIndex.Param, EditAndContinueOperation.Default),
- Row(2, TableIndex.Param, EditAndContinueOperation.Default),
- Row(3, TableIndex.Param, EditAndContinueOperation.Default),
- Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(2, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(8, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default));
- }
- }
+ using var md1 = diff1.GetMetadata();
+
+ // notice no TypeDefs, FieldDefs
+ CheckEncLogDefinitions(md1.Reader,
+ Row(7, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
+ Row(8, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
+ Row(9, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
+ Row(10, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
+ Row(11, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
+ Row(12, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
+ Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(3, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(6, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default),
+ Row(1, TableIndex.Param, EditAndContinueOperation.Default),
+ Row(2, TableIndex.Param, EditAndContinueOperation.Default),
+ Row(3, TableIndex.Param, EditAndContinueOperation.Default),
+ Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(2, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(6, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(8, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
+ Row(9, TableIndex.CustomAttribute, EditAndContinueOperation.Default));
}
[Fact]
@@ -1099,65 +1094,2207 @@ .locals init (int V_0,
}
[Fact]
- public void UpdateIterator_UserDefinedVariables_NoChange()
+ public void UpdateAsync_Await_Add()
{
- var source0 = @"
-using System.Collections.Generic;
+ var source0 = MarkedSource(@"
+using System.Threading.Tasks;
class C
{
- static IEnumerable F(int p)
+ static Task M1() => null;
+ static Task M2() => null;
+ static Task M3() => null;
+ static void End() {}
+
+ static async Task F()
{
- int x = p;
- yield return 1;
+ await M1();
+ await M2();
+ End();
}
-}";
- var source1 = @"
-using System.Collections.Generic;
+}");
+ var source1 = MarkedSource(@"
+using System.Threading.Tasks;
class C
{
- static IEnumerable F(int p)
+ static Task M1() => null;
+ static Task M2() => null;
+ static Task M3() => null;
+ static void End() {}
+
+ static async Task F()
{
- int x = p;
- yield return 2;
+ await M1();
+ await M3();
+ await M2();
+ End();
}
-}";
- var compilation0 = CreateCompilationWithMscorlib45(source0, options: ComSafeDebugDll);
- var compilation1 = compilation0.WithSource(source1);
+}");
+ var compilation0 = CreateCompilationWithMscorlib45(new[] { source0.Tree }, new[] { SystemCoreRef, CSharpRef }, options: ComSafeDebugDll);
+ var compilation1 = compilation0.WithSource(source1.Tree);
var v0 = CompileAndVerify(compilation0);
- var symReader = v0.CreateSymReader();
+ v0.VerifyDiagnostics();
+ var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData);
- using (var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData))
- {
- var method0 = compilation0.GetMember("C.F");
- var method1 = compilation1.GetMember("C.F");
+ var f0 = compilation0.GetMember("C.F");
+ var f1 = compilation1.GetMember("C.F");
- var generation0 = EmitBaseline.CreateInitialBaseline(md0, symReader.GetEncMethodDebugInfo);
+ var generation0 = EmitBaseline.CreateInitialBaseline(md0, v0.CreateSymReader().GetEncMethodDebugInfo);
- var diff1 = compilation1.EmitDifference(
- generation0,
- ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method0, method1, GetEquivalentNodesMap(method1, method0), preserveLocalVariables: true)));
+ var diff1 = compilation1.EmitDifference(
+ generation0,
+ ImmutableArray.Create(
+ SemanticEdit.Create(SemanticEditKind.Update, f0, f1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables: true)));
- // Verify delta metadata contains expected rows.
- using (var md1 = diff1.GetMetadata())
- {
- // Verify that no new TypeDefs, FieldDefs or MethodDefs were added,
- // 3 methods were updated:
- // - the kick-off method (might be changed if the method previously wasn't an iterator)
- // - Finally method
- // - MoveNext method
- CheckEncLogDefinitions(md1.Reader,
- Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default),
- Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(5, TableIndex.MethodDef, EditAndContinueOperation.Default),
- Row(1, TableIndex.Param, EditAndContinueOperation.Default),
- Row(1, TableIndex.CustomAttribute, EditAndContinueOperation.Default),
- Row(7, TableIndex.CustomAttribute, EditAndContinueOperation.Default));
+ v0.VerifyPdb("C.F", @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+");
+ v0.VerifyPdb("C+d__4.MoveNext", @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+", options: PdbValidationOptions.ExcludeSequencePoints);
- diff1.VerifyIL("C.d__0.System.Collections.IEnumerator.MoveNext", @"
+ v0.VerifyIL("C.d__4.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @"
+{
+ // Code size 268 (0x10c)
+ .maxstack 3
+ .locals init (int V_0,
+ System.Runtime.CompilerServices.TaskAwaiter V_1,
+ C.d__4 V_2,
+ System.Runtime.CompilerServices.TaskAwaiter V_3,
+ System.Exception V_4)
+ IL_0000: ldarg.0
+ IL_0001: ldfld ""int C.d__4.<>1__state""
+ IL_0006: stloc.0
+ .try
+ {
+ IL_0007: ldloc.0
+ IL_0008: brfalse.s IL_0012
+ IL_000a: br.s IL_000c
+ IL_000c: ldloc.0
+ IL_000d: ldc.i4.1
+ IL_000e: beq.s IL_0014
+ IL_0010: br.s IL_0019
+ IL_0012: br.s IL_0055
+ IL_0014: br IL_00b1
+
+ IL_0019: nop
+ IL_001a: call ""System.Threading.Tasks.Task C.M1()""
+ IL_001f: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_0024: stloc.1
+ IL_0025: ldloca.s V_1
+ IL_0027: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_002c: brtrue.s IL_0071
+
+ IL_002e: ldarg.0
+ IL_002f: ldc.i4.0
+ IL_0030: dup
+ IL_0031: stloc.0
+ IL_0032: stfld ""int C.d__4.<>1__state""
+ IL_0037: ldarg.0
+ IL_0038: ldloc.1
+ IL_0039: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_003e: ldarg.0
+ IL_003f: stloc.2
+ IL_0040: ldarg.0
+ IL_0041: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0046: ldloca.s V_1
+ IL_0048: ldloca.s V_2
+ IL_004a: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_004f: nop
+ IL_0050: leave IL_010b
+
+ IL_0055: ldarg.0
+ IL_0056: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_005b: stloc.1
+ IL_005c: ldarg.0
+ IL_005d: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_0062: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_0068: ldarg.0
+ IL_0069: ldc.i4.m1
+ IL_006a: dup
+ IL_006b: stloc.0
+ IL_006c: stfld ""int C.d__4.<>1__state""
+
+ IL_0071: ldloca.s V_1
+ IL_0073: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_0078: nop
+ IL_0079: call ""System.Threading.Tasks.Task C.M2()""
+ IL_007e: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_0083: stloc.3
+ IL_0084: ldloca.s V_3
+ IL_0086: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_008b: brtrue.s IL_00cd
+
+ IL_008d: ldarg.0
+ IL_008e: ldc.i4.1
+ IL_008f: dup
+ IL_0090: stloc.0
+ IL_0091: stfld ""int C.d__4.<>1__state""
+ IL_0096: ldarg.0
+ IL_0097: ldloc.3
+ IL_0098: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_009d: ldarg.0
+ IL_009e: stloc.2
+ IL_009f: ldarg.0
+ IL_00a0: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_00a5: ldloca.s V_3
+ IL_00a7: ldloca.s V_2
+ IL_00a9: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_00ae: nop
+ IL_00af: leave.s IL_010b
+
+ IL_00b1: ldarg.0
+ IL_00b2: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00b7: stloc.3
+ IL_00b8: ldarg.0
+ IL_00b9: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00be: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_00c4: ldarg.0
+ IL_00c5: ldc.i4.m1
+ IL_00c6: dup
+ IL_00c7: stloc.0
+ IL_00c8: stfld ""int C.d__4.<>1__state""
+
+ IL_00cd: ldloca.s V_3
+ IL_00cf: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_00d4: nop
+ IL_00d5: call ""void C.End()""
+ IL_00da: nop
+ IL_00db: leave.s IL_00f7
+ }
+ catch System.Exception
+ {
+ IL_00dd: stloc.s V_4
+ IL_00df: ldarg.0
+ IL_00e0: ldc.i4.s -2
+ IL_00e2: stfld ""int C.d__4.<>1__state""
+ IL_00e7: ldarg.0
+ IL_00e8: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_00ed: ldloc.s V_4
+ IL_00ef: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
+ IL_00f4: nop
+ IL_00f5: leave.s IL_010b
+ }
+ IL_00f7: ldarg.0
+ IL_00f8: ldc.i4.s -2
+ IL_00fa: stfld ""int C.d__4.<>1__state""
+ IL_00ff: ldarg.0
+ IL_0100: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0105: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
+ IL_010a: nop
+ IL_010b: ret
+}
+");
+
+ diff1.VerifyIL("C.d__4.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @"
+{
+ // Code size 380 (0x17c)
+ .maxstack 3
+ .locals init (int V_0,
+ System.Runtime.CompilerServices.TaskAwaiter V_1,
+ C.d__4 V_2,
+ System.Runtime.CompilerServices.TaskAwaiter V_3,
+ System.Runtime.CompilerServices.TaskAwaiter V_4,
+ System.Exception V_5)
+ IL_0000: ldarg.0
+ IL_0001: ldfld ""int C.d__4.<>1__state""
+ IL_0006: stloc.0
+ .try
+ {
+ IL_0007: ldloc.0
+ IL_0008: switch (
+ IL_001b,
+ IL_001d,
+ IL_0022)
+ IL_0019: br.s IL_0027
+ IL_001b: br.s IL_0063
+ IL_001d: br IL_0120
+ IL_0022: br IL_00c2
+
+ IL_0027: nop
+ IL_0028: call ""System.Threading.Tasks.Task C.M1()""
+ IL_002d: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_0032: stloc.1
+ IL_0033: ldloca.s V_1
+ IL_0035: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_003a: brtrue.s IL_007f
+
+ IL_003c: ldarg.0
+ IL_003d: ldc.i4.0
+ IL_003e: dup
+ IL_003f: stloc.0
+ IL_0040: stfld ""int C.d__4.<>1__state""
+ IL_0045: ldarg.0
+ IL_0046: ldloc.1
+ IL_0047: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_004c: ldarg.0
+ IL_004d: stloc.2
+ IL_004e: ldarg.0
+ IL_004f: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0054: ldloca.s V_1
+ IL_0056: ldloca.s V_2
+ IL_0058: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_005d: nop
+ IL_005e: leave IL_017b
+
+ IL_0063: ldarg.0
+ IL_0064: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_0069: stloc.1
+ IL_006a: ldarg.0
+ IL_006b: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_0070: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_0076: ldarg.0
+ IL_0077: ldc.i4.m1
+ IL_0078: dup
+ IL_0079: stloc.0
+ IL_007a: stfld ""int C.d__4.<>1__state""
+
+ IL_007f: ldloca.s V_1
+ IL_0081: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_0086: nop
+ IL_0087: call ""System.Threading.Tasks.Task C.M3()""
+ IL_008c: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_0091: stloc.3
+ IL_0092: ldloca.s V_3
+ IL_0094: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_0099: brtrue.s IL_00de
+
+ IL_009b: ldarg.0
+ IL_009c: ldc.i4.2
+ IL_009d: dup
+ IL_009e: stloc.0
+ IL_009f: stfld ""int C.d__4.<>1__state""
+ IL_00a4: ldarg.0
+ IL_00a5: ldloc.3
+ IL_00a6: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00ab: ldarg.0
+ IL_00ac: stloc.2
+ IL_00ad: ldarg.0
+ IL_00ae: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_00b3: ldloca.s V_3
+ IL_00b5: ldloca.s V_2
+ IL_00b7: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_00bc: nop
+ IL_00bd: leave IL_017b
+
+ IL_00c2: ldarg.0
+ IL_00c3: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00c8: stloc.3
+ IL_00c9: ldarg.0
+ IL_00ca: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00cf: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_00d5: ldarg.0
+ IL_00d6: ldc.i4.m1
+ IL_00d7: dup
+ IL_00d8: stloc.0
+ IL_00d9: stfld ""int C.d__4.<>1__state""
+
+ IL_00de: ldloca.s V_3
+ IL_00e0: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_00e5: nop
+ IL_00e6: call ""System.Threading.Tasks.Task C.M2()""
+ IL_00eb: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_00f0: stloc.s V_4
+ IL_00f2: ldloca.s V_4
+ IL_00f4: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_00f9: brtrue.s IL_013d
+
+ IL_00fb: ldarg.0
+ IL_00fc: ldc.i4.1
+ IL_00fd: dup
+ IL_00fe: stloc.0
+ IL_00ff: stfld ""int C.d__4.<>1__state""
+ IL_0104: ldarg.0
+ IL_0105: ldloc.s V_4
+ IL_0107: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_010c: ldarg.0
+ IL_010d: stloc.2
+ IL_010e: ldarg.0
+ IL_010f: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0114: ldloca.s V_4
+ IL_0116: ldloca.s V_2
+ IL_0118: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_011d: nop
+ IL_011e: leave.s IL_017b
+
+ IL_0120: ldarg.0
+ IL_0121: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_0126: stloc.s V_4
+ IL_0128: ldarg.0
+ IL_0129: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_012e: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_0134: ldarg.0
+ IL_0135: ldc.i4.m1
+ IL_0136: dup
+ IL_0137: stloc.0
+ IL_0138: stfld ""int C.d__4.<>1__state""
+
+ IL_013d: ldloca.s V_4
+ IL_013f: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_0144: nop
+ IL_0145: call ""void C.End()""
+ IL_014a: nop
+ IL_014b: leave.s IL_0167
+ }
+ catch System.Exception
+ {
+ IL_014d: stloc.s V_5
+ IL_014f: ldarg.0
+ IL_0150: ldc.i4.s -2
+ IL_0152: stfld ""int C.d__4.<>1__state""
+ IL_0157: ldarg.0
+ IL_0158: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_015d: ldloc.s V_5
+ IL_015f: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
+ IL_0164: nop
+ IL_0165: leave.s IL_017b
+ }
+ IL_0167: ldarg.0
+ IL_0168: ldc.i4.s -2
+ IL_016a: stfld ""int C.d__4.<>1__state""
+ IL_016f: ldarg.0
+ IL_0170: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0175: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
+ IL_017a: nop
+ IL_017b: ret
+}
+");
+ }
+
+ [Fact]
+ public void UpdateAsync_Await_Remove_RemoveAdd()
+ {
+ var source0 = MarkedSource(@"
+using System.Threading.Tasks;
+
+class C
+{
+ static Task M1() => null;
+ static Task M2() => null;
+ static Task M3() => null;
+ static void End() {}
+
+ static async Task F()
+ {
+ await M1();
+ await M3();
+ await M2();
+ End();
+ }
+}");
+ var source1 = MarkedSource(@"
+using System.Threading.Tasks;
+
+class C
+{
+ static Task M1() => null;
+ static Task M2() => null;
+ static Task M3() => null;
+ static void End() {}
+
+ static async Task F()
+ {
+ await M1();
+ await M2();
+ End();
+ }
+}");
+ var source2 = MarkedSource(@"
+using System.Threading.Tasks;
+
+class C
+{
+ static Task M1() => null;
+ static Task M2() => null;
+ static Task M3() => null;
+ static void End() {}
+
+ static async Task F()
+ {
+ await M3();
+ await M1();
+ End();
+ }
+}");
+ var compilation0 = CreateCompilationWithMscorlib45(new[] { source0.Tree }, new[] { SystemCoreRef, CSharpRef }, options: ComSafeDebugDll);
+ var compilation1 = compilation0.WithSource(source1.Tree);
+ var compilation2 = compilation0.WithSource(source2.Tree);
+
+ var v0 = CompileAndVerify(compilation0);
+ v0.VerifyDiagnostics();
+ var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData);
+
+ var f0 = compilation0.GetMember("C.F");
+ var f1 = compilation1.GetMember("C.F");
+ var f2 = compilation2.GetMember("C.F");
+
+ var generation0 = EmitBaseline.CreateInitialBaseline(md0, v0.CreateSymReader().GetEncMethodDebugInfo);
+
+ var diff1 = compilation1.EmitDifference(
+ generation0,
+ ImmutableArray.Create(
+ SemanticEdit.Create(SemanticEditKind.Update, f0, f1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables: true)));
+
+ var diff2 = compilation2.EmitDifference(
+ diff1.NextGeneration,
+ ImmutableArray.Create(
+ SemanticEdit.Create(SemanticEditKind.Update, f1, f2, GetSyntaxMapFromMarkers(source1, source2), preserveLocalVariables: true)));
+
+ v0.VerifyPdb("C.F", @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+");
+ v0.VerifyPdb("C+d__4.MoveNext", @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+", options: PdbValidationOptions.ExcludeSequencePoints);
+
+ v0.VerifyIL("C.d__4.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @"
+{
+ // Code size 380 (0x17c)
+ .maxstack 3
+ .locals init (int V_0,
+ System.Runtime.CompilerServices.TaskAwaiter V_1,
+ C.d__4 V_2,
+ System.Runtime.CompilerServices.TaskAwaiter V_3,
+ System.Runtime.CompilerServices.TaskAwaiter V_4,
+ System.Exception V_5)
+ IL_0000: ldarg.0
+ IL_0001: ldfld ""int C.d__4.<>1__state""
+ IL_0006: stloc.0
+ .try
+ {
+ IL_0007: ldloc.0
+ IL_0008: switch (
+ IL_001b,
+ IL_001d,
+ IL_0022)
+ IL_0019: br.s IL_0027
+ IL_001b: br.s IL_0063
+ IL_001d: br IL_00c2
+ IL_0022: br IL_0120
+
+ IL_0027: nop
+ IL_0028: call ""System.Threading.Tasks.Task C.M1()""
+ IL_002d: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_0032: stloc.1
+ IL_0033: ldloca.s V_1
+ IL_0035: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_003a: brtrue.s IL_007f
+
+ IL_003c: ldarg.0
+ IL_003d: ldc.i4.0
+ IL_003e: dup
+ IL_003f: stloc.0
+ IL_0040: stfld ""int C.d__4.<>1__state""
+ IL_0045: ldarg.0
+ IL_0046: ldloc.1
+ IL_0047: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_004c: ldarg.0
+ IL_004d: stloc.2
+ IL_004e: ldarg.0
+ IL_004f: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0054: ldloca.s V_1
+ IL_0056: ldloca.s V_2
+ IL_0058: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_005d: nop
+ IL_005e: leave IL_017b
+
+ IL_0063: ldarg.0
+ IL_0064: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_0069: stloc.1
+ IL_006a: ldarg.0
+ IL_006b: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_0070: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_0076: ldarg.0
+ IL_0077: ldc.i4.m1
+ IL_0078: dup
+ IL_0079: stloc.0
+ IL_007a: stfld ""int C.d__4.<>1__state""
+
+ IL_007f: ldloca.s V_1
+ IL_0081: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_0086: nop
+ IL_0087: call ""System.Threading.Tasks.Task C.M3()""
+ IL_008c: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_0091: stloc.3
+ IL_0092: ldloca.s V_3
+ IL_0094: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_0099: brtrue.s IL_00de
+
+ IL_009b: ldarg.0
+ IL_009c: ldc.i4.1
+ IL_009d: dup
+ IL_009e: stloc.0
+ IL_009f: stfld ""int C.d__4.<>1__state""
+ IL_00a4: ldarg.0
+ IL_00a5: ldloc.3
+ IL_00a6: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00ab: ldarg.0
+ IL_00ac: stloc.2
+ IL_00ad: ldarg.0
+ IL_00ae: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_00b3: ldloca.s V_3
+ IL_00b5: ldloca.s V_2
+ IL_00b7: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_00bc: nop
+ IL_00bd: leave IL_017b
+
+ IL_00c2: ldarg.0
+ IL_00c3: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00c8: stloc.3
+ IL_00c9: ldarg.0
+ IL_00ca: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00cf: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_00d5: ldarg.0
+ IL_00d6: ldc.i4.m1
+ IL_00d7: dup
+ IL_00d8: stloc.0
+ IL_00d9: stfld ""int C.d__4.<>1__state""
+
+ IL_00de: ldloca.s V_3
+ IL_00e0: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_00e5: nop
+ IL_00e6: call ""System.Threading.Tasks.Task C.M2()""
+ IL_00eb: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_00f0: stloc.s V_4
+ IL_00f2: ldloca.s V_4
+ IL_00f4: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_00f9: brtrue.s IL_013d
+
+ IL_00fb: ldarg.0
+ IL_00fc: ldc.i4.2
+ IL_00fd: dup
+ IL_00fe: stloc.0
+ IL_00ff: stfld ""int C.d__4.<>1__state""
+ IL_0104: ldarg.0
+ IL_0105: ldloc.s V_4
+ IL_0107: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_010c: ldarg.0
+ IL_010d: stloc.2
+ IL_010e: ldarg.0
+ IL_010f: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0114: ldloca.s V_4
+ IL_0116: ldloca.s V_2
+ IL_0118: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_011d: nop
+ IL_011e: leave.s IL_017b
+
+ IL_0120: ldarg.0
+ IL_0121: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_0126: stloc.s V_4
+ IL_0128: ldarg.0
+ IL_0129: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_012e: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_0134: ldarg.0
+ IL_0135: ldc.i4.m1
+ IL_0136: dup
+ IL_0137: stloc.0
+ IL_0138: stfld ""int C.d__4.<>1__state""
+
+ IL_013d: ldloca.s V_4
+ IL_013f: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_0144: nop
+ IL_0145: call ""void C.End()""
+ IL_014a: nop
+ IL_014b: leave.s IL_0167
+ }
+ catch System.Exception
+ {
+ IL_014d: stloc.s V_5
+ IL_014f: ldarg.0
+ IL_0150: ldc.i4.s -2
+ IL_0152: stfld ""int C.d__4.<>1__state""
+ IL_0157: ldarg.0
+ IL_0158: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_015d: ldloc.s V_5
+ IL_015f: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
+ IL_0164: nop
+ IL_0165: leave.s IL_017b
+ }
+ IL_0167: ldarg.0
+ IL_0168: ldc.i4.s -2
+ IL_016a: stfld ""int C.d__4.<>1__state""
+ IL_016f: ldarg.0
+ IL_0170: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0175: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
+ IL_017a: nop
+ IL_017b: ret
+}
+");
+
+ diff1.VerifyIL("C.d__4.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @"
+{
+ // Code size 283 (0x11b)
+ .maxstack 3
+ .locals init (int V_0,
+ System.Runtime.CompilerServices.TaskAwaiter V_1,
+ C.d__4 V_2,
+ System.Runtime.CompilerServices.TaskAwaiter V_3,
+ System.Exception V_4)
+ IL_0000: ldarg.0
+ IL_0001: ldfld ""int C.d__4.<>1__state""
+ IL_0006: stloc.0
+ .try
+ {
+ IL_0007: ldloc.0
+ IL_0008: brfalse.s IL_0012
+ IL_000a: br.s IL_000c
+ IL_000c: ldloc.0
+ IL_000d: ldc.i4.2
+ IL_000e: beq.s IL_0014
+ IL_0010: br.s IL_0019
+ IL_0012: br.s IL_0064
+ IL_0014: br IL_00c0
+ IL_0019: ldloc.0
+ IL_001a: ldc.i4.0
+ IL_001b: blt.s IL_0028
+ IL_001d: ldstr """ + CodeAnalysisResources.EncCannotResumeSuspendedAsyncMethod + @"""
+ IL_0022: newobj ""System.InvalidOperationException..ctor(string)""
+ IL_0027: throw
+
+ IL_0028: nop
+ IL_0029: call ""System.Threading.Tasks.Task C.M1()""
+ IL_002e: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_0033: stloc.1
+ IL_0034: ldloca.s V_1
+ IL_0036: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_003b: brtrue.s IL_0080
+
+ IL_003d: ldarg.0
+ IL_003e: ldc.i4.0
+ IL_003f: dup
+ IL_0040: stloc.0
+ IL_0041: stfld ""int C.d__4.<>1__state""
+ IL_0046: ldarg.0
+ IL_0047: ldloc.1
+ IL_0048: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_004d: ldarg.0
+ IL_004e: stloc.2
+ IL_004f: ldarg.0
+ IL_0050: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0055: ldloca.s V_1
+ IL_0057: ldloca.s V_2
+ IL_0059: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_005e: nop
+ IL_005f: leave IL_011a
+
+ IL_0064: ldarg.0
+ IL_0065: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_006a: stloc.1
+ IL_006b: ldarg.0
+ IL_006c: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_0071: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_0077: ldarg.0
+ IL_0078: ldc.i4.m1
+ IL_0079: dup
+ IL_007a: stloc.0
+ IL_007b: stfld ""int C.d__4.<>1__state""
+ IL_0080: ldloca.s V_1
+ IL_0082: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_0087: nop
+ IL_0088: call ""System.Threading.Tasks.Task C.M2()""
+ IL_008d: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_0092: stloc.3
+ IL_0093: ldloca.s V_3
+ IL_0095: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_009a: brtrue.s IL_00dc
+
+ IL_009c: ldarg.0
+ IL_009d: ldc.i4.2
+ IL_009e: dup
+ IL_009f: stloc.0
+ IL_00a0: stfld ""int C.d__4.<>1__state""
+ IL_00a5: ldarg.0
+ IL_00a6: ldloc.3
+ IL_00a7: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00ac: ldarg.0
+ IL_00ad: stloc.2
+ IL_00ae: ldarg.0
+ IL_00af: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_00b4: ldloca.s V_3
+ IL_00b6: ldloca.s V_2
+ IL_00b8: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_00bd: nop
+ IL_00be: leave.s IL_011a
+
+ IL_00c0: ldarg.0
+ IL_00c1: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00c6: stloc.3
+ IL_00c7: ldarg.0
+ IL_00c8: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00cd: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_00d3: ldarg.0
+ IL_00d4: ldc.i4.m1
+ IL_00d5: dup
+ IL_00d6: stloc.0
+ IL_00d7: stfld ""int C.d__4.<>1__state""
+
+ IL_00dc: ldloca.s V_3
+ IL_00de: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_00e3: nop
+ IL_00e4: call ""void C.End()""
+ IL_00e9: nop
+ IL_00ea: leave.s IL_0106
+ }
+ catch System.Exception
+ {
+ IL_00ec: stloc.s V_4
+ IL_00ee: ldarg.0
+ IL_00ef: ldc.i4.s -2
+ IL_00f1: stfld ""int C.d__4.<>1__state""
+ IL_00f6: ldarg.0
+ IL_00f7: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_00fc: ldloc.s V_4
+ IL_00fe: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
+ IL_0103: nop
+ IL_0104: leave.s IL_011a
+ }
+ IL_0106: ldarg.0
+ IL_0107: ldc.i4.s -2
+ IL_0109: stfld ""int C.d__4.<>1__state""
+ IL_010e: ldarg.0
+ IL_010f: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0114: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
+ IL_0119: nop
+ IL_011a: ret
+}
+");
+ // note that CDI is not emitted to the delta since we already have the information captured in changed symbols:
+ diff1.VerifyPdb(Enumerable.Range(1, 20).Select(MetadataTokens.MethodDefinitionHandle), @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+");
+ diff2.VerifyIL("C.d__4.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @"
+{
+ // Code size 283 (0x11b)
+ .maxstack 3
+ .locals init (int V_0,
+ System.Runtime.CompilerServices.TaskAwaiter V_1,
+ C.d__4 V_2,
+ System.Runtime.CompilerServices.TaskAwaiter V_3,
+ System.Exception V_4)
+ IL_0000: ldarg.0
+ IL_0001: ldfld ""int C.d__4.<>1__state""
+ IL_0006: stloc.0
+ .try
+ {
+ IL_0007: ldloc.0
+ IL_0008: brfalse.s IL_0012
+ IL_000a: br.s IL_000c
+ IL_000c: ldloc.0
+ IL_000d: ldc.i4.3
+ IL_000e: beq.s IL_0017
+ IL_0010: br.s IL_0019
+ IL_0012: br IL_00c0
+ IL_0017: br.s IL_0064
+ IL_0019: ldloc.0
+ IL_001a: ldc.i4.0
+ IL_001b: blt.s IL_0028
+ IL_001d: ldstr """ + CodeAnalysisResources.EncCannotResumeSuspendedAsyncMethod + @"""
+ IL_0022: newobj ""System.InvalidOperationException..ctor(string)""
+ IL_0027: throw
+
+ IL_0028: nop
+ IL_0029: call ""System.Threading.Tasks.Task C.M3()""
+ IL_002e: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_0033: stloc.1
+ IL_0034: ldloca.s V_1
+ IL_0036: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_003b: brtrue.s IL_0080
+
+ IL_003d: ldarg.0
+ IL_003e: ldc.i4.3
+ IL_003f: dup
+ IL_0040: stloc.0
+ IL_0041: stfld ""int C.d__4.<>1__state""
+ IL_0046: ldarg.0
+ IL_0047: ldloc.1
+ IL_0048: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_004d: ldarg.0
+ IL_004e: stloc.2
+ IL_004f: ldarg.0
+ IL_0050: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0055: ldloca.s V_1
+ IL_0057: ldloca.s V_2
+ IL_0059: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_005e: nop
+ IL_005f: leave IL_011a
+
+ IL_0064: ldarg.0
+ IL_0065: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_006a: stloc.1
+ IL_006b: ldarg.0
+ IL_006c: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_0071: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_0077: ldarg.0
+ IL_0078: ldc.i4.m1
+ IL_0079: dup
+ IL_007a: stloc.0
+ IL_007b: stfld ""int C.d__4.<>1__state""
+
+ IL_0080: ldloca.s V_1
+ IL_0082: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_0087: nop
+ IL_0088: call ""System.Threading.Tasks.Task C.M1()""
+ IL_008d: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_0092: stloc.3
+ IL_0093: ldloca.s V_3
+ IL_0095: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_009a: brtrue.s IL_00dc
+
+ IL_009c: ldarg.0
+ IL_009d: ldc.i4.0
+ IL_009e: dup
+ IL_009f: stloc.0
+ IL_00a0: stfld ""int C.d__4.<>1__state""
+ IL_00a5: ldarg.0
+ IL_00a6: ldloc.3
+ IL_00a7: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00ac: ldarg.0
+ IL_00ad: stloc.2
+ IL_00ae: ldarg.0
+ IL_00af: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_00b4: ldloca.s V_3
+ IL_00b6: ldloca.s V_2
+ IL_00b8: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_00bd: nop
+ IL_00be: leave.s IL_011a
+
+ IL_00c0: ldarg.0
+ IL_00c1: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00c6: stloc.3
+ IL_00c7: ldarg.0
+ IL_00c8: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_00cd: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_00d3: ldarg.0
+ IL_00d4: ldc.i4.m1
+ IL_00d5: dup
+ IL_00d6: stloc.0
+ IL_00d7: stfld ""int C.d__4.<>1__state""
+
+ IL_00dc: ldloca.s V_3
+ IL_00de: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_00e3: nop
+ IL_00e4: call ""void C.End()""
+ IL_00e9: nop
+ IL_00ea: leave.s IL_0106
+ }
+ catch System.Exception
+ {
+ IL_00ec: stloc.s V_4
+ IL_00ee: ldarg.0
+ IL_00ef: ldc.i4.s -2
+ IL_00f1: stfld ""int C.d__4.<>1__state""
+ IL_00f6: ldarg.0
+ IL_00f7: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_00fc: ldloc.s V_4
+ IL_00fe: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
+ IL_0103: nop
+ IL_0104: leave.s IL_011a
+ }
+ IL_0106: ldarg.0
+ IL_0107: ldc.i4.s -2
+ IL_0109: stfld ""int C.d__4.<>1__state""
+ IL_010e: ldarg.0
+ IL_010f: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0114: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
+ IL_0119: nop
+ IL_011a: ret
+}
+");
+ }
+
+ [Fact]
+ public void UpdateAsync_Await_Remove_FirstAndLast()
+ {
+ var source0 = MarkedSource(@"
+using System.Threading.Tasks;
+
+class C
+{
+ static Task M1() => null;
+ static Task M2() => null;
+ static Task M3() => null;
+ static void End() {}
+
+ static async Task F()
+ {
+ await M1();
+ await M2();
+ await M3();
+ End();
+ }
+}");
+ var source1 = MarkedSource(@"
+using System.Threading.Tasks;
+
+class C
+{
+ static Task M1() => null;
+ static Task M2() => null;
+ static Task M3() => null;
+ static void End() {}
+
+ static async Task F()
+ {
+ await M2();
+ End();
+ }
+}");
+ var compilation0 = CreateCompilationWithMscorlib45(new[] { source0.Tree }, new[] { SystemCoreRef, CSharpRef }, options: ComSafeDebugDll);
+ var compilation1 = compilation0.WithSource(source1.Tree);
+
+ var v0 = CompileAndVerify(compilation0);
+ v0.VerifyDiagnostics();
+ var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData);
+
+ var f0 = compilation0.GetMember("C.F");
+ var f1 = compilation1.GetMember("C.F");
+
+ var generation0 = EmitBaseline.CreateInitialBaseline(md0, v0.CreateSymReader().GetEncMethodDebugInfo);
+
+ var diff1 = compilation1.EmitDifference(
+ generation0,
+ ImmutableArray.Create(
+ SemanticEdit.Create(SemanticEditKind.Update, f0, f1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables: true)));
+
+ diff1.VerifyIL("C.d__4.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @"
+{
+ // Code size 176 (0xb0)
+ .maxstack 3
+ .locals init (int V_0,
+ System.Runtime.CompilerServices.TaskAwaiter V_1,
+ C.d__4 V_2,
+ System.Exception V_3)
+ IL_0000: ldarg.0
+ IL_0001: ldfld ""int C.d__4.<>1__state""
+ IL_0006: stloc.0
+ .try
+ {
+ IL_0007: ldloc.0
+ IL_0008: ldc.i4.1
+ IL_0009: beq.s IL_000d
+ IL_000b: br.s IL_000f
+ IL_000d: br.s IL_0057
+ IL_000f: ldloc.0
+ IL_0010: ldc.i4.0
+ IL_0011: blt.s IL_001e
+ IL_0013: ldstr """ + CodeAnalysisResources.EncCannotResumeSuspendedAsyncMethod + @"""
+ IL_0018: newobj ""System.InvalidOperationException..ctor(string)""
+ IL_001d: throw
+
+ IL_001e: nop
+ IL_001f: call ""System.Threading.Tasks.Task C.M2()""
+ IL_0024: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_0029: stloc.1
+ IL_002a: ldloca.s V_1
+ IL_002c: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_0031: brtrue.s IL_0073
+
+ IL_0033: ldarg.0
+ IL_0034: ldc.i4.1
+ IL_0035: dup
+ IL_0036: stloc.0
+ IL_0037: stfld ""int C.d__4.<>1__state""
+ IL_003c: ldarg.0
+ IL_003d: ldloc.1
+ IL_003e: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_0043: ldarg.0
+ IL_0044: stloc.2
+ IL_0045: ldarg.0
+ IL_0046: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_004b: ldloca.s V_1
+ IL_004d: ldloca.s V_2
+ IL_004f: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__4>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__4)""
+ IL_0054: nop
+ IL_0055: leave.s IL_00af
+
+ IL_0057: ldarg.0
+ IL_0058: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_005d: stloc.1
+ IL_005e: ldarg.0
+ IL_005f: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__4.<>u__1""
+ IL_0064: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_006a: ldarg.0
+ IL_006b: ldc.i4.m1
+ IL_006c: dup
+ IL_006d: stloc.0
+ IL_006e: stfld ""int C.d__4.<>1__state""
+
+ IL_0073: ldloca.s V_1
+ IL_0075: call ""void System.Runtime.CompilerServices.TaskAwaiter.GetResult()""
+ IL_007a: nop
+ IL_007b: call ""void C.End()""
+ IL_0080: nop
+ IL_0081: leave.s IL_009b
+ }
+ catch System.Exception
+ {
+ IL_0083: stloc.3
+ IL_0084: ldarg.0
+ IL_0085: ldc.i4.s -2
+ IL_0087: stfld ""int C.d__4.<>1__state""
+ IL_008c: ldarg.0
+ IL_008d: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_0092: ldloc.3
+ IL_0093: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
+ IL_0098: nop
+ IL_0099: leave.s IL_00af
+ }
+ IL_009b: ldarg.0
+ IL_009c: ldc.i4.s -2
+ IL_009e: stfld ""int C.d__4.<>1__state""
+ IL_00a3: ldarg.0
+ IL_00a4: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__4.<>t__builder""
+ IL_00a9: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
+ IL_00ae: nop
+ IL_00af: ret
+}
+");
+ }
+
+ [Fact]
+ public void UpdateAsync_Await_Remove_TryBlock()
+ {
+ var source0 = MarkedSource(@"
+using System.Threading.Tasks;
+
+class C
+{
+ static void Start() {}
+ static Task M1() => null;
+ static Task M2() => null;
+ static Task M3() => null;
+ static Task M4() => null;
+ static Task M5() => null;
+ static void End() {}
+
+ static async Task F()
+ {
+ Start();
+ await M1();
+ try
+ {
+ await M2();
+ await M3();
+ }
+ catch
+ {
+ await M4();
+ await M5();
+ }
+ End();
+ }
+}");
+ var source1 = MarkedSource(@"
+using System.Threading.Tasks;
+
+class C
+{
+ static void Start() {}
+ static Task M1() => null;
+ static Task M2() => null;
+ static Task M3() => null;
+ static Task M4() => null;
+ static Task M5() => null;
+ static void End() {}
+
+ static async Task F()
+ {
+ Start();
+ try
+ {
+ await M2();
+ }
+ catch
+ {
+ await M4();
+ }
+ End();
+ }
+}");
+ var compilation0 = CreateCompilationWithMscorlib45(new[] { source0.Tree }, new[] { SystemCoreRef, CSharpRef }, options: ComSafeDebugDll);
+ var compilation1 = compilation0.WithSource(source1.Tree);
+
+ var v0 = CompileAndVerify(compilation0);
+ v0.VerifyDiagnostics();
+ var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData);
+
+ var f0 = compilation0.GetMember("C.F");
+ var f1 = compilation1.GetMember("C.F");
+
+ var generation0 = EmitBaseline.CreateInitialBaseline(md0, v0.CreateSymReader().GetEncMethodDebugInfo);
+
+ var diff1 = compilation1.EmitDifference(
+ generation0,
+ ImmutableArray.Create(
+ SemanticEdit.Create(SemanticEditKind.Update, f0, f1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables: true)));
+
+ v0.VerifyIL("C.d__7.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @"
+{
+ // Code size 671 (0x29f)
+ .maxstack 3
+ .locals init (int V_0,
+ System.Runtime.CompilerServices.TaskAwaiter V_1,
+ C.d__7 V_2,
+ System.Runtime.CompilerServices.TaskAwaiter V_3,
+ System.Runtime.CompilerServices.TaskAwaiter V_4,
+ object V_5,
+ int V_6,
+ System.Runtime.CompilerServices.TaskAwaiter V_7,
+ System.Runtime.CompilerServices.TaskAwaiter V_8,
+ System.Exception V_9)
+ IL_0000: ldarg.0
+ IL_0001: ldfld ""int C.d__7.<>1__state""
+ IL_0006: stloc.0
+ .try
+ {
+ IL_0007: ldloc.0
+ IL_0008: switch (
+ IL_0023,
+ IL_0025,
+ IL_0025,
+ IL_0027,
+ IL_002c)
+ IL_0021: br.s IL_0031
+ IL_0023: br.s IL_0073
+ IL_0025: br.s IL_009e
+ IL_0027: br IL_01da
+ IL_002c: br IL_0239
+
+ IL_0031: nop
+ IL_0032: call ""void C.Start()""
+ IL_0037: nop
+ IL_0038: call ""System.Threading.Tasks.Task C.M1()""
+ IL_003d: callvirt ""System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()""
+ IL_0042: stloc.1
+ IL_0043: ldloca.s V_1
+ IL_0045: call ""bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get""
+ IL_004a: brtrue.s IL_008f
+
+ IL_004c: ldarg.0
+ IL_004d: ldc.i4.0
+ IL_004e: dup
+ IL_004f: stloc.0
+ IL_0050: stfld ""int C.d__7.<>1__state""
+ IL_0055: ldarg.0
+ IL_0056: ldloc.1
+ IL_0057: stfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__7.<>u__1""
+ IL_005c: ldarg.0
+ IL_005d: stloc.2
+ IL_005e: ldarg.0
+ IL_005f: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__7.<>t__builder""
+ IL_0064: ldloca.s V_1
+ IL_0066: ldloca.s V_2
+ IL_0068: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompletedd__7>(ref System.Runtime.CompilerServices.TaskAwaiter, ref C.d__7)""
+ IL_006d: nop
+ IL_006e: leave IL_029e
+
+ IL_0073: ldarg.0
+ IL_0074: ldfld ""System.Runtime.CompilerServices.TaskAwaiter C.d__7.<>u__1""
+ IL_0079: stloc.1
+ IL_007a: ldarg.0
+ IL_007b: ldflda ""System.Runtime.CompilerServices.TaskAwaiter C.d__7.<>u__1""
+ IL_0080: initobj ""System.Runtime.CompilerServices.TaskAwaiter""
+ IL_0086: ldarg.0
+ IL_0087: ldc.i4.m1
+ IL_0088: dup
+ IL_0089: stloc.0
+ IL_008a: stfld ""int C.