dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
19.07k stars 4.04k forks source link

Hot Reload fails to apply change with IndexOutOfRangeException #73416

Open isadorasophia opened 6 months ago

isadorasophia commented 6 months ago

Repro steps This is somewhat flakey. I see it happens sporadically while applying code changes on a console app with .NET 8 running on 17.9. The issue occurred while modifying the method body that returns an IEnumerator with yield return.

Roslyn log messages:

Found {0} potentially changed document(s) in project '{1}'
Document changed, added, or deleted: '{0}'
Project summary for '{0}': {1}
Emitting update of '{0}'
Exception while emitting update: {0}

Exception details:

   System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at Roslyn.Utilities.StringExtensions.GetNumeral(Int32 number)
   at Microsoft.CodeAnalysis.CSharp.Symbols.GeneratedNames.MakeIteratorFinallyMethodName(StateMachineState finalizeState)
   at Microsoft.CodeAnalysis.CSharp.IteratorMethodToStateMachineRewriter.MakeSynthesizedFinally(StateMachineState finalizeState)
   at Microsoft.CodeAnalysis.CSharp.IteratorMethodToStateMachineRewriter.PushFrame(BoundTryStatement statement)
   at Microsoft.CodeAnalysis.CSharp.IteratorMethodToStateMachineRewriter.VisitTryStatement(BoundTryStatement node)
   at Microsoft.CodeAnalysis.CSharp.MethodToStateMachineRewriter.Visit(BoundNode node)
   at Microsoft.CodeAnalysis.CSharp.BoundTreeRewriter.DoVisitList[T](ImmutableArray`1 list)
   at Microsoft.CodeAnalysis.CSharp.Symbols.MethodToClassRewriter.VisitBlock(BoundBlock node, Boolean removeInstrumentation)
   at Microsoft.CodeAnalysis.CSharp.MethodToStateMachineRewriter.PossibleIteratorScope(ImmutableArray`1 locals, Func`1 wrapped)
   at Microsoft.CodeAnalysis.CSharp.MethodToStateMachineRewriter.Visit(BoundNode node)
   at Microsoft.CodeAnalysis.CSharp.BoundTreeRewriter.DoVisitList[T](ImmutableArray`1 list)
   at Microsoft.CodeAnalysis.CSharp.Symbols.MethodToClassRewriter.VisitBlock(BoundBlock node, Boolean removeInstrumentation)
   at Microsoft.CodeAnalysis.CSharp.MethodToStateMachineRewriter.PossibleIteratorScope(ImmutableArray`1 locals, Func`1 wrapped)
   at Microsoft.CodeAnalysis.CSharp.MethodToStateMachineRewriter.Visit(BoundNode node)
   at Microsoft.CodeAnalysis.CSharp.BoundTreeRewriter.DoVisitList[T](ImmutableArray`1 list)
   at Microsoft.CodeAnalysis.CSharp.Symbols.MethodToClassRewriter.VisitBlock(BoundBlock node, Boolean removeInstrumentation)
   at Microsoft.CodeAnalysis.CSharp.MethodToStateMachineRewriter.PossibleIteratorScope(ImmutableArray`1 locals, Func`1 wrapped)
   at Microsoft.CodeAnalysis.CSharp.MethodToStateMachineRewriter.Visit(BoundNode node)
   at Microsoft.CodeAnalysis.CSharp.BoundTreeRewriter.DoVisitList[T](ImmutableArray`1 list)
   at Microsoft.CodeAnalysis.CSharp.Symbols.MethodToClassRewriter.VisitBlock(BoundBlock node, Boolean removeInstrumentation)
   at Microsoft.CodeAnalysis.CSharp.MethodToStateMachineRewriter.PossibleIteratorScope(ImmutableArray`1 locals, Func`1 wrapped)
   at Microsoft.CodeAnalysis.CSharp.MethodToStateMachineRewriter.Visit(BoundNode node)
   at Microsoft.CodeAnalysis.CSharp.IteratorMethodToStateMachineRewriter.GenerateMoveNextAndDispose(BoundStatement body, SynthesizedImplementationMethod moveNextMethod, SynthesizedImplementationMethod disposeMethod)
   at Microsoft.CodeAnalysis.CSharp.IteratorRewriter.GenerateEnumeratorImplementation()
   at Microsoft.CodeAnalysis.CSharp.IteratorRewriter.GenerateMethodImplementations()
   at Microsoft.CodeAnalysis.CSharp.StateMachineRewriter.Rewrite()
   at Microsoft.CodeAnalysis.CSharp.IteratorRewriter.Rewrite(BoundStatement body, MethodSymbol method, Int32 methodOrdinal, ArrayBuilder`1 stateMachineStateDebugInfoBuilder, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics, IteratorStateMachine& stateMachineType)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.LowerBodyOrInitializer(MethodSymbol method, Int32 methodOrdinal, BoundStatement body, SynthesizedSubmissionFields previousSubmissionFields, TypeCompilationState compilationState, MethodInstrumentation instrumentation, DebugDocumentProvider debugDocumentProvider, ImmutableArray`1& codeCoverageSpans, BindingDiagnosticBag diagnostics, VariableSlotAllocator& lazyVariableSlotAllocator, ArrayBuilder`1 lambdaDebugInfoBuilder, ArrayBuilder`1 lambdaRuntimeRudeEditsBuilder, ArrayBuilder`1 closureDebugInfoBuilder, ArrayBuilder`1 stateMachineStateDebugInfoBuilder, StateMachineTypeSymbol& stateMachineTypeOpt)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileMethod(MethodSymbol methodSymbol, Int32 methodOrdinal, ProcessedFieldInitializers& processedInitializers, SynthesizedSubmissionFields previousSubmissionFields, TypeCompilationState compilationState)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamedType(NamedTypeSymbol containingType)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.VisitNamedType(NamedTypeSymbol symbol, TypeCompilationState arg)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamespace(NamespaceSymbol symbol)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.VisitNamespace(NamespaceSymbol symbol, TypeCompilationState arg)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamespace(NamespaceSymbol symbol)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.VisitNamespace(NamespaceSymbol symbol, TypeCompilationState arg)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamespace(NamespaceSymbol symbol)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileMethodBodies(CSharpCompilation compilation, PEModuleBuilder moduleBeingBuiltOpt, Boolean emittingPdb, Boolean hasDeclarationErrors, Boolean emitMethodBodies, BindingDiagnosticBag diagnostics, Predicate`1 filterOpt, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CompileMethods(CommonPEModuleBuilder moduleBuilder, Boolean emittingPdb, DiagnosticBag diagnostics, Predicate`1 filterOpt, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Compilation.Compile(CommonPEModuleBuilder moduleBuilder, Boolean emittingPdb, DiagnosticBag diagnostics, Predicate`1 filterOpt, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.Emit.EmitHelpers.EmitDifference(CSharpCompilation compilation, EmitBaseline baseline, IEnumerable`1 edits, Func`2 isAddedSymbol, Stream metadataStream, Stream ilStream, Stream pdbStream, CompilationTestData testData, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Compilation.EmitDifference(EmitBaseline baseline, IEnumerable`1 edits, Func`2 isAddedSymbol, Stream metadataStream, Stream ilStream, Stream pdbStream, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.EditAndContinue.EditSession.EmitSolutionUpdateAsync(Solution solution, ActiveStatementSpanProvider solutionActiveStatementSpanProvider, UpdateId updateId, CancellationToken cancellationToken)
isadorasophia commented 6 months ago

Interestingly, I reproduced the same exception with a different call stack from my Trace.log after enabling EnC diagnostics environment variable. This was thrown before any deltas were produced in the log directory. The code change was changing the default return value of an auto property.

21:03 25.77 Checking for updates...
21:03 28.28 [Error] error ENC1002: Cannot apply changes -- unexpected error: 'Index was outside the bounds of the array.'
21:03 28.28 Invalid changes were found. Please refer to the Error List window to fix those issues.
Exception while emitting update: System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at Microsoft.CodeAnalysis.EditAndContinue.EditSession.<>c__DisplayClass27_0.<MergePartialEdits>b__5(SyntaxNode node)
   at Microsoft.CodeAnalysis.Emit.EncVariableSlotAllocator.TryGetPreviousLocalId(SyntaxNode currentDeclarator, LocalDebugId currentId, LocalDebugId& previousId)
   at Microsoft.CodeAnalysis.Emit.EncVariableSlotAllocator.GetPreviousLocal(ITypeReference currentType, ILocalSymbolInternal currentLocalSymbol, String name, SynthesizedLocalKind kind, LocalDebugId id, LocalVariableAttributes pdbAttributes, LocalSlotConstraints constraints, ImmutableArray`1 dynamicTransformFlags, ImmutableArray`1 tupleElementNames)
   at Microsoft.CodeAnalysis.CodeGen.LocalSlotManager.DeclareLocalImpl(ITypeReference type, ILocalSymbolInternal symbol, String name, SynthesizedLocalKind kind, LocalDebugId id, LocalVariableAttributes pdbAttributes, LocalSlotConstraints constraints, ImmutableArray`1 dynamicTransformFlags, ImmutableArray`1 tupleElementNames)
   at Microsoft.CodeAnalysis.CodeGen.LocalSlotManager.DeclareLocal(ITypeReference type, ILocalSymbolInternal symbol, String name, SynthesizedLocalKind kind, LocalDebugId id, LocalVariableAttributes pdbAttributes, LocalSlotConstraints constraints, ImmutableArray`1 dynamicTransformFlags, ImmutableArray`1 tupleElementNames, Boolean isSlotReusable)
   at Microsoft.CodeAnalysis.CSharp.CodeGen.CodeGenerator.DefineLocal(LocalSymbol local, SyntaxNode syntaxNode)
   at Microsoft.CodeAnalysis.CSharp.CodeGen.CodeGenerator.EmitUninstrumentedBlock(BoundBlock block)
   at Microsoft.CodeAnalysis.CSharp.CodeGen.CodeGenerator.EmitStatement(BoundStatement statement)
   at Microsoft.CodeAnalysis.CSharp.CodeGen.CodeGenerator.EmitStatements(ImmutableArray`1 statements)
   at Microsoft.CodeAnalysis.CSharp.CodeGen.CodeGenerator.EmitUninstrumentedBlock(BoundBlock block)
   at Microsoft.CodeAnalysis.CSharp.CodeGen.CodeGenerator.EmitStatement(BoundStatement statement)
   at Microsoft.CodeAnalysis.CSharp.CodeGen.CodeGenerator.EmitStatementList(BoundStatementList list)
   at Microsoft.CodeAnalysis.CSharp.CodeGen.CodeGenerator.EmitStatement(BoundStatement statement)
   at Microsoft.CodeAnalysis.CSharp.CodeGen.CodeGenerator.GenerateImpl()
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.GenerateMethodBody(PEModuleBuilder moduleBuilder, MethodSymbol method, Int32 methodOrdinal, BoundStatement block, ImmutableArray`1 lambdaDebugInfo, ImmutableArray`1 orderedLambdaRuntimeRudeEdits, ImmutableArray`1 closureDebugInfo, ImmutableArray`1 stateMachineStateDebugInfos, StateMachineTypeSymbol stateMachineTypeOpt, VariableSlotAllocator variableSlotAllocatorOpt, BindingDiagnosticBag diagnostics, DebugDocumentProvider debugDocumentProvider, ImportChain importChainOpt, Boolean emittingPdb, ImmutableArray`1 codeCoverageSpans, AsyncForwardEntryPoint entryPointOpt)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileMethod(MethodSymbol methodSymbol, Int32 methodOrdinal, ProcessedFieldInitializers& processedInitializers, SynthesizedSubmissionFields previousSubmissionFields, TypeCompilationState compilationState)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamedType(NamedTypeSymbol containingType)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.VisitNamedType(NamedTypeSymbol symbol, TypeCompilationState arg)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamespace(NamespaceSymbol symbol)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.VisitNamespace(NamespaceSymbol symbol, TypeCompilationState arg)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamespace(NamespaceSymbol symbol)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.VisitNamespace(NamespaceSymbol symbol, TypeCompilationState arg)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamespace(NamespaceSymbol symbol)
   at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileMethodBodies(CSharpCompilation compilation, PEModuleBuilder moduleBeingBuiltOpt, Boolean emittingPdb, Boolean hasDeclarationErrors, Boolean emitMethodBodies, BindingDiagnosticBag diagnostics, Predicate`1 filterOpt, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.CompileMethods(CommonPEModuleBuilder moduleBuilder, Boolean emittingPdb, DiagnosticBag diagnostics, Predicate`1 filterOpt, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Compilation.Compile(CommonPEModuleBuilder moduleBuilder, Boolean emittingPdb, DiagnosticBag diagnostics, Predicate`1 filterOpt, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.Emit.EmitHelpers.EmitDifference(CSharpCompilation compilation, EmitBaseline baseline, IEnumerable`1 edits, Func`2 isAddedSymbol, Stream metadataStream, Stream ilStream, Stream pdbStream, CompilationTestData testData, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Compilation.EmitDifference(EmitBaseline baseline, IEnumerable`1 edits, Func`2 isAddedSymbol, Stream metadataStream, Stream ilStream, Stream pdbStream, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.EditAndContinue.EditSession.EmitSolutionUpdateAsync(Solution solution, ActiveStatementSpanProvider solutionActiveStatementSpanProvider, UpdateId updateId, CancellationToken cancellationToken)