File: Symbols\EEMethodSymbol.vb
Web Access
Project: src\src\ExpressionEvaluator\VisualBasic\Source\ExpressionCompiler\Microsoft.CodeAnalysis.VisualBasic.ExpressionCompiler.vbproj (Microsoft.CodeAnalysis.VisualBasic.ExpressionCompiler)
' 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 System.Reflection
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.Collections
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Roslyn.Utilities
 
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
 
    Friend Delegate Function GenerateMethodBody(
        method As EEMethodSymbol,
        diagnostics As DiagnosticBag,
        <Out> ByRef properties As ResultProperties) As BoundStatement
 
    Friend NotInheritable Class EEMethodSymbol
        Inherits MethodSymbol
 
        Friend ReadOnly TypeMap As TypeSubstitution
        Friend ReadOnly SubstitutedSourceMethod As MethodSymbol
        Friend ReadOnly Locals As ImmutableArray(Of LocalSymbol)
        Friend ReadOnly LocalsForBinding As ImmutableArray(Of LocalSymbol)
 
        Private ReadOnly _compilation As VisualBasicCompilation
        Private ReadOnly _container As EENamedTypeSymbol
        Private ReadOnly _name As String
        Private ReadOnly _locations As ImmutableArray(Of Location)
        Private ReadOnly _typeParameters As ImmutableArray(Of TypeParameterSymbol)
        Private ReadOnly _parameters As ImmutableArray(Of ParameterSymbol)
        Private ReadOnly _meParameter As ParameterSymbol
        Private ReadOnly _displayClassVariables As ImmutableDictionary(Of String, DisplayClassVariable)
        Private ReadOnly _voidType As NamedTypeSymbol
 
        ''' <summary>
        ''' Invoked at most once to generate the method body.
        ''' (If the compilation has no errors, it will be invoked
        ''' exactly once, otherwise it may be skipped.)
        ''' </summary>
        Private ReadOnly _generateMethodBody As GenerateMethodBody
 
        Private _lazyReturnType As TypeSymbol
        Private _lazyResultProperties As ResultProperties
 
        ' NOTE: This is only used for asserts, so it could be conditional on DEBUG.
        Private ReadOnly _allTypeParameters As ImmutableArray(Of TypeParameterSymbol)
 
        Friend Sub New(
            compilation As VisualBasicCompilation,
            container As EENamedTypeSymbol,
            name As String,
            location As Location,
            sourceMethod As MethodSymbol,
            sourceLocals As ImmutableArray(Of LocalSymbol),
            sourceLocalsForBinding As ImmutableArray(Of LocalSymbol),
            sourceDisplayClassVariables As ImmutableDictionary(Of String, DisplayClassVariable),
            voidType As NamedTypeSymbol,
            generateMethodBody As GenerateMethodBody)
 
            Debug.Assert(sourceMethod.IsDefinition)
            Debug.Assert(TypeSymbol.Equals(sourceMethod.ContainingType, container.SubstitutedSourceType.OriginalDefinition, TypeCompareKind.ConsiderEverything))
            Debug.Assert(sourceLocals.All(Function(l) l.ContainingSymbol = sourceMethod))
 
            _compilation = compilation
            _container = container
            _name = name
            _locations = ImmutableArray.Create(location)
            _voidType = voidType
 
            ' What we want is to map all original type parameters to the corresponding new type parameters
            ' (since the old ones have the wrong owners).  Unfortunately, we have a circular dependency:
            '   1) Each new type parameter requires the entire map in order to be able to construct its constraint list.
            '   2) The map cannot be constructed until all new type parameters exist.
            ' Our solution is to pass each new type parameter a lazy reference to the type map.  We then 
            ' initialize the map as soon as the new type parameters are available - and before they are 
            ' handed out - so that there is never a period where they can require the type map and find
            ' it uninitialized.
 
            Dim sourceMethodTypeParameters = sourceMethod.TypeParameters
            Dim allSourceTypeParameters = container.SourceTypeParameters.Concat(sourceMethodTypeParameters)
 
            Dim getTypeMap As New Func(Of TypeSubstitution)(Function() TypeMap)
            _typeParameters = sourceMethodTypeParameters.SelectAsArray(
                Function(tp As TypeParameterSymbol, i As Integer, arg As Object) DirectCast(New EETypeParameterSymbol(Me, tp, i, getTypeMap), TypeParameterSymbol),
                DirectCast(Nothing, Object))
            _allTypeParameters = container.TypeParameters.Concat(_typeParameters)
            Me.TypeMap = TypeSubstitution.Create(sourceMethod, allSourceTypeParameters, ImmutableArrayExtensions.Cast(Of TypeParameterSymbol, TypeSymbol)(_allTypeParameters))
 
            EENamedTypeSymbol.VerifyTypeParameters(Me, _typeParameters)
 
            Dim substitutedSourceType = container.SubstitutedSourceType
            Me.SubstitutedSourceMethod = sourceMethod.AsMember(substitutedSourceType)
            If _typeParameters.Any() Then
                Me.SubstitutedSourceMethod = Me.SubstitutedSourceMethod.Construct(_typeParameters.As(Of TypeSymbol)())
            End If
            TypeParameterChecker.Check(Me.SubstitutedSourceMethod, _allTypeParameters)
 
            ' Create a map from original parameter to target parameter.
            Dim parameterBuilder = ArrayBuilder(Of ParameterSymbol).GetInstance()
 
            Dim substitutedSourceMeParameter = Me.SubstitutedSourceMethod.MeParameter
            Dim substitutedSourceHasMeParameter = substitutedSourceMeParameter IsNot Nothing
            If substitutedSourceHasMeParameter Then
                _meParameter = MakeParameterSymbol(0, GeneratedNames.MakeStateMachineCapturedMeName(), substitutedSourceMeParameter) ' NOTE: Name doesn't actually matter.
                Debug.Assert(TypeSymbol.Equals(_meParameter.Type, Me.SubstitutedSourceMethod.ContainingType, TypeCompareKind.ConsiderEverything))
                parameterBuilder.Add(_meParameter)
            End If
 
            Dim ordinalOffset = If(substitutedSourceHasMeParameter, 1, 0)
            For Each substitutedSourceParameter In Me.SubstitutedSourceMethod.Parameters
                Dim ordinal = substitutedSourceParameter.Ordinal + ordinalOffset
                Debug.Assert(ordinal = parameterBuilder.Count)
                Dim parameter = MakeParameterSymbol(ordinal, substitutedSourceParameter.Name, substitutedSourceParameter)
                parameterBuilder.Add(parameter)
            Next
 
            _parameters = parameterBuilder.ToImmutableAndFree()
 
            Dim localsBuilder = ArrayBuilder(Of LocalSymbol).GetInstance()
            Dim localsMap = PooledDictionary(Of LocalSymbol, LocalSymbol).GetInstance()
            For Each sourceLocal In sourceLocals
                Dim local = sourceLocal.ToOtherMethod(Me, Me.TypeMap)
                localsMap.Add(sourceLocal, local)
                localsBuilder.Add(local)
            Next
            Me.Locals = localsBuilder.ToImmutableAndFree()
            localsBuilder = ArrayBuilder(Of LocalSymbol).GetInstance()
            For Each sourceLocal In sourceLocalsForBinding
                Dim local As LocalSymbol = Nothing
                If Not localsMap.TryGetValue(sourceLocal, local) Then
                    local = sourceLocal.ToOtherMethod(Me, Me.TypeMap)
                    localsMap.Add(sourceLocal, local)
                End If
                localsBuilder.Add(local)
            Next
            Me.LocalsForBinding = localsBuilder.ToImmutableAndFree()
 
            ' Create a map from variable name to display class field.
            _displayClassVariables = SubstituteDisplayClassVariables(sourceDisplayClassVariables, localsMap, Me, Me.TypeMap)
            localsMap.Free()
 
            _generateMethodBody = generateMethodBody
        End Sub
 
        Private Shared Function SubstituteDisplayClassVariables(
            oldDisplayClassVariables As ImmutableDictionary(Of String, DisplayClassVariable),
            localsMap As Dictionary(Of LocalSymbol, LocalSymbol),
            otherMethod As MethodSymbol,
            typeMap As TypeSubstitution) As ImmutableDictionary(Of String, DisplayClassVariable)
 
            ' Create a map from variable name to display class field.
            Dim newDisplayClassVariables = PooledDictionary(Of String, DisplayClassVariable).GetInstance()
            For Each pair In oldDisplayClassVariables
                Dim variable = pair.Value
                Dim oldDisplayClassInstance = variable.DisplayClassInstance
 
                ' Note: we don't call ToOtherMethod in the local case because doing so would produce
                ' a new LocalSymbol that would not be ReferenceEquals to the one in this.LocalsForBinding.
                Dim oldDisplayClassInstanceFromLocal = TryCast(oldDisplayClassInstance, DisplayClassInstanceFromLocal)
                Dim newDisplayClassInstance = If(oldDisplayClassInstanceFromLocal Is Nothing,
                    oldDisplayClassInstance.ToOtherMethod(otherMethod, typeMap),
                    New DisplayClassInstanceFromLocal(DirectCast(localsMap(oldDisplayClassInstanceFromLocal.Local), EELocalSymbol)))
 
                variable = variable.SubstituteFields(newDisplayClassInstance, typeMap)
                newDisplayClassVariables.Add(pair.Key, variable)
            Next
 
            Dim result = newDisplayClassVariables.ToImmutableDictionary()
            newDisplayClassVariables.Free()
            Return result
        End Function
 
        Private Function MakeParameterSymbol(ordinal As Integer, name As String, sourceParameter As ParameterSymbol) As ParameterSymbol
            Return SynthesizedParameterSymbol.Create(
                Me,
                sourceParameter.Type,
                ordinal,
                sourceParameter.IsByRef,
                name,
                sourceParameter.CustomModifiers,
                sourceParameter.RefCustomModifiers)
        End Function
 
        Public Overrides ReadOnly Property MethodKind As MethodKind
            Get
                Return MethodKind.Ordinary
            End Get
        End Property
 
        Public Overrides ReadOnly Property Name As String
            Get
                Return _name
            End Get
        End Property
 
        Public Overrides ReadOnly Property Arity As Integer
            Get
                Return _typeParameters.Length
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsExtensionMethod As Boolean
            Get
                Return False
            End Get
        End Property
 
        Friend Overrides ReadOnly Property HasSpecialName As Boolean
            Get
                Return True
            End Get
        End Property
 
        Friend Overrides ReadOnly Property ImplementationAttributes As MethodImplAttributes
            Get
                Return Nothing
            End Get
        End Property
 
        Friend Overrides ReadOnly Property HasDeclarativeSecurity As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides Function GetDllImportData() As DllImportData
            Return Nothing
        End Function
 
        Friend Overrides Function GetSecurityInformation() As IEnumerable(Of Microsoft.Cci.SecurityAttribute)
            Throw ExceptionUtilities.Unreachable
        End Function
 
        Friend Overrides ReadOnly Property ReturnTypeMarshallingInformation As MarshalPseudoCustomAttributeData
            Get
                Return Nothing
            End Get
        End Property
 
        Friend Overrides Function TryGetMeParameter(<Out> ByRef meParameter As ParameterSymbol) As Boolean
            meParameter = Nothing
            Return True
        End Function
 
        Public Overrides ReadOnly Property IsVararg As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property ReturnsByRef As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsSub As Boolean
            Get
                Return ReturnType.SpecialType = SpecialType.System_Void
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsAsync As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property ReturnType As TypeSymbol
            Get
                If _lazyReturnType Is Nothing Then
                    Throw New InvalidOperationException()
                End If
                Return _lazyReturnType
            End Get
        End Property
 
        Public Overrides ReadOnly Property TypeArguments As ImmutableArray(Of TypeSymbol)
            Get
                Return ImmutableArrayExtensions.Cast(Of TypeParameterSymbol, TypeSymbol)(_typeParameters)
            End Get
        End Property
 
        Public Overrides ReadOnly Property TypeParameters As ImmutableArray(Of TypeParameterSymbol)
            Get
                Return _typeParameters
            End Get
        End Property
 
        Public Overrides ReadOnly Property Parameters As ImmutableArray(Of ParameterSymbol)
            Get
                Return _parameters
            End Get
        End Property
 
        Public Overrides ReadOnly Property ExplicitInterfaceImplementations As ImmutableArray(Of MethodSymbol)
            Get
                Return ImmutableArray(Of MethodSymbol).Empty
            End Get
        End Property
 
        Public Overrides ReadOnly Property ReturnTypeCustomModifiers As ImmutableArray(Of CustomModifier)
            Get
                Return ImmutableArray(Of CustomModifier).Empty
            End Get
        End Property
 
        Public Overrides ReadOnly Property RefCustomModifiers As ImmutableArray(Of CustomModifier)
            Get
                Return ImmutableArray(Of CustomModifier).Empty
            End Get
        End Property
 
        Public Overrides ReadOnly Property AssociatedSymbol As Symbol
            Get
                Return Nothing
            End Get
        End Property
 
        Friend Overrides Function GetAppliedConditionalSymbols() As ImmutableArray(Of String)
            Throw ExceptionUtilities.Unreachable
        End Function
 
        Friend Overrides ReadOnly Property CallingConvention As Cci.CallingConvention
            Get
                Debug.Assert(Me.IsShared)
                Dim cc = Cci.CallingConvention.Default
                If Me.IsVararg Then
                    cc = cc Or Cci.CallingConvention.ExtraArguments
                End If
                If Me.IsGenericMethod Then
                    cc = cc Or Cci.CallingConvention.Generic
                End If
                Return cc
            End Get
        End Property
 
        Friend Overrides ReadOnly Property GenerateDebugInfoImpl As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property ContainingSymbol As Symbol
            Get
                Return _container
            End Get
        End Property
 
        Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location)
            Get
                Return _locations
            End Get
        End Property
 
        Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference)
            Get
                Return GetDeclaringSyntaxReferenceHelper(Of VisualBasicSyntaxNode)(_locations)
            End Get
        End Property
 
        Public Overrides ReadOnly Property DeclaredAccessibility As Accessibility
            Get
                Return Accessibility.Internal
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsShared As Boolean
            Get
                Return True
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsOverridable As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsOverrides As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsMustOverride As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsNotOverridable As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsExternalMethod As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsIterator As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsInitOnly As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsOverloads As Boolean
            Get
                Return False
            End Get
        End Property
 
        Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
            Get
                Throw ExceptionUtilities.Unreachable
            End Get
        End Property
 
        Friend Overrides ReadOnly Property IsMethodKindBasedOnSyntax As Boolean
            Get
                Return False
            End Get
        End Property
 
        Friend Overrides ReadOnly Property Syntax As SyntaxNode
            Get
                Return Nothing
            End Get
        End Property
 
        Friend ReadOnly Property ResultProperties As ResultProperties
            Get
                Return _lazyResultProperties
            End Get
        End Property
 
#Disable Warning CA1200 ' Avoid using cref tags with a prefix
        ''' <remarks>
        ''' The corresponding C# method, 
        ''' <see cref="M:Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.EEMethodSymbol.GenerateMethodBody(Microsoft.CodeAnalysis.CSharp.TypeCompilationState,Microsoft.CodeAnalysis.DiagnosticBag)"/>, 
        ''' invokes the <see cref="LocalRewriter"/> and the <see cref="LambdaRewriter"/> explicitly.
        ''' In VB, the caller (of this method) does that.
        ''' </remarks>
#Enable Warning CA1200 ' Avoid using cref tags with a prefix
        Friend Overrides Function GetBoundMethodBody(compilationState As TypeCompilationState, diagnostics As BindingDiagnosticBag, <Out> ByRef Optional methodBodyBinder As Binder = Nothing) As BoundBlock
            Debug.Assert(diagnostics.DiagnosticBag IsNot Nothing)
 
            Dim body = _generateMethodBody(Me, diagnostics.DiagnosticBag, _lazyResultProperties)
            Debug.Assert(body IsNot Nothing)
 
            _lazyReturnType = CalculateReturnType(body)
 
            ' Can't do this until the return type has been computed.
            TypeParameterChecker.Check(Me, _allTypeParameters)
 
            Dim syntax As SyntaxNode = body.Syntax
            Dim statementsBuilder = ArrayBuilder(Of BoundStatement).GetInstance()
            statementsBuilder.Add(body)
            ' Insert an implicit return statement if necessary.
            If body.Kind <> BoundKind.ReturnStatement Then
                statementsBuilder.Add(New BoundReturnStatement(syntax, Nothing, Nothing, Nothing))
            End If
 
            Dim originalLocalsBuilder = ArrayBuilder(Of LocalSymbol).GetInstance()
            Dim originalLocalsSet = PooledHashSet(Of LocalSymbol).GetInstance()
            For Each local In LocalsForBinding
                Debug.Assert(Not originalLocalsSet.Contains(local))
                originalLocalsBuilder.Add(local)
                originalLocalsSet.Add(local)
            Next
            For Each local In Me.Locals
                If originalLocalsSet.Add(local) Then
                    originalLocalsBuilder.Add(local)
                End If
            Next
            originalLocalsSet.Free()
            Dim originalLocals = originalLocalsBuilder.ToImmutableAndFree()
            Dim newBody = New BoundBlock(syntax, Nothing, originalLocals, statementsBuilder.ToImmutableAndFree())
 
            If diagnostics.HasAnyErrors() Then
                Return newBody
            End If
 
            DiagnosticsPass.IssueDiagnostics(newBody, diagnostics.DiagnosticBag, Me)
            If diagnostics.HasAnyErrors() Then
                Return newBody
            End If
 
            ' Check for use-site errors (e.g. missing types in the signature).
            Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = Me.CalculateUseSiteInfo()
            If useSiteInfo.DiagnosticInfo IsNot Nothing Then
                diagnostics.Add(useSiteInfo, _locations(0))
                Return newBody
            End If
 
            Debug.Assert(Not newBody.HasErrors)
 
            ' NOTE: In C#, EE rewriting happens AFTER local rewriting.  However, that order would be difficult
            ' to accommodate in VB, so we reverse it.
 
            Try
                ' Rewrite local declaration statement.
                newBody = LocalDeclarationRewriter.Rewrite(_compilation, _container, newBody)
 
                ' Rewrite pseudo-variable references to helper method calls.
                newBody = DirectCast(PlaceholderLocalRewriter.Rewrite(_compilation, _container, newBody, diagnostics.DiagnosticBag), BoundBlock)
                If diagnostics.HasAnyErrors() Then
                    Return newBody
                End If
 
                ' Create a map from original local to target local.
                Dim localMap = PooledDictionary(Of LocalSymbol, LocalSymbol).GetInstance()
                Dim targetLocals = newBody.Locals
                Debug.Assert(originalLocals.Length = targetLocals.Length)
                For i = 0 To originalLocals.Length - 1
                    Dim originalLocal = originalLocals(i)
                    Dim targetLocal = targetLocals(i)
                    Debug.Assert(TypeOf originalLocal IsNot EELocalSymbol OrElse
                        DirectCast(originalLocal, EELocalSymbol).Ordinal = DirectCast(targetLocal, EELocalSymbol).Ordinal)
                    localMap.Add(originalLocal, targetLocal)
                Next
 
                ' Variables may have been captured by lambdas in the original method
                ' or in the expression, and we need to preserve the existing values of
                ' those variables in the expression. This requires rewriting the variables
                ' in the expression based on the closure classes from both the original
                ' method and the expression, and generating a preamble that copies
                ' values into the expression closure classes.
                '
                ' Consider the original method:
                ' Shared Sub M()
                '     Dim x, y, z as Integer
                '     ...
                '     F(Function() x + y)
                ' End Sub
                ' and the expression in the EE: "F(Function() x + z)".
                '
                ' The expression is first rewritten using the closure class and local <1>
                ' from the original method: F(Function() <1>.x + z)
                ' Then lambda rewriting introduces a new closure class that includes
                ' the locals <1> and z, and a corresponding local <2>: F(Function() <2>.<1>.x + <2>.z)
                ' And a preamble is added to initialize the fields of <2>:
                '     <2> = New <>c__DisplayClass0()
                '     <2>.<1> = <1>
                '     <2>.z = z
                '
                ' Note: The above behavior is actually implemented in the LambdaRewriter and
                '       is triggered by overriding PreserveOriginalLocals to return "True".
 
                ' Create a map from variable name to display class field.
                Dim displayClassVariables = SubstituteDisplayClassVariables(_displayClassVariables, localMap, Me, Me.TypeMap)
 
                ' Rewrite references to "Me" to refer to this method's "Me" parameter.
                ' Rewrite variables within body to reference existing display classes.
                newBody = DirectCast(CapturedVariableRewriter.Rewrite(
                    If(Me.SubstitutedSourceMethod.IsShared, Nothing, Me.Parameters(0)),
                    displayClassVariables,
                    newBody,
                    diagnostics.DiagnosticBag), BoundBlock)
 
                If diagnostics.HasAnyErrors() Then
                    Return newBody
                End If
 
                ' Insert locals from the original method, followed by any new locals.
                Dim localBuilder = ArrayBuilder(Of LocalSymbol).GetInstance()
                For Each originalLocal In Me.Locals
                    Dim targetLocal = localMap(originalLocal)
                    Debug.Assert(TypeOf targetLocal IsNot EELocalSymbol OrElse DirectCast(targetLocal, EELocalSymbol).Ordinal = localBuilder.Count)
                    localBuilder.Add(targetLocal)
                Next
 
                localMap.Free()
                newBody = newBody.Update(newBody.StatementListSyntax, localBuilder.ToImmutableAndFree(), newBody.Statements)
                TypeParameterChecker.Check(newBody, _allTypeParameters)
 
            Catch ex As BoundTreeVisitor.CancelledByStackGuardException
                ex.AddAnError(diagnostics)
            End Try
 
            Return newBody
        End Function
 
        Private Function CalculateReturnType(body As BoundStatement) As TypeSymbol
            Select Case body.Kind
                Case BoundKind.ReturnStatement
                    Return DirectCast(body, BoundReturnStatement).ExpressionOpt.Type
                Case BoundKind.ExpressionStatement,
                     BoundKind.RedimStatement
                    Return _voidType
                Case Else
                    Throw ExceptionUtilities.UnexpectedValue(body.Kind)
            End Select
        End Function
 
        Friend Overrides Sub AddSynthesizedReturnTypeAttributes(ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
            MyBase.AddSynthesizedReturnTypeAttributes(attributes)
 
            Dim returnType = Me.ReturnType
            If returnType.ContainsTupleNames() AndAlso DeclaringCompilation.HasTupleNamesAttributes() Then
                AddSynthesizedAttribute(attributes, DeclaringCompilation.SynthesizeTupleNamesAttribute(returnType))
            End If
        End Sub
 
        Friend Overrides Function CalculateLocalSyntaxOffset(localPosition As Integer, localTree As SyntaxTree) As Integer
            Return localPosition
        End Function
 
        Friend Overrides ReadOnly Property PreserveOriginalLocals As Boolean
            Get
                Return True
            End Get
        End Property
 
        Friend Overrides ReadOnly Property HasSetsRequiredMembers As Boolean
            Get
                Return False
            End Get
        End Property
    End Class
 
End Namespace