File: HoistedMeTests.vb
Web Access
Project: ..\..\..\src\ExpressionEvaluator\VisualBasic\Test\ExpressionCompiler\Microsoft.CodeAnalysis.VisualBasic.ExpressionCompiler.UnitTests.vbproj (Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.ExpressionCompiler.UnitTests)
' 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.
 
Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests
Imports Roslyn.Test.PdbUtilities
Imports Roslyn.Test.Utilities
Imports Xunit
 
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests
    Public Class HoistedMeTests
        Inherits ExpressionCompilerTestBase
 
        <Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1067379")>
        Public Sub InstanceIterator_NoCapturing()
            Const source = "
Class C
    Iterator Function F() As System.Collections.IEnumerable
        Yield 1
    End Function
End Class
"
            Const expectedIL = "
{
  // Code size        7 (0x7)
  .maxstack  1
  .locals init (Boolean V_0,
                Integer V_1)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C.VB$StateMachine_1_F.$VB$Me As C""
  IL_0006:  ret
}
"
            VerifyHasMe(source, "C.VB$StateMachine_1_F.MoveNext", "C", expectedIL)
        End Sub
 
        <Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1067379")>
        Public Sub InstanceAsync_NoCapturing()
            Const source = "
Imports System
Imports System.Threading.Tasks
 
Class C
    Async Function F() As Task
        Await Console.Out.WriteLineAsync(""a"")
    End Function
End Class
"
            Const expectedIL = "
{
  // Code size        7 (0x7)
  .maxstack  1
  .locals init (Integer V_0,
                System.Runtime.CompilerServices.TaskAwaiter V_1,
                C.VB$StateMachine_1_F V_2,
                System.Exception V_3)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C.VB$StateMachine_1_F.$VB$Me As C""
  IL_0006:  ret
}
"
            VerifyHasMe(source, "C.VB$StateMachine_1_F.MoveNext", "C", expectedIL)
        End Sub
 
        <Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1067379")>
        Public Sub InstanceLambda_NoCapturing()
            Const source = "
Class C
    Sub M()
        Dim a As System.Action = Sub() Equals(1, 2)
        a()
    End Sub
End Class
"
            ' This test documents the fact that, as in dev12, "Me"
            ' is unavailable while stepping through the lambda.  It
            ' would be preferable if it were.
            VerifyNoMe(source, "C._Closure$__._Lambda$__1-0")
        End Sub
 
        <Fact>
        Public Sub InstanceLambda_NoCapturingExceptThis()
            Const source = "
Class C
    Sub M()
        Dim a As System.Action = Sub() Equals(Me.GetHashCode(), 2)
        a()
    End Sub
End Class
"
            Const expectedIL = "
{
  // Code size        2 (0x2)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  ret
}
"
            VerifyHasMe(source, "C._Lambda$__1-0", "C", expectedIL)
        End Sub
 
        <Fact>
        Public Sub InstanceIterator_CapturedMe()
            Const source = "
Class C
    Iterator Function F() As System.Collections.IEnumerable
        Yield Me
    End Function
End Class
"
            Const expectedIL = "
{
  // Code size        7 (0x7)
  .maxstack  1
  .locals init (Boolean V_0,
                Integer V_1)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C.VB$StateMachine_1_F.$VB$Me As C""
  IL_0006:  ret
}
"
            VerifyHasMe(source, "C.VB$StateMachine_1_F.MoveNext", "C", expectedIL)
        End Sub
 
        <Fact>
        Public Sub InstanceAsync_CapturedMe()
            Const source = "
Imports System
Imports System.Threading.Tasks
 
Class C
    Async Function F() As Task
        Await Console.Out.WriteLineAsync(Me.ToString())
    End Function
End Class
"
            Const expectedIL = "
{
  // Code size        7 (0x7)
  .maxstack  1
  .locals init (Integer V_0,
                System.Runtime.CompilerServices.TaskAwaiter V_1,
                C.VB$StateMachine_1_F V_2,
                System.Exception V_3)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C.VB$StateMachine_1_F.$VB$Me As C""
  IL_0006:  ret
}
"
            VerifyHasMe(source, "C.VB$StateMachine_1_F.MoveNext", "C", expectedIL)
        End Sub
 
        <Fact>
        Public Sub InstanceLambda_CapturedMe_DisplayClass()
            Const source = "
Class C
    Private x As Integer
 
    Sub M(y As Integer)
        Dim a As System.Action = Sub() Equals(x, y)
        a()
    End Sub
End Class
"
            Const expectedIL = "
{
  // Code size        7 (0x7)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C._Closure$__2-0.$VB$Me As C""
  IL_0006:  ret
}
"
            VerifyHasMe(source, "C._Closure$__2-0._Lambda$__0", "C", expectedIL)
        End Sub
 
        <Fact>
        Public Sub InstanceLambda_CapturedMe_NoDisplayClass()
            Const source = "
Class C
    Private x As Integer
 
    Sub M()
        Dim a As System.Action = Sub() Equals(x, 1)
        a()
    End Sub
End Class
"
            Const expectedIL = "
{
  // Code size        2 (0x2)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  ret
}
"
            VerifyHasMe(source, "C._Lambda$__2-0", "C", expectedIL)
        End Sub
 
        <Fact>
        Public Sub InstanceIterator_Generic()
            Const source = "
Class C(Of T)
    Iterator Function F(Of U)() As System.Collections.IEnumerable
        Yield Me
    End Function
End Class
"
            Const expectedIL = "
{
  // Code size        7 (0x7)
  .maxstack  1
  .locals init (Boolean V_0,
                Integer V_1)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C(Of T).VB$StateMachine_1_F(Of U).$VB$Me As C(Of T)""
  IL_0006:  ret
}
"
            VerifyHasMe(source, "C.VB$StateMachine_1_F.MoveNext", "C(Of T)", expectedIL)
        End Sub
 
        <Fact>
        Public Sub InstanceAsync_Generic()
            Const source = "
Imports System
Imports System.Threading.Tasks
 
Class C(Of T)
    Async Function F(Of U)() As Task
        Await Console.Out.WriteLineAsync(Me.ToString())
    End Function
End Class
"
            Const expectedIL = "
{
  // Code size        7 (0x7)
  .maxstack  1
  .locals init (Integer V_0,
                System.Runtime.CompilerServices.TaskAwaiter V_1,
                C(Of T).VB$StateMachine_1_F(Of U) V_2,
                System.Exception V_3)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C(Of T).VB$StateMachine_1_F(Of U).$VB$Me As C(Of T)""
  IL_0006:  ret
}
"
            VerifyHasMe(source, "C.VB$StateMachine_1_F.MoveNext", "C(Of T)", expectedIL)
        End Sub
 
        <Fact>
        Public Sub InstanceLambda_Generic()
            Const source = "
Class C(Of T)
    Private x As Integer
 
    Sub M(Of U)(y As Integer)
        Dim a As System.Action = Sub() Equals(x, y)
        a()
    End Sub
End Class
"
            Const expectedIL = "
{
  // Code size        7 (0x7)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C(Of T)._Closure$__2-0(Of $CLS0).$VB$Me As C(Of T)""
  IL_0006:  ret
}
"
            VerifyHasMe(source, "C._Closure$__2-0._Lambda$__0", "C(Of T)", expectedIL)
        End Sub
 
        ' Note: Not actually an issue in VB, since the name isn't mangled.
        <Fact>
        Public Sub InstanceIterator_ExplicitInterfaceImplementation()
            Const source = "
Interface I
    Function F() As System.Collections.IEnumerable
End Interface
 
Class C : Implements I
    Iterator Function F() As System.Collections.IEnumerable Implements I.F
        Yield Me
    End Function
End Class
"
            Const expectedIL = "
{
  // Code size        7 (0x7)
  .maxstack  1
  .locals init (Boolean V_0,
                Integer V_1)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C.VB$StateMachine_1_F.$VB$Me As C""
  IL_0006:  ret
}
"
            VerifyHasMe(source, "C.VB$StateMachine_1_F.MoveNext", "C", expectedIL)
        End Sub
 
        ' Note: Not actually an issue in VB, since the name isn't mangled.
        <Fact>
        Public Sub InstanceAsync_ExplicitInterfaceImplementation()
            Const source = "
Imports System
Imports System.Threading.Tasks
 
Interface I
    Function F() As Task
End Interface
 
Class C : Implements I
    Async Function F() As Task Implements I.F
        Await Console.Out.WriteLineAsync(Me.ToString())
    End Function
End Class
"
            Const expectedIL = "
{
  // Code size        7 (0x7)
  .maxstack  1
  .locals init (Integer V_0,
                System.Runtime.CompilerServices.TaskAwaiter V_1,
                C.VB$StateMachine_1_F V_2,
                System.Exception V_3)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C.VB$StateMachine_1_F.$VB$Me As C""
  IL_0006:  ret
}
"
            VerifyHasMe(source, "C.VB$StateMachine_1_F.MoveNext", "C", expectedIL)
        End Sub
 
        <Fact>
        Public Sub InstanceLambda_ExplicitInterfaceImplementation()
            Const source = "
Interface I
    Sub M(y As Integer)
End Interface
 
Class C : Implements I
    Private x As Integer
 
    Sub M(y As Integer) Implements I.M
        Dim a As System.Action = Sub() Equals(x, y)
        a()
    End Sub
End Class
"
            Const expectedIL = "
{
  // Code size        7 (0x7)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C._Closure$__2-0.$VB$Me As C""
  IL_0006:  ret
}
"
            VerifyHasMe(source, "C._Closure$__2-0._Lambda$__0", "C", expectedIL)
        End Sub
 
        <Fact>
        Public Sub SharedIterator()
            Const source = "
Module M
    Iterator Function F() As System.Collections.IEnumerable
        Yield 1
    End Function
End Module
"
            VerifyNoMe(source, "M.VB$StateMachine_0_F.MoveNext")
        End Sub
 
        <Fact>
        Public Sub SharedAsync()
            Const source = "
Imports System
Imports System.Threading.Tasks
 
Module M
    Async Function F() As Task
        Await Console.Out.WriteLineAsync(""A"")
    End Function
End Module
"
            VerifyNoMe(source, "M.VB$StateMachine_0_F.MoveNext")
        End Sub
 
        <Fact>
        Public Sub SharedLambda()
            Const source = "
Module M
    Sub M(y As Integer)
        Dim a As System.Action = Sub() Equals(1, y)
        a()
    End Sub
End Module
"
            VerifyNoMe(source, "M._Closure$__0-0._Lambda$__0")
        End Sub
 
        <Fact>
        Public Sub ExtensionIterator()
            Const source = "
Module M
    <System.Runtime.CompilerServices.Extension>
    Iterator Function F(x As Integer) As System.Collections.IEnumerable
        Yield x
    End Function
End Module
"
            VerifyNoMe(source, "M.VB$StateMachine_0_F.MoveNext")
        End Sub
 
        <Fact>
        Public Sub ExtensionAsync()
            Const source = "
Imports System
Imports System.Threading.Tasks
 
Module M
    <System.Runtime.CompilerServices.Extension>
    Async Function F(x As Integer) As Task
        Await Console.Out.WriteLineAsync(""A"")
    End Function
End Module
"
            VerifyNoMe(source, "M.VB$StateMachine_0_F.MoveNext")
        End Sub
 
        <Fact>
        Public Sub ExtensionLambda()
            Const source = "
Module M
    <System.Runtime.CompilerServices.Extension>
    Sub M(y As Integer)
        Dim a As System.Action = Sub() Equals(1, y)
        a()
    End Sub
End Module
"
            VerifyNoMe(source, "M._Closure$__0-0._Lambda$__0")
        End Sub
 
        <Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1072296")>
        Public Sub OldStyleNonCapturingLambda()
            Const ilSource = "
.class public auto ansi C
       extends [mscorlib]System.Object
{
  .method public specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    ldarg.0
    call       instance void [mscorlib]System.Object::.ctor()
    ret
  }
 
  .method public instance void  M() cil managed
  {
    ldnull
    throw
  }
 
  .method private specialname static int32 
          _Lambda$__1() cil managed
  {
    ldnull
    throw
  }
 
} // end of class C
"
 
            Dim ilModule = ExpressionCompilerTestHelpers.GetModuleInstanceForIL(ilSource)
            Dim runtime = CreateRuntimeInstance(ilModule, {MscorlibRef})
            Dim context = CreateMethodContext(runtime, "C._Lambda$__1")
            VerifyNoMe(context)
        End Sub
 
        <Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1069554")>
        <WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1067379")>
        Public Sub LambdaLocations_HasThis()
            Const source = "
Imports System
 
Class C
    Private _toBeCaptured As Integer
 
    Private _f As Integer = (Function(x) (Function() _toBeCaptured + x + 1)() + 1)(1)
 
    Public Sub New()
        Dim l As Integer = (Function(x) (Function() _toBeCaptured + x + 2)() + 1)(1)
    End Sub
 
    Protected Overrides Sub Finalize()
        Dim l As Integer = (Function(x) (Function() _toBeCaptured + x + 3)() + 1)(1)
    End Sub
 
    Public Property P As Integer
        Get
            Return (Function(x) (Function() _toBeCaptured + x + 4)() + 1)(1)
        End Get
        Set(value As Integer)
            value = (Function(x) (Function() _toBeCaptured + x + 5)() + 1)(1)
        End Set
    End Property
 
    Public Custom Event E As Action
        AddHandler(value As Action)
            Dim l As Integer = (Function(x) (Function() _toBeCaptured + x + 6)() + 1)(1)
        End AddHandler
        RemoveHandler(value As Action)
            Dim l As Integer = (Function(x) (Function() _toBeCaptured + x + 7)() + 1)(1)
        End RemoveHandler
        RaiseEvent()
            Dim l As Integer = (Function(x) (Function() _toBeCaptured + x + 8)() + 1)(1)
        End RaiseEvent
    End Event
End Class
"
 
            Const expectedILTemplate = "
{{
  // Code size        7 (0x7)
  .maxstack  1
  .locals init (Object V_0)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C.{0}.$VB$Me As C""
  IL_0006:  ret
}}
"
 
            Dim comp = CreateEmptyCompilationWithReferences({VisualBasicSyntaxTree.ParseText(source)}, {MscorlibRef, MsvbRef}, TestOptions.DebugDll)
            WithRuntimeInstance(comp,
                Sub(runtime)
                    Dim compOptions = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All)
                    Dim dummyComp = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences((<Compilation/>), {comp.EmitToImageReference()}, compOptions)
                    Dim typeC = dummyComp.GlobalNamespace.GetMember(Of NamedTypeSymbol)("C")
                    Dim displayClassTypes = typeC.GetMembers().OfType(Of NamedTypeSymbol)()
                    Assert.True(displayClassTypes.Any())
                    For Each displayClassType In displayClassTypes
                        Dim displayClassName = displayClassType.Name
                        Assert.True(displayClassName.StartsWith(GeneratedNameConstants.DisplayClassPrefix, StringComparison.Ordinal))
                        For Each displayClassMethod In displayClassType.GetMembers().OfType(Of MethodSymbol)().Where(AddressOf IsLambda)
                            Dim lambdaMethodName = String.Format("C.{0}.{1}", displayClassName, displayClassMethod.Name)
                            Dim context = CreateMethodContext(runtime, lambdaMethodName)
                            Dim expectedIL = String.Format(expectedILTemplate, displayClassName)
                            VerifyHasMe(context, "C", expectedIL)
                        Next
                    Next
                End Sub)
        End Sub
 
        <Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1069554")>
        Public Sub LambdaLocations_NoThis()
            Const source = "
Imports System
 
Module M
    Private _f As Integer = (Function(x) (Function() x + 1)() + 1)(1)
 
    Sub New()
        Dim l As Integer = (Function(x) (Function() x + 2)() + 1)(1)
    End Sub
 
    Public Property P As Integer
        Get
            Return (Function(x) (Function() x + 3)() + 1)(1)
        End Get
        Set(value As Integer)
            value = (Function(x) (Function() x + 4)() + 1)(1)
        End Set
    End Property
 
    Public Custom Event E As Action
        AddHandler(value As Action)
            Dim l As Integer = (Function(x) (Function() x + 5)() + 1)(1)
        End AddHandler
        RemoveHandler(value As Action)
            Dim l As Integer = (Function(x) (Function() x + 6)() + 1)(1)
        End RemoveHandler
        RaiseEvent()
            Dim l As Integer = (Function(x) (Function() x + 7)() + 1)(1)
        End RaiseEvent
    End Event
End Module
"
 
            Dim comp = CreateEmptyCompilationWithReferences({VisualBasicSyntaxTree.ParseText(source)}, {MscorlibRef, MsvbRef}, TestOptions.DebugDll)
            WithRuntimeInstance(comp,
                Sub(runtime)
 
                    Dim dummyComp As VisualBasicCompilation = MakeDummyCompilation(comp)
                    Dim typeC = dummyComp.GlobalNamespace.GetMember(Of NamedTypeSymbol)("M")
                    Dim displayClassTypes = typeC.GetMembers().OfType(Of NamedTypeSymbol)()
                    Assert.True(displayClassTypes.Any())
                    For Each displayClassType In displayClassTypes
                        Dim displayClassName = displayClassType.Name
                        Assert.True(displayClassName.StartsWith(GeneratedNameConstants.DisplayClassPrefix, StringComparison.Ordinal))
                        For Each displayClassMethod In displayClassType.GetMembers().OfType(Of MethodSymbol)().Where(AddressOf IsLambda)
                            Dim lambdaMethodName = String.Format("M.{0}.{1}", displayClassName, displayClassMethod.Name)
                            Dim context = CreateMethodContext(runtime, lambdaMethodName)
                            VerifyNoMe(context)
                        Next
                    Next
                End Sub)
        End Sub
 
        Private Sub VerifyHasMe(source As String, moveNextMethodName As String, expectedType As String, expectedIL As String)
            Dim sourceCompilation = CreateEmptyCompilationWithReferences(
                {VisualBasicSyntaxTree.ParseText(source)},
                {MscorlibRef_v4_0_30316_17626, SystemRef_v4_0_30319_17929, MsvbRef_v4_0_30319_17929},
                TestOptions.DebugDll)
 
            WithRuntimeInstance(sourceCompilation,
                Sub(runtime)
                    VerifyHasMe(CreateMethodContext(runtime, moveNextMethodName), expectedType, expectedIL)
                End Sub)
 
            ' Now recompile and test CompileExpression with optimized code.
            WithRuntimeInstance(sourceCompilation.WithOptions(sourceCompilation.Options.WithOptimizationLevel(OptimizationLevel.Release)),
                Sub(runtime)
                    ' In VB, "Me" is never optimized away.
                    VerifyHasMe(CreateMethodContext(runtime, moveNextMethodName), expectedType, expectedIL:=Nothing)
                End Sub)
        End Sub
 
        Private Sub VerifyHasMe(context As EvaluationContext, expectedType As String, expectedIL As String)
            Dim locals = ArrayBuilder(Of LocalAndMethod).GetInstance()
            Dim typeName As String = Nothing
            Dim testData As New CompilationTestData()
            Dim assembly = context.CompileGetLocals(locals, argumentsOnly:=False, typeName:=typeName, testData:=testData)
            Assert.NotNull(assembly)
            Assert.NotEqual(0, assembly.Count)
            Dim localAndMethod = locals.Single(Function(l) l.LocalName = "Me")
            Dim methods = testData.GetMethodsByName()
            If expectedIL IsNot Nothing Then
                VerifyMethodData(methods.Single(Function(m) m.Key.Contains(localAndMethod.MethodName)).Value, expectedType, expectedIL)
            End If
            locals.Free()
 
            Dim errorMessage As String = Nothing
            testData = New CompilationTestData()
            context.CompileExpression("Me", errorMessage, testData)
            Assert.Null(errorMessage)
            If expectedIL IsNot Nothing Then
                VerifyMethodData(methods.Single(Function(m) m.Key.Contains("<>m0")).Value, expectedType, expectedIL)
            End If
        End Sub
 
        Private Shared Sub VerifyMethodData(methodData As CompilationTestData.MethodData, expectedType As String, expectedIL As String)
            methodData.VerifyIL(expectedIL)
            Dim method As MethodSymbol = DirectCast(methodData.Method, MethodSymbol)
            VerifyTypeParameters(method)
            Assert.Equal(expectedType, method.ReturnType.ToTestDisplayString())
        End Sub
 
        Private Sub VerifyNoMe(source As String, moveNextMethodName As String)
            Dim comp = CreateEmptyCompilationWithReferences(
                {VisualBasicSyntaxTree.ParseText(source)},
                {MscorlibRef_v4_0_30316_17626, SystemRef_v4_0_30319_17929, MsvbRef_v4_0_30319_17929},
                TestOptions.DebugDll)
            WithRuntimeInstance(comp,
                Sub(runtime)
                    VerifyNoMe(CreateMethodContext(runtime, moveNextMethodName))
                End Sub)
        End Sub
 
        Private Shared Sub VerifyNoMe(context As EvaluationContext)
            Dim locals = ArrayBuilder(Of LocalAndMethod).GetInstance()
            Dim typeName As String = Nothing
            Dim testData As New CompilationTestData()
            Dim assembly = context.CompileGetLocals(locals, argumentsOnly:=False, typeName:=typeName, testData:=testData)
            Assert.NotNull(assembly)
            AssertEx.None(locals, Function(l) l.LocalName.Contains("Me"))
            locals.Free()
 
            Dim errorMessage As String = Nothing
            testData = New CompilationTestData()
            context.CompileExpression("Me", errorMessage, testData)
            Assert.Contains(errorMessage,
                            {
                                "error BC32001: 'Me' is not valid within a Module.",
                                "error BC30043: 'Me' is valid only within an instance method."
                            })
 
            testData = New CompilationTestData()
            context.CompileExpression("MyBase.ToString()", errorMessage, testData)
            Assert.Contains(errorMessage,
                            {
                                "error BC32001: 'MyBase' is not valid within a Module.",
                                "error BC30043: 'MyBase' is valid only within an instance method."
                            })
 
            testData = New CompilationTestData()
            context.CompileExpression("MyClass.ToString()", errorMessage, testData)
            Assert.Contains(errorMessage,
                            {
                                "error BC30470: 'MyClass' cannot be used outside of a class.",
                                "error BC32001: 'MyClass' is not valid within a Module.",
                                "error BC30043: 'MyClass' is valid only within an instance method."
                            })
        End Sub
 
        <Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1024137")>
        Public Sub InstanceMembersInIterator()
            Const source = "
Class C
    Private x As Object
 
    Iterator Function F() As System.Collections.IEnumerable
        Yield Me.x
    End Function
End Class
"
            Dim comp = CreateCompilationWithMscorlib40({source}, options:=TestOptions.DebugDll)
            WithRuntimeInstance(comp,
                Sub(runtime)
                    Dim context = CreateMethodContext(runtime, "C.VB$StateMachine_2_F.MoveNext")
 
                    Dim resultProperties As ResultProperties = Nothing
                    Dim errorMessage As String = Nothing
                    Dim testData = New CompilationTestData()
                    context.CompileExpression("Me.x", errorMessage, testData)
                    Assert.Null(errorMessage)
                    testData.GetMethodData("<>x.<>m0").VerifyIL("
{
  // Code size       12 (0xc)
  .maxstack  1
  .locals init (Boolean V_0,
                Integer V_1)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C.VB$StateMachine_2_F.$VB$Me As C""
  IL_0006:  ldfld      ""C.x As Object""
  IL_000b:  ret
}
")
                End Sub)
        End Sub
 
        <Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1024137")>
        Public Sub InstanceMembersInLambda()
            Const source = "
Class C
    Private x As Object
 
    Sub F()
        Dim a As System.Action = Sub() Me.x.ToString()
        a()
    End Sub
End Class
"
            Dim comp = CreateCompilationWithMscorlib40({source}, options:=TestOptions.DebugDll)
            WithRuntimeInstance(comp,
                Sub(runtime)
                    Dim context = CreateMethodContext(runtime, "C._Lambda$__2-0")
 
                    Dim resultProperties As ResultProperties = Nothing
                    Dim errorMessage As String = Nothing
                    Dim testData = New CompilationTestData()
                    context.CompileExpression("Me.x", errorMessage, testData)
                    Assert.Null(errorMessage)
                    testData.GetMethodData("<>x.<>m0").VerifyIL("
{
  // Code size        7 (0x7)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C.x As Object""
  IL_0006:  ret
}
")
                End Sub)
        End Sub
 
        <Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1024137")>
        Public Sub InstanceMembersInAsync()
            Const source = "
Imports System
Imports System.Threading.Tasks
 
Class C
    Private x As Object
 
    Async Function F() As Task
        Await Console.Out.WriteLineAsync(Me.ToString())
    End Function
End Class
"
            Dim comp = CreateEmptyCompilationWithReferences(
                {VisualBasicSyntaxTree.ParseText(source)},
                {MscorlibRef_v4_0_30316_17626, SystemRef_v4_0_30319_17929, MsvbRef_v4_0_30319_17929},
                TestOptions.DebugDll)
            WithRuntimeInstance(comp,
                Sub(runtime)
                    Dim context = CreateMethodContext(runtime, "C.VB$StateMachine_2_F.MoveNext")
 
                    Dim resultProperties As ResultProperties = Nothing
                    Dim errorMessage As String = Nothing
                    Dim testData = New CompilationTestData()
                    context.CompileExpression("Me.x", errorMessage, testData)
                    Assert.Null(errorMessage)
                    testData.GetMethodData("<>x.<>m0").VerifyIL("
{
  // Code size       12 (0xc)
  .maxstack  1
  .locals init (Integer V_0,
                System.Runtime.CompilerServices.TaskAwaiter V_1,
                C.VB$StateMachine_2_F V_2,
                System.Exception V_3)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C.VB$StateMachine_2_F.$VB$Me As C""
  IL_0006:  ldfld      ""C.x As Object""
  IL_000b:  ret
}
")
                End Sub)
        End Sub
 
        <Fact>
        Public Sub BaseMembersInIterator()
            Const source = "
Class Base
    Protected x As Integer
End Class
 
Class Derived : Inherits Base
    Shadows Protected x As Object
 
    Iterator Function F() As System.Collections.IEnumerable
        Yield MyBase.x
    End Function
End Class
"
            Dim comp = CreateCompilationWithMscorlib40({source}, options:=TestOptions.DebugDll)
            WithRuntimeInstance(comp,
                Sub(runtime)
                    Dim context = CreateMethodContext(runtime, "Derived.VB$StateMachine_2_F.MoveNext")
 
                    Dim resultProperties As ResultProperties = Nothing
                    Dim errorMessage As String = Nothing
                    Dim testData = New CompilationTestData()
                    context.CompileExpression("MyBase.x", errorMessage, testData)
                    Assert.Null(errorMessage)
                    testData.GetMethodData("<>x.<>m0").VerifyIL("
{
  // Code size       12 (0xc)
  .maxstack  1
  .locals init (Boolean V_0,
                Integer V_1)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""Derived.VB$StateMachine_2_F.$VB$Me As Derived""
  IL_0006:  ldfld      ""Base.x As Integer""
  IL_000b:  ret
}
")
                End Sub)
        End Sub
 
        <Fact>
        Public Sub BaseMembersInAsync()
            Const source = "
Imports System
Imports System.Threading.Tasks
 
Class Base
    Protected x As Integer
End Class
 
Class Derived : Inherits Base
    Shadows Protected x As Object
 
    Async Function F() As Task
        Await Console.Out.WriteLineAsync(Me.ToString())
    End Function
End Class
"
            Dim comp = CreateEmptyCompilationWithReferences(
                {VisualBasicSyntaxTree.ParseText(source)},
                {MscorlibRef_v4_0_30316_17626, SystemRef_v4_0_30319_17929, MsvbRef_v4_0_30319_17929},
                TestOptions.DebugDll)
            WithRuntimeInstance(comp,
                Sub(runtime)
                    Dim context = CreateMethodContext(runtime, "Derived.VB$StateMachine_2_F.MoveNext")
 
                    Dim resultProperties As ResultProperties = Nothing
                    Dim errorMessage As String = Nothing
                    Dim testData = New CompilationTestData()
                    context.CompileExpression("MyBase.x", errorMessage, testData)
                    Assert.Null(errorMessage)
                    testData.GetMethodData("<>x.<>m0").VerifyIL("
{
  // Code size       12 (0xc)
  .maxstack  1
  .locals init (Integer V_0,
                System.Runtime.CompilerServices.TaskAwaiter V_1,
                Derived.VB$StateMachine_2_F V_2,
                System.Exception V_3)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""Derived.VB$StateMachine_2_F.$VB$Me As Derived""
  IL_0006:  ldfld      ""Base.x As Integer""
  IL_000b:  ret
}
")
                End Sub)
        End Sub
 
        <Fact>
        Public Sub BaseMembersInLambda()
            Const source = "
Class Base
    Protected x As Integer
End Class
 
Class Derived : Inherits Base
    Shadows Protected x As Object
 
    Sub F()
        Dim a As System.Action = Sub() Me.x.ToString()
        a()
    End Sub
End Class
"
            Dim comp = CreateCompilationWithMscorlib40({source}, options:=TestOptions.DebugDll)
            WithRuntimeInstance(comp,
                Sub(runtime)
                    Dim context = CreateMethodContext(runtime, "Derived._Lambda$__2-0")
 
                    Dim resultProperties As ResultProperties = Nothing
                    Dim errorMessage As String = Nothing
                    Dim testData = New CompilationTestData()
                    context.CompileExpression("MyBase.x", errorMessage, testData)
                    Assert.Null(errorMessage)
                    testData.GetMethodData("<>x.<>m0").VerifyIL("
{
  // Code size        7 (0x7)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""Base.x As Integer""
  IL_0006:  ret
}
")
                End Sub)
        End Sub
 
        <Fact>
        Public Sub IteratorOverloading_Parameters1()
            Const source = "
Imports System.Collections
 
Public Class C
    Public Iterator Function M() As IEnumerable
        Yield Me
    End Function
 
    Public Function M(x As Integer) As IEnumerable
        Return Nothing
    End Function
End Class
"
            CheckIteratorOverloading(source, Function(m) m.ParameterCount = 0)
        End Sub
 
        <Fact>
        Public Sub IteratorOverloading_Parameters2() ' Same as above, but declarations reversed.
            Const source = "
Imports System.Collections
 
Public Class C
    Public Function M(x As Integer) As IEnumerable
        Return Nothing
    End Function
 
    Public Iterator Function M() As IEnumerable
        Yield Me
    End Function
End Class
"
            ' NB: We pick the wrong overload, but it doesn't matter because 
            ' the methods have the same characteristics.
            ' Also, we don't require this behavior, we're just documenting it.
            CheckIteratorOverloading(source, Function(m) m.ParameterCount = 1)
        End Sub
 
        <Fact>
        Public Sub IteratorOverloading_Sharedness()
            Const source = "
Imports System.Collections
 
Public Class C
    Public Shared Function M(x As Integer) As IEnumerable
        Return Nothing
    End Function
 
    ' NB: We declare the interesting overload last so we know we're not
    ' just picking the first one by mistake.
    Public Iterator Function M() As IEnumerable
        Yield Me
    End Function
End Class
"
            CheckIteratorOverloading(source, Function(m) Not m.IsShared)
        End Sub
 
        <Fact>
        Public Sub IteratorOverloading_MustOverrideness()
            Const source = "
Imports System.Collections
 
Public MustInherit Class C
    Public MustOverride Function M(x As Integer) As IEnumerable
 
    ' NB: We declare the interesting overload last so we know we're not
    ' just picking the first one by mistake.
    Public Iterator Function M() As IEnumerable
        Yield Me
    End Function
End Class
"
            CheckIteratorOverloading(source, Function(m) Not m.IsMustOverride)
        End Sub
 
        <Fact>
        Public Sub IteratorOverloading_Arity1()
            Const source = "
Imports System.Collections
 
Public Class C
    Public Function M(Of T)(x As Integer) As IEnumerable
        Return Nothing
    End Function
 
    ' NB: We declare the interesting overload last so we know we're not
    ' just picking the first one by mistake.
    Public Iterator Function M() As IEnumerable
        Yield Me
    End Function
End Class
"
            CheckIteratorOverloading(source, Function(m) m.Arity = 0)
        End Sub
 
        <Fact>
        Public Sub IteratorOverloading_Arity2()
            Const source = "
Imports System.Collections
 
Public Class C
    Public Function M(x As Integer) As IEnumerable
        Return Nothing
    End Function
 
    ' NB: We declare the interesting overload last so we know we're not
    ' just picking the first one by mistake.
    Public Iterator Function M(Of T)() As IEnumerable
        Yield Me
    End Function
End Class
"
            CheckIteratorOverloading(source, Function(m) m.Arity = 1)
        End Sub
 
        <Fact>
        Public Sub IteratorOverloading_Constraints1()
            Const source = "
Imports System.Collections
 
Public Class C
    Public Function M(Of T As Structure)(x As Integer) As IEnumerable
        Return Nothing
    End Function
 
    ' NB: We declare the interesting overload last so we know we're not
    ' just picking the first one by mistake.
    Public Iterator Function M(Of T As Class)() As IEnumerable
        Yield Me
    End Function
End Class
"
            CheckIteratorOverloading(source, Function(m) m.TypeParameters.Single().HasReferenceTypeConstraint)
        End Sub
 
        <Fact>
        Public Sub IteratorOverloading_Constraints2()
            Const source = "
Imports System.Collections
Imports System.Collections.Generic
 
Public Class C
    ' NB: We declare the interesting overload last so we know we're not
    ' just picking the first one by mistake.
    Public Iterator Function M(Of T As IEnumerable(Of U), U As Class)() As IEnumerable
        Yield Me
    End Function
End Class
"
            ' NOTE: this isn't the feature we're switching on, but it is a convenient differentiator.
            CheckIteratorOverloading(source, Function(m) m.ParameterCount = 0)
        End Sub
 
        <Fact>
        Public Sub LambdaOverloading_NonGeneric()
            Const source = "
Public Class C
    Public Sub M(x As Integer)
        Dim a As System.Action = Sub() x.ToString()
    End Sub
End Class
"
            ' Note: We're picking the first method with the correct generic arity, etc.
            CheckLambdaOverloading(source, Function(m) m.MethodKind = MethodKind.Constructor)
        End Sub
 
        <Fact>
        Public Sub LambdaOverloading_Generic()
            Const source = "
Public Class C
    Public Sub M(Of T)(x As Integer)
        Dim a As System.Action = Sub() x.ToString()
    End Sub
End Class
"
            CheckLambdaOverloading(source, Function(m) m.Arity = 1)
        End Sub
 
        Private Shared Sub CheckIteratorOverloading(source As String, isDesiredOverload As Func(Of MethodSymbol, Boolean))
            CheckOverloading(
                source,
                Function(m) m.Name = "M" AndAlso isDesiredOverload(m),
                Function(originalType)
                    Dim stateMachineType = originalType.GetMembers().OfType(Of NamedTypeSymbol).Single(Function(t) t.Name.StartsWith(GeneratedNameConstants.StateMachineTypeNamePrefix, StringComparison.Ordinal))
                    Return stateMachineType.GetMember(Of MethodSymbol)("MoveNext")
                End Function)
        End Sub
 
        Private Shared Sub CheckLambdaOverloading(source As String, isDesiredOverload As Func(Of MethodSymbol, Boolean))
            CheckOverloading(
                source,
                isDesiredOverload,
                Function(originalType)
                    Dim displayClass As NamedTypeSymbol = originalType.GetMembers().OfType(Of NamedTypeSymbol).Single(Function(t) t.Name.StartsWith(GeneratedNameConstants.DisplayClassPrefix, StringComparison.Ordinal))
                    Return displayClass.GetMembers().OfType(Of MethodSymbol).Single(AddressOf IsLambda)
                End Function)
        End Sub
 
        Private Shared Function IsLambda(method As MethodSymbol) As Boolean
            Return method.Name.StartsWith(GeneratedNameConstants.LambdaMethodNamePrefix, StringComparison.Ordinal)
        End Function
 
        Private Shared Sub CheckOverloading(source As String, isDesiredOverload As Func(Of MethodSymbol, Boolean), getSynthesizedMethod As Func(Of NamedTypeSymbol, MethodSymbol))
            Dim comp = CreateCompilationWithMscorlib40({source}, options:=TestOptions.DebugDll)
            Dim dummyComp = MakeDummyCompilation(comp)
 
            Dim originalType = dummyComp.GlobalNamespace.GetMember(Of NamedTypeSymbol)("C")
            Dim desiredMethod = originalType.GetMembers().OfType(Of MethodSymbol).Single(isDesiredOverload)
 
            Dim synthesizedMethod As MethodSymbol = getSynthesizedMethod(originalType)
 
            Dim guessedMethod = CompilationContext.GetSubstitutedSourceMethod(synthesizedMethod, sourceMethodMustBeInstance:=True)
            Assert.Equal(desiredMethod, guessedMethod.OriginalDefinition)
        End Sub
 
        Private Shared Function MakeDummyCompilation(comp As VisualBasicCompilation) As VisualBasicCompilation
            Dim compOptions = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All)
            Return CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(<Compilation/>, {comp.EmitToImageReference()}, compOptions)
        End Function
    End Class
End Namespace