提交 a3a8e8e9 编写于 作者: A AlekseyTs

Merge pull request #2871 from AlekseyTs/Issue2862

Do not hoist ByRef locals used within iterator methods, even when building debug.
......@@ -45,6 +45,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' Returns deterministically ordered list of variables that ought to be hoisted.
Public Overloads Shared Function Analyze(info As FlowAnalysisInfo, diagnostics As DiagnosticBag) As Result
Debug.Assert(info.Symbol IsNot Nothing)
Debug.Assert(info.Symbol.Kind = SymbolKind.Method)
Dim walker As New IteratorAndAsyncCaptureWalker(info)
walker.Analyze()
Debug.Assert(Not walker.InvalidRegionDetected)
......@@ -69,16 +72,21 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If info.Compilation.Options.OptimizationLevel <> OptimizationLevel.Release Then
Debug.Assert(variablesToHoist.Count = 0)
' In debug build we hoist all locals and parameters:
variablesToHoist.AddRange(From v In allVariables
Where v.Symbol IsNot Nothing AndAlso HoistInDebugBuild(v.Symbol)
Select v.Symbol)
' In debug build we hoist all locals and parameters, except ByRef locals in iterator methods.
' Lifetime of ByRef locals in iterator methods never crosses stament boundaries, thus
' there is no reason to hoist them and the pipeline doesn't handle this.
Dim skipByRefLocals As Boolean = DirectCast(info.Symbol, MethodSymbol).IsIterator
For Each v In allVariables
If v.Symbol IsNot Nothing AndAlso HoistInDebugBuild(v.Symbol, skipByRefLocals) Then
variablesToHoist.Add(v.Symbol)
End If
Next
End If
Return New Result(variablesToHoist, byRefLocalsInitializers)
End Function
Private Shared Function HoistInDebugBuild(symbol As Symbol) As Boolean
Private Shared Function HoistInDebugBuild(symbol As Symbol, skipByRefLocals As Boolean) As Boolean
' In debug build hoist all parameters that can be hoisted:
If symbol.Kind = SymbolKind.Parameter Then
Dim parameter = TryCast(symbol, ParameterSymbol)
......@@ -91,6 +99,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return False
End If
If skipByRefLocals AndAlso local.IsByRef Then
Return False
End If
' hoist all user-defined locals that can be hoisted
If local.SynthesizedKind = SynthesizedLocalKind.UserDefined Then
Return Not local.Type.IsRestrictedType()
......
......@@ -936,6 +936,61 @@ BC36947: Single-line lambdas cannot have the 'Iterator' modifier. Use a multilin
</errors>)
End Sub
<Fact(), WorkItem(1173145, "DevDiv"), WorkItem(2862, "https://github.com/dotnet/roslyn/issues/2862")>
Public Sub CompoundAssignmentToAField()
Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(
<compilation>
<file name="a.vb">
<![CDATA[
Imports System.Collections
Imports System.Collections.Generic
Module Module1
Sub Main()
For Each x In New MyEnumerable(Of Integer)({100, 99, 98})
System.Console.WriteLine(x)
Next
End Sub
End Module
Public Class MyEnumerable(Of T)
Implements IEnumerable(Of T)
Private ReadOnly _items As T()
Private _count As Integer = 0
Public Sub New(items As T())
_items = items
_count = items.Length
End Sub
Public Iterator Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
For Each item In _items
If _count = 0 Then Exit Function
_count -= 1
Yield item
Next
End Function
Public Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
Return GetEnumerator()
End Function
End Class
]]>
</file>
</compilation>, TestOptions.DebugExe)
Dim expected As Xml.Linq.XCData = <![CDATA[
100
99
98
]]>
CompileAndVerify(compilation, expected)
CompileAndVerify(compilation.WithOptions(TestOptions.ReleaseExe), expected)
End Sub
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册