File: Binding\Binder_Invocation.vb
Web Access
Project: src\src\roslyn\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' 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.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax

Namespace Microsoft.CodeAnalysis.VisualBasic

    ' Binding of method/property invocation is implemented in this part.

    Partial Friend Class Binder

        Private Function CreateBoundMethodGroup(
            node As SyntaxNode,
            lookupResult As LookupResult,
            lookupOptionsUsed As LookupOptions,
            withDependencies As Boolean,
            receiver As BoundExpression,
            typeArgumentsOpt As BoundTypeArguments,
            qualKind As QualificationKind,
            Optional hasError As Boolean = False
        ) As BoundMethodGroup
            Dim pendingExtensionMethods As ExtensionMethodGroup = Nothing

            Debug.Assert(lookupResult.Kind = LookupResultKind.Good OrElse lookupResult.Kind = LookupResultKind.Inaccessible)

            ' Name lookup does not look for extension methods if it found a suitable
            ' instance method. So, if the first symbol we have is not a reduced extension
            ' method, we might need to look for extension methods later, on demand.
            Debug.Assert((lookupOptionsUsed And LookupOptions.EagerlyLookupExtensionMethods) = 0)
            If lookupResult.IsGood AndAlso Not lookupResult.Symbols(0).IsReducedExtensionMethod() Then
                pendingExtensionMethods = New ExtensionMethodGroup(Me, lookupOptionsUsed, withDependencies)
            End If

            Return New BoundMethodGroup(
                node,
                typeArgumentsOpt,
                lookupResult.Symbols.ToDowncastedImmutable(Of MethodSymbol),
                pendingExtensionMethods,
                lookupResult.Kind,
                receiver,
                qualKind,
                hasErrors:=hasError)
        End Function

        ''' <summary>
        ''' Returns if all the rules for a "Me.New" or "MyBase.New" constructor call are satisfied:
        '''   a) In instance constructor body
        '''   b) First statement of that constructor
        '''   c) "Me", "MyClass", or "MyBase" is the receiver.
        ''' </summary>
        Private Function IsConstructorCallAllowed(invocationExpression As InvocationExpressionSyntax, boundMemberGroup As BoundMethodOrPropertyGroup) As Boolean
            If Me.ContainingMember.Kind = SymbolKind.Method AndAlso DirectCast(Me.ContainingMember, MethodSymbol).MethodKind = MethodKind.Constructor Then
                ' (a) we are in an instance constructor body

                Dim node As VisualBasicSyntaxNode = invocationExpression.Parent
                If node Is Nothing OrElse (node.Kind <> SyntaxKind.CallStatement AndAlso node.Kind <> SyntaxKind.ExpressionStatement) Then
                    Return False
                End If

                Dim nodeParent As VisualBasicSyntaxNode = node.Parent
                If nodeParent Is Nothing OrElse nodeParent.Kind <> SyntaxKind.ConstructorBlock Then
                    Return False
                End If

                If DirectCast(nodeParent, ConstructorBlockSyntax).Statements(0) Is node Then
                    ' (b) call statement we are binding is 'the first' statement of the constructor
                    Dim receiver As BoundExpression = boundMemberGroup.ReceiverOpt

                    If receiver IsNot Nothing AndAlso (receiver.Kind = BoundKind.MeReference OrElse
                                                       receiver.Kind = BoundKind.MyBaseReference OrElse
                                                       receiver.Kind = BoundKind.MyClassReference) Then
                        ' (c) receiver is 'Me'/'MyClass'/'MyBase'
                        Return True
                    End If
                End If
            End If

            Return False
        End Function

        Friend Class ConstructorCallArgumentsBinder
            Inherits Binder

            Public Sub New(containingBinder As Binder)
                MyBase.New(containingBinder)
            End Sub

            Protected Overrides ReadOnly Property IsInsideChainedConstructorCallArguments As Boolean
                Get
                    Return True
                End Get
            End Property
        End Class

        ''' <summary>
        ''' Bind a Me.New(...), MyBase.New (...), MyClass.New(...) constructor call. 
        ''' (NOT a normal constructor call like New Type(...)).
        ''' </summary>
        Private Function BindDirectConstructorCall(node As InvocationExpressionSyntax, group As BoundMethodGroup, diagnostics As BindingDiagnosticBag) As BoundExpression
            Dim boundArguments As ImmutableArray(Of BoundExpression) = Nothing
            Dim argumentNames As ImmutableArray(Of String) = Nothing
            Dim argumentNamesLocations As ImmutableArray(Of Location) = Nothing
            Dim argumentList As ArgumentListSyntax = node.ArgumentList

            Debug.Assert(IsGroupOfConstructors(group))

            ' Direct constructor call is only allowed if: (a) we are in an instance constructor body,
            ' and (b) call statement we are binding is 'the first' statement of the constructor, 
            ' and (c) receiver is 'Me'/'MyClass'/'MyBase'
            If IsConstructorCallAllowed(node, group) Then
                ' Bind arguments with special binder that prevents use of Me.
                Dim argumentsBinder As Binder = New ConstructorCallArgumentsBinder(Me)
                argumentsBinder.BindArgumentsAndNames(argumentList, boundArguments, argumentNames, argumentNamesLocations, diagnostics)

                ' Bind constructor call, errors will be generated if needed
                Return BindInvocationExpression(node, node.Expression, ExtractTypeCharacter(node.Expression),
                                                group, boundArguments, argumentNames, diagnostics,
                                                allowConstructorCall:=True, callerInfoOpt:=group.Syntax)
            Else
                ' Error case -- constructor call in wrong location.
                ' Report error BC30282 about invalid constructor call
                ' For semantic model / IDE purposes, we still bind it even if in a location that wasn't allowed.
                If Not group.HasErrors Then
                    ReportDiagnostic(diagnostics, group.Syntax, ERRID.ERR_InvalidConstructorCall)
                End If

                BindArgumentsAndNames(argumentList, boundArguments, argumentNames, argumentNamesLocations, diagnostics)

                ' Bind constructor call, ignore errors by putting into discarded bag.
                Dim expr = BindInvocationExpression(node, node.Expression, ExtractTypeCharacter(node.Expression),
                                                group, boundArguments, argumentNames, BindingDiagnosticBag.Discarded,
                                                allowConstructorCall:=True, callerInfoOpt:=group.Syntax)
                If expr.Kind = BoundKind.Call Then
                    ' Set HasErrors to prevent cascading errors.
                    Dim callExpr = DirectCast(expr, BoundCall)
                    expr = New BoundCall(
                        callExpr.Syntax,
                        callExpr.Method,
                        callExpr.MethodGroupOpt,
                        callExpr.ReceiverOpt,
                        callExpr.Arguments,
                        callExpr.DefaultArguments,
                        callExpr.ConstantValueOpt,
                        isLValue:=False,
                        suppressObjectClone:=False,
                        type:=callExpr.Type,
                        hasErrors:=True)
                End If

                Return expr
            End If

        End Function

        Private Function BindInvocationExpression(node As InvocationExpressionSyntax, diagnostics As BindingDiagnosticBag) As BoundExpression

            ' Set "IsInvocationsOrAddressOf" to prevent binding to return value variable.
            Dim target As BoundExpression

            If node.Expression Is Nothing Then
                ' Must be conditional case
                Dim conditionalAccess As ConditionalAccessExpressionSyntax = node.GetCorrespondingConditionalAccessExpression()

                If conditionalAccess IsNot Nothing Then
                    target = GetConditionalAccessReceiver(conditionalAccess)
                Else
                    target = ReportDiagnosticAndProduceBadExpression(diagnostics, node, ERRID.ERR_Syntax).MakeCompilerGenerated()
                End If
            Else
                target = BindExpression(node.Expression, diagnostics:=diagnostics, isInvocationOrAddressOf:=True, isOperandOfConditionalBranch:=False, eventContext:=False)
            End If

            ' If 'target' is a bound constructor group, we need to do special checks and special processing of arguments.
            If target.Kind = BoundKind.MethodGroup Then
                Dim group = DirectCast(target, BoundMethodGroup)
                If IsGroupOfConstructors(group) Then
                    Return BindDirectConstructorCall(node, group, diagnostics)
                End If
            End If

            Dim boundArguments As ImmutableArray(Of BoundExpression) = Nothing
            Dim argumentNames As ImmutableArray(Of String) = Nothing
            Dim argumentNamesLocations As ImmutableArray(Of Location) = Nothing
            Me.BindArgumentsAndNames(node.ArgumentList, boundArguments, argumentNames, argumentNamesLocations, diagnostics)

            If target.Kind = BoundKind.MethodGroup OrElse target.Kind = BoundKind.PropertyGroup Then
                Return BindInvocationExpressionPossiblyWithoutArguments(
                    node,
                    ExtractTypeCharacter(node.Expression),
                    DirectCast(target, BoundMethodOrPropertyGroup),
                    boundArguments,
                    argumentNames,
                    argumentNamesLocations,
                    allowBindingWithoutArguments:=True,
                    diagnostics:=diagnostics)
            End If

            If target.Kind = BoundKind.NamespaceExpression Then
                Dim namespaceExp As BoundNamespaceExpression = DirectCast(target, BoundNamespaceExpression)
                Dim diagInfo = ErrorFactory.ErrorInfo(ERRID.ERR_NamespaceNotExpression1, namespaceExp.NamespaceSymbol)
                ReportDiagnostic(diagnostics, node.Expression, diagInfo)

            ElseIf target.Kind = BoundKind.TypeExpression Then
                Dim typeExp As BoundTypeExpression = DirectCast(target, BoundTypeExpression)

                If Not IsCallStatementContext(node) Then
                    ' Try default instance property through DefaultInstanceAlias
                    Dim instance As BoundExpression = TryDefaultInstanceProperty(typeExp, diagnostics)

                    If instance IsNot Nothing Then
                        Return BindIndexedInvocationExpression(
                            node,
                            instance,
                            boundArguments,
                            argumentNames,
                            argumentNamesLocations,
                            allowBindingWithoutArguments:=False,
                            hasIndexableTarget:=False,
                            diagnostics:=diagnostics)
                    End If
                End If

                Dim diagInfo = ErrorFactory.ErrorInfo(GetTypeNotExpressionErrorId(typeExp.Type), typeExp.Type)
                ReportDiagnostic(diagnostics, node.Expression, diagInfo)

            Else
                Return BindIndexedInvocationExpression(
                        node,
                        target,
                        boundArguments,
                        argumentNames,
                        argumentNamesLocations,
                        allowBindingWithoutArguments:=True,
                        hasIndexableTarget:=False,
                        diagnostics:=diagnostics)
            End If

            Return GenerateBadExpression(node, target, boundArguments)
        End Function

        ''' <summary>
        ''' Bind an invocation expression representing an array access,
        ''' delegate invocation, or default member.
        ''' </summary>
        Private Function BindIndexedInvocationExpression(
            node As InvocationExpressionSyntax,
            target As BoundExpression,
            boundArguments As ImmutableArray(Of BoundExpression),
            argumentNames As ImmutableArray(Of String),
            argumentNamesLocations As ImmutableArray(Of Location),
            allowBindingWithoutArguments As Boolean,
            <Out()> ByRef hasIndexableTarget As Boolean,
            diagnostics As BindingDiagnosticBag) As BoundExpression

            Debug.Assert(target.Kind <> BoundKind.NamespaceExpression)
            Debug.Assert(target.Kind <> BoundKind.TypeExpression)
            Debug.Assert(target.Kind <> BoundKind.MethodGroup)
            Debug.Assert(target.Kind <> BoundKind.PropertyGroup)

            hasIndexableTarget = False

            If Not target.IsLValue AndAlso target.Kind <> BoundKind.LateMemberAccess Then
                target = MakeRValue(target, diagnostics)
            End If

            Dim targetType As TypeSymbol = target.Type

            ' there are values or variables like "Nothing" which have no type
            If targetType IsNot Nothing Then

                ' this method is also called for e.g. Arrays because they are also InvocationExpressions
                ' if target is an array, then call BindArrayAccess only if target is not a direct successor
                ' of a call statement
                If targetType.IsArrayType Then
                    hasIndexableTarget = True

                    ' only bind to an array if this method was called outside of a call statement context
                    If Not IsCallStatementContext(node) Then
                        Return BindArrayAccess(node, target, boundArguments, argumentNames, diagnostics)
                    End If

                ElseIf targetType.Kind = SymbolKind.NamedType AndAlso targetType.TypeKind = TypeKind.Delegate Then
                    hasIndexableTarget = True

                    ' an invocation of a delegate actually calls the delegate's Invoke method.
                    Dim delegateInvoke = DirectCast(targetType, NamedTypeSymbol).DelegateInvokeMethod

                    If delegateInvoke Is Nothing Then
                        If Not target.HasErrors Then
                            ReportDiagnostic(diagnostics, target.Syntax, ERRID.ERR_DelegateNoInvoke1, target.Type)
                        End If

                    ElseIf ReportDelegateInvokeUseSite(diagnostics, target.Syntax, targetType, delegateInvoke) Then
                        delegateInvoke = Nothing
                    End If

                    If delegateInvoke IsNot Nothing Then
                        Dim methodGroup = New BoundMethodGroup(
                            If(node.Expression, node),
                            Nothing,
                            ImmutableArray.Create(Of MethodSymbol)(delegateInvoke),
                            LookupResultKind.Good,
                            target,
                            QualificationKind.QualifiedViaValue).MakeCompilerGenerated()

                        Return BindInvocationExpression(
                            node,
                            If(node.Expression, node),
                            ExtractTypeCharacter(node.Expression),
                            methodGroup,
                            boundArguments,
                            argumentNames,
                            diagnostics,
                            callerInfoOpt:=node,
                            representCandidateInDiagnosticsOpt:=targetType)
                    Else
                        Dim badExpressionChildren = ArrayBuilder(Of BoundExpression).GetInstance()
                        badExpressionChildren.Add(target)
                        badExpressionChildren.AddRange(boundArguments)
                        Return BadExpression(node, badExpressionChildren.ToImmutableAndFree(), ErrorTypeSymbol.UnknownResultType)
                    End If
                End If
            End If

            If target.Kind = BoundKind.BadExpression Then
                ' Error already reported for a bad expression, so don't report another error

            ElseIf Not IsCallStatementContext(node) Then
                ' If the invocation is outside of a call statement
                ' context, bind to the default property group if any.

                If target.Type.SpecialType = SpecialType.System_Object OrElse
                   target.Type.SpecialType = SpecialType.System_Array Then

                    hasIndexableTarget = True

                    Return BindLateBoundInvocation(node, Nothing, target, boundArguments, argumentNames, diagnostics,
                                                   suppressLateBindingResolutionDiagnostics:=(target.Kind = BoundKind.LateMemberAccess))
                End If

                If Not target.HasErrors Then
                    ' Bind to the default property group.
                    Dim defaultPropertyGroup As BoundExpression = BindDefaultPropertyGroup(If(node.Expression, node), target, diagnostics)

                    If defaultPropertyGroup IsNot Nothing Then
                        Debug.Assert(defaultPropertyGroup.Kind = BoundKind.PropertyGroup OrElse
                                     defaultPropertyGroup.Kind = BoundKind.MethodGroup OrElse
                                     defaultPropertyGroup.HasErrors)

                        hasIndexableTarget = True

                        If defaultPropertyGroup.Kind = BoundKind.PropertyGroup OrElse defaultPropertyGroup.Kind = BoundKind.MethodGroup Then
                            Return BindInvocationExpressionPossiblyWithoutArguments(
                                node,
                                TypeCharacter.None,
                                DirectCast(defaultPropertyGroup, BoundMethodOrPropertyGroup),
                                boundArguments,
                                argumentNames,
                                argumentNamesLocations,
                                allowBindingWithoutArguments,
                                diagnostics)
                        End If
                    Else
                        ReportNoDefaultProperty(target, diagnostics)
                    End If
                End If

            ElseIf target.Kind = BoundKind.LateMemberAccess Then
                hasIndexableTarget = True

                Dim lateMember = DirectCast(target, BoundLateMemberAccess)
                Return BindLateBoundInvocation(node, Nothing, lateMember, boundArguments, argumentNames, diagnostics)

            ElseIf Not target.HasErrors Then
                ' "Expression is not a method."
                Dim diagInfo = ErrorFactory.ErrorInfo(ERRID.ERR_ExpectedProcedure)
                ReportDiagnostic(diagnostics, If(node.Expression, node), diagInfo)
            End If

            Return GenerateBadExpression(node, target, boundArguments)
        End Function

        Private Function BindInvocationExpressionPossiblyWithoutArguments(
            node As InvocationExpressionSyntax,
            typeChar As TypeCharacter,
            group As BoundMethodOrPropertyGroup,
            boundArguments As ImmutableArray(Of BoundExpression),
            argumentNames As ImmutableArray(Of String),
            argumentNamesLocations As ImmutableArray(Of Location),
            allowBindingWithoutArguments As Boolean,
            diagnostics As BindingDiagnosticBag) As BoundExpression

            ' Spec §11.8 Invocation Expressions
            ' ...
            ' If the method group only contains one accessible method, including both instance and 
            ' extension methods, and that method takes no arguments and is a function, then the method 
            ' group is interpreted as an invocation expression with an empty argument list and the result 
            ' is used as the target of an invocation expression with the provided argument list(s).
            If allowBindingWithoutArguments AndAlso
                boundArguments.Length > 0 AndAlso
                Not IsCallStatementContext(node) AndAlso
                ShouldBindWithoutArguments(node, group, diagnostics) Then

                Dim tmpDiagnostics = BindingDiagnosticBag.GetInstance(diagnostics)
                Dim result As BoundExpression = Nothing

                Debug.Assert(node.Expression IsNot Nothing)

                ' NOTE: when binding without arguments, we pass node.Expression as the first parameter 
                ' so that the new bound node references it instead of invocation expression
                Dim withoutArgs = BindInvocationExpression(
                            node.Expression,
                            node.Expression,
                            typeChar,
                            group,
                            ImmutableArray(Of BoundExpression).Empty,
                            Nothing,
                            tmpDiagnostics,
                            callerInfoOpt:=group.Syntax)

                If withoutArgs.Kind = BoundKind.Call OrElse withoutArgs.Kind = BoundKind.PropertyAccess Then
                    ' We were able to bind the method group or property access without arguments,
                    ' possibly with some diagnostic.
                    diagnostics.AddRange(tmpDiagnostics)
                    tmpDiagnostics.Clear()

                    If withoutArgs.Kind = BoundKind.PropertyAccess Then
                        Dim receiverOpt As BoundExpression = DirectCast(withoutArgs, BoundPropertyAccess).ReceiverOpt
                        If receiverOpt?.Syntax Is withoutArgs.Syntax AndAlso Not receiverOpt.WasCompilerGenerated Then
                            withoutArgs.MakeCompilerGenerated()
                        End If

                        withoutArgs = MakeRValue(withoutArgs, diagnostics)

                    Else
                        Dim receiverOpt As BoundExpression = DirectCast(withoutArgs, BoundCall).ReceiverOpt
                        If receiverOpt?.Syntax Is withoutArgs.Syntax AndAlso Not receiverOpt.WasCompilerGenerated Then
                            withoutArgs.MakeCompilerGenerated()
                        End If
                    End If

                    If withoutArgs.Kind = BoundKind.BadExpression Then
                        result = GenerateBadExpression(node, withoutArgs, boundArguments)

                    Else
                        Dim hasIndexableTarget = False

                        ' Bind the invocation with arguments as an indexed invocation.
                        Dim withArgs = BindIndexedInvocationExpression(
                            node,
                            withoutArgs,
                            boundArguments,
                            argumentNames,
                            argumentNamesLocations,
                            allowBindingWithoutArguments:=False,
                            hasIndexableTarget:=hasIndexableTarget,
                            diagnostics:=tmpDiagnostics)

                        If hasIndexableTarget Then
                            diagnostics.AddRange(tmpDiagnostics)
                            result = withArgs

                        Else
                            ' Report BC32016 if something wrong.
                            ReportDiagnostic(diagnostics,
                                             node.Expression,
                                             ERRID.ERR_FunctionResultCannotBeIndexed1,
                                             withoutArgs.ExpressionSymbol)

                            ' If result of binding with no args was not indexable after all, then instead
                            ' of just producing a bad expression, bind the invocation expression normally,
                            ' but without reporting any more diagnostics. This produces more accurate
                            ' bound nodes for semantic model questions and may allow the type of the
                            ' expression to be computed, thus leading to fewer errors later.
                            result = BindInvocationExpression(
                                node,
                                node.Expression,
                                typeChar,
                                group,
                                boundArguments,
                                argumentNames,
                                BindingDiagnosticBag.Discarded,
                                callerInfoOpt:=group.Syntax)
                        End If
                    End If
                End If

                tmpDiagnostics.Free()

                If result IsNot Nothing Then
                    Return result
                End If
            End If

            Return BindInvocationExpression(
                node,
                If(node.Expression, group.Syntax),
                typeChar,
                group,
                boundArguments,
                argumentNames,
                diagnostics,
                callerInfoOpt:=group.Syntax)
        End Function

        ''' <summary>
        ''' Returns a BoundPropertyGroup if the expression represents a valid
        ''' default property access. If there is a default property but the property
        ''' access is invalid, a BoundBadExpression is returned. If there is no
        ''' default property for the expression type, Nothing is returned.
        ''' 
        ''' Note, that default Query Indexer may be a method, not a property.
        ''' </summary>
        Private Function BindDefaultPropertyGroup(node As VisualBasicSyntaxNode, target As BoundExpression, diagnostics As BindingDiagnosticBag) As BoundExpression
            Dim result = LookupResult.GetInstance()
            Dim defaultMemberGroup As BoundExpression = Nothing
            Dim useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics)

            MemberLookup.LookupDefaultProperty(result, target.Type, Me, useSiteInfo)

            ' We're not reporting any diagnostic if there are no symbols.
            Debug.Assert(result.HasSymbol OrElse Not result.HasDiagnostic)

            If result.HasSymbol Then
                defaultMemberGroup = BindSymbolAccess(node, result, LookupOptions.Default, target, Nothing, QualificationKind.QualifiedViaValue, diagnostics)
                Debug.Assert(defaultMemberGroup IsNot Nothing)
                Debug.Assert((defaultMemberGroup.Kind = BoundKind.BadExpression) OrElse (defaultMemberGroup.Kind = BoundKind.PropertyGroup))

            Else
                ' All queryable sources have default indexer, which maps to an ElementAtOrDefault method or property on the source.
                Dim tempDiagnostics = BindingDiagnosticBag.GetInstance(diagnostics)

                target = MakeRValue(target, tempDiagnostics)

                Dim controlVariableType As TypeSymbol = Nothing
                target = ConvertToQueryableType(target, tempDiagnostics, controlVariableType)

                If controlVariableType IsNot Nothing Then
                    result.Clear()

                    Const options As LookupOptions = LookupOptions.AllMethodsOfAnyArity ' overload resolution filters methods by arity.

                    LookupMember(result, target.Type, StringConstants.ElementAtMethod, 0, options, useSiteInfo)

                    If result.IsGood Then
                        Dim kind As SymbolKind = result.Symbols(0).Kind

                        If kind = SymbolKind.Method OrElse kind = SymbolKind.Property Then
                            diagnostics.AddRange(tempDiagnostics)
                            defaultMemberGroup = BindSymbolAccess(node, result, options, target, Nothing, QualificationKind.QualifiedViaValue, diagnostics)
                        End If
                    End If
                End If

                tempDiagnostics.Free()
            End If

            diagnostics.Add(node, useSiteInfo)
            result.Free()

            ' We don't want the default property GROUP to override the meaning of the item it's being 
            ' accessed off of, so mark it as compiler generated.
            If defaultMemberGroup IsNot Nothing Then
                defaultMemberGroup.SetWasCompilerGenerated()
            End If

            Return defaultMemberGroup
        End Function

        ''' <summary>
        ''' Tests whether or not the method or property group should be bound without arguments. 
        ''' In case of method group it may also update the group by filtering out all subs
        ''' </summary>
        Private Function ShouldBindWithoutArguments(node As VisualBasicSyntaxNode, ByRef group As BoundMethodOrPropertyGroup, diagnostics As BindingDiagnosticBag) As Boolean
            Dim useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics)
            Dim result = ShouldBindWithoutArguments(group, useSiteInfo)
            diagnostics.Add(node, useSiteInfo)
            Return result
        End Function

        Private Function ShouldBindWithoutArguments(ByRef group As BoundMethodOrPropertyGroup, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As Boolean

            If group.Kind = BoundKind.MethodGroup Then

                Dim newMethods As ArrayBuilder(Of MethodSymbol) = ArrayBuilder(Of MethodSymbol).GetInstance()

                ' check method group members
                Dim methodGroup = DirectCast(group, BoundMethodGroup)
                Debug.Assert(methodGroup.Methods.Length > 0)

                ' any sub should be removed from a group in case we try binding without arguments
                Dim shouldUpdateGroup As Boolean = False
                Dim atLeastOneFunction As Boolean = False

                ' Dev10 behavior: 
                ' For instance methods - 
                '     Check if all functions from the group (ignoring subs) 
                '     have the same arity as specified in the call and 0 parameters.
                '     However, the part that handles arity check is rather inconsistent between methods 
                '     overloaded within the same type and in derived type. Also, language spec doesn't mention 
                '     any restrictions for arity. So, we will not try to duplicate Dev10 logic around arity 
                '     because the logic is close to impossible to match and behavior change will not be a breaking
                '     change.
                ' In presence of extension methods the rules are more constrained-
                '    If group contains an extension method, it must be the only method in the group,
                '    it must have no parameters, must have no type parameters and must be a Function.

                ' Note, we should avoid requesting AdditionalExtensionMethods whenever possible because 
                ' lookup of extension methods might be very expensive.
                Dim extensionMethod As MethodSymbol = Nothing

                For Each method In methodGroup.Methods

                    If method.IsReducedExtensionMethod Then
                        extensionMethod = method
                        Exit For
                    End If

                    If (method.IsSub) Then
                        If method.CanBeCalledWithNoParameters() Then
                            ' If its a sub that could be called parameterlessly, it might hide the function. So it is included
                            ' in the group for further processing in overload resolution (which will process possible hiding).
                            ' If overload resolution does select the Sub, we'll get an error about return type not indexable. 
                            ' See Roslyn bug 14019 for example.
                            newMethods.Add(method)
                        Else
                            ' ignore other subs entirely 
                            shouldUpdateGroup = True
                        End If
                    ElseIf method.ParameterCount > 0 Then
                        ' any function with more than 0 parameters 
                        newMethods.Free()
                        Return False
                    Else
                        newMethods.Add(method)
                        atLeastOneFunction = True
                    End If
                Next

                If extensionMethod Is Nothing Then
                    Dim additionalExtensionMethods As ImmutableArray(Of MethodSymbol) = methodGroup.AdditionalExtensionMethods(useSiteInfo)

                    If additionalExtensionMethods.Length > 0 Then
                        Debug.Assert(methodGroup.Methods.Length > 0)
                        ' We have at least one extension method in the group and it is not the only one method in the
                        ' group. Cannot apply default property transformation.
                        newMethods.Free()
                        Return False
                    End If
                Else
                    newMethods.Free()

                    Debug.Assert(extensionMethod IsNot Nothing)

                    ' This method must have no parameters, must have no type parameters and must not be a Sub.
                    Return methodGroup.Methods.Length = 1 AndAlso methodGroup.TypeArgumentsOpt Is Nothing AndAlso
                           extensionMethod.ParameterCount = 0 AndAlso
                           extensionMethod.Arity = 0 AndAlso
                           Not extensionMethod.IsSub AndAlso
                           methodGroup.AdditionalExtensionMethods(useSiteInfo).Length = 0
                End If

                If Not atLeastOneFunction Then
                    newMethods.Free()
                    Return False
                End If

                If shouldUpdateGroup Then
                    ' at least one sub was removed
                    If newMethods.IsEmpty Then
                        ' no functions left
                        newMethods.Free()
                        Return False
                    End If

                    ' there are some functions, update the group
                    group = methodGroup.Update(methodGroup.TypeArgumentsOpt,
                                               newMethods.ToImmutable(),
                                               Nothing,
                                               methodGroup.ResultKind,
                                               methodGroup.ReceiverOpt,
                                               methodGroup.QualificationKind)
                End If

                newMethods.Free()
                Return True

            Else
                ' check property group members
                Dim propertyGroup = DirectCast(group, BoundPropertyGroup)
                Debug.Assert(propertyGroup.Properties.Length > 0)

                For Each prop In propertyGroup.Properties
                    If (prop.ParameterCount > 0) Then
                        Return False
                    End If
                Next

                ' assuming property group was not empty
                Return True
            End If

        End Function

        Private Shared Function IsGroupOfConstructors(group As BoundMethodOrPropertyGroup) As Boolean

            If group.Kind = BoundKind.MethodGroup Then
                Dim methodGroup = DirectCast(group, BoundMethodGroup)
                Debug.Assert(methodGroup.Methods.Length > 0)
                Return methodGroup.Methods(0).MethodKind = MethodKind.Constructor
            End If

            Return False
        End Function

        Friend Function BindInvocationExpression(
            node As SyntaxNode,
            target As SyntaxNode,
            typeChar As TypeCharacter,
            group As BoundMethodOrPropertyGroup,
            boundArguments As ImmutableArray(Of BoundExpression),
            argumentNames As ImmutableArray(Of String),
            diagnostics As BindingDiagnosticBag,
            callerInfoOpt As SyntaxNode,
            Optional allowConstructorCall As Boolean = False,
            Optional suppressAbstractCallDiagnostics As Boolean = False,
            Optional isDefaultMemberAccess As Boolean = False,
            Optional representCandidateInDiagnosticsOpt As Symbol = Nothing,
            Optional forceExpandedForm As Boolean = False
        ) As BoundExpression

            Debug.Assert(group IsNot Nothing)
            Debug.Assert(allowConstructorCall OrElse Not IsGroupOfConstructors(group))
            Debug.Assert(group.ResultKind = LookupResultKind.Good OrElse group.ResultKind = LookupResultKind.Inaccessible)

            ' It is possible to get here with method group with ResultKind = LookupResultKind.Inaccessible.
            ' When this happens, it is worth trying to do overload resolution on the "bad" set
            ' to report better errors.
            Dim useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics)
            Dim results As OverloadResolution.OverloadResolutionResult = OverloadResolution.MethodOrPropertyInvocationOverloadResolution(group, boundArguments, argumentNames, Me, callerInfoOpt, useSiteInfo, forceExpandedForm:=forceExpandedForm)

            If diagnostics.Add(node, useSiteInfo) Then
                If group.ResultKind <> LookupResultKind.Inaccessible Then
                    ' Suppress additional diagnostics
                    diagnostics = BindingDiagnosticBag.Discarded
                End If
            End If

            If Not results.BestResult.HasValue Then

                If results.ResolutionIsLateBound Then
                    Debug.Assert(OptionStrict <> VisualBasic.OptionStrict.On)

                    ' Did we have extension methods among candidates?
                    If group.Kind = BoundKind.MethodGroup Then
                        Dim haveAnExtensionMethod As Boolean = False
                        Dim methodGroup = DirectCast(group, BoundMethodGroup)

                        For Each method As MethodSymbol In methodGroup.Methods
                            If method.ReducedFrom IsNot Nothing Then
                                haveAnExtensionMethod = True
                                Exit For
                            End If
                        Next

                        If Not haveAnExtensionMethod Then
                            useSiteInfo = New CompoundUseSiteInfo(Of AssemblySymbol)(useSiteInfo)
                            haveAnExtensionMethod = Not methodGroup.AdditionalExtensionMethods(useSiteInfo).IsEmpty
                            diagnostics.Add(node, useSiteInfo)
                        End If

                        If haveAnExtensionMethod Then
                            ReportDiagnostic(diagnostics, GetLocationForOverloadResolutionDiagnostic(node, group), ERRID.ERR_ExtensionMethodCannotBeLateBound)

                            Dim builder = ArrayBuilder(Of BoundExpression).GetInstance()

                            builder.Add(group)

                            If Not boundArguments.IsEmpty Then
                                builder.AddRange(boundArguments)
                            End If

                            Return New BoundBadExpression(node, LookupResultKind.OverloadResolutionFailure,
                                                          ImmutableArray(Of Symbol).Empty, builder.ToImmutableAndFree(),
                                                          ErrorTypeSymbol.UnknownResultType, hasErrors:=True)
                        End If
                    End If

                    Return BindLateBoundInvocation(node, group, isDefaultMemberAccess, boundArguments, argumentNames, diagnostics)
                End If

                ' Create and report the diagnostic.
                If results.Candidates.Length = 0 Then
                    results = OverloadResolution.MethodOrPropertyInvocationOverloadResolution(group, boundArguments, argumentNames, Me, includeEliminatedCandidates:=True, callerInfoOpt:=callerInfoOpt,
                                                                                              useSiteInfo:=CompoundUseSiteInfo(Of AssemblySymbol).Discarded, forceExpandedForm:=forceExpandedForm)
                End If

                Return ReportOverloadResolutionFailureAndProduceBoundNode(node, group, boundArguments, argumentNames, results, diagnostics,
                                                                          callerInfoOpt,
                                                                          representCandidateInDiagnosticsOpt:=representCandidateInDiagnosticsOpt)
            Else
                Return CreateBoundCallOrPropertyAccess(
                            node,
                            target,
                            typeChar,
                            group,
                            boundArguments,
                            results.BestResult.Value,
                            results.AsyncLambdaSubToFunctionMismatch,
                            diagnostics,
                            suppressAbstractCallDiagnostics)
            End If
        End Function

        Private Function CreateBoundCallOrPropertyAccess(
            node As SyntaxNode,
            target As SyntaxNode,
            typeChar As TypeCharacter,
            group As BoundMethodOrPropertyGroup,
            boundArguments As ImmutableArray(Of BoundExpression),
            bestResult As OverloadResolution.CandidateAnalysisResult,
            asyncLambdaSubToFunctionMismatch As ImmutableArray(Of BoundExpression),
            diagnostics As BindingDiagnosticBag,
            Optional suppressAbstractCallDiagnostics As Boolean = False
        ) As BoundExpression

            Dim candidate = bestResult.Candidate
            Dim methodOrProperty = candidate.UnderlyingSymbol
            Dim returnType = candidate.ReturnType

            If group.ResultKind = LookupResultKind.Inaccessible Then
                ReportDiagnostic(diagnostics, target, GetInaccessibleErrorInfo(bestResult.Candidate.UnderlyingSymbol))
            Else
                Debug.Assert(group.ResultKind = LookupResultKind.Good)
                CheckMemberTypeAccessibility(diagnostics, node, methodOrProperty)
            End If

            diagnostics.AddRange(bestResult.TypeArgumentInferenceDiagnosticsOpt)

            Dim argumentInfo As (Arguments As ImmutableArray(Of BoundExpression), DefaultArguments As BitVector) = PassArguments(node, bestResult, boundArguments, diagnostics)
            boundArguments = argumentInfo.Arguments
            Debug.Assert(Not boundArguments.IsDefault)

            Dim hasErrors As Boolean = False

            Dim receiver As BoundExpression = group.ReceiverOpt

            If group.ResultKind = LookupResultKind.Good Then
                hasErrors = CheckSharedSymbolAccess(target, methodOrProperty.IsShared, receiver, group.QualificationKind, diagnostics)  ' give diagnostics if sharedness is wrong.
            End If

            ReportDiagnosticsIfObsoleteOrNotSupported(diagnostics, methodOrProperty, node)

            hasErrors = hasErrors Or group.HasErrors

            If Not returnType.IsErrorType() Then
                VerifyTypeCharacterConsistency(node, returnType, typeChar, diagnostics)
            End If

            Dim resolvedTypeOrValueReceiver As BoundExpression = Nothing
            If receiver IsNot Nothing AndAlso Not hasErrors Then
                receiver = AdjustReceiverTypeOrValue(receiver, receiver.Syntax, methodOrProperty.IsShared, diagnostics, resolvedTypeOrValueReceiver)
            End If

            If Not suppressAbstractCallDiagnostics AndAlso receiver IsNot Nothing AndAlso (receiver.IsMyBaseReference OrElse receiver.IsMyClassReference) Then

                If methodOrProperty.IsMustOverride Then
                    '  Generate an error, but continue processing
                    ReportDiagnostic(diagnostics, group.Syntax,
                                     If(receiver.IsMyBaseReference,
                                        ERRID.ERR_MyBaseAbstractCall1,
                                        ERRID.ERR_MyClassAbstractCall1),
                                     methodOrProperty)
                End If
            End If

            If Not asyncLambdaSubToFunctionMismatch.IsEmpty Then
                For Each lambda In asyncLambdaSubToFunctionMismatch
                    Dim errorLocation As SyntaxNode = lambda.Syntax
                    Dim lambdaNode = TryCast(errorLocation, LambdaExpressionSyntax)

                    If lambdaNode IsNot Nothing Then
                        errorLocation = lambdaNode.SubOrFunctionHeader
                    End If

                    ReportDiagnostic(diagnostics, errorLocation, ERRID.WRN_AsyncSubCouldBeFunction)
                Next
            End If

            If methodOrProperty.Kind = SymbolKind.Method Then

                Dim method = DirectCast(methodOrProperty, MethodSymbol)
                Dim reducedFrom = method.ReducedFrom
                Dim constantValue As ConstantValue = Nothing

                If reducedFrom Is Nothing Then
                    If receiver IsNot Nothing AndAlso receiver.IsPropertyOrXmlPropertyAccess() Then
                        receiver = MakeRValue(receiver, diagnostics)
                    End If

                    If method.IsUserDefinedOperator() AndAlso Me.ContainingMember Is method Then
                        ReportDiagnostic(diagnostics, target, ERRID.WRN_RecursiveOperatorCall, method)
                    End If

                    ' replace call with literal if possible (Chr, ChrW, Asc, AscW)
                    constantValue = OptimizeLibraryCall(method,
                                                        boundArguments,
                                                        node,
                                                        hasErrors,
                                                        diagnostics)

                Else
                    ' We are calling an extension method, prepare the receiver to be 
                    ' passed as the first parameter.
                    receiver = UpdateReceiverForExtensionMethodOrPropertyGroup(receiver, method.ReceiverType, reducedFrom.Parameters(0), diagnostics)

                End If

                ' Remove receiver from the method group
                ' NOTE: we only remove it if we pass it to a new BoundCall node, 
                '       otherwise we keep it in the group to support semantic queries
                Dim methodGroup = DirectCast(group, BoundMethodGroup)
                Dim newReceiver As BoundExpression = If(receiver IsNot Nothing, Nothing, If(resolvedTypeOrValueReceiver, methodGroup.ReceiverOpt))
                methodGroup = methodGroup.Update(methodGroup.TypeArgumentsOpt,
                                                 methodGroup.Methods,
                                                 methodGroup.PendingExtensionMethodsOpt,
                                                 methodGroup.ResultKind,
                                                 newReceiver,
                                                 methodGroup.QualificationKind)

                Return New BoundCall(
                    node,
                    method,
                    methodGroup,
                    receiver,
                    boundArguments,
                    constantValue,
                    returnType,
                    suppressObjectClone:=False,
                    hasErrors:=hasErrors,
                    defaultArguments:=argumentInfo.DefaultArguments)

            Else
                Dim [property] = DirectCast(methodOrProperty, PropertySymbol)
                Dim reducedFrom = [property].ReducedFromDefinition

                Debug.Assert(Not boundArguments.Any(Function(a) a.Kind = BoundKind.ByRefArgumentWithCopyBack))

                If reducedFrom Is Nothing Then
                    If receiver IsNot Nothing AndAlso receiver.IsPropertyOrXmlPropertyAccess() Then
                        receiver = MakeRValue(receiver, diagnostics)
                    End If
                Else
                    receiver = UpdateReceiverForExtensionMethodOrPropertyGroup(receiver, [property].ReceiverType, reducedFrom.Parameters(0), diagnostics)
                End If

                ' Remove receiver from the property group
                ' NOTE: we only remove it if we pass it to a new BoundPropertyAccess node, 
                '       otherwise we keep it in the group to support semantic queries
                Dim propertyGroup = DirectCast(group, BoundPropertyGroup)
                Dim newReceiver As BoundExpression = If(receiver IsNot Nothing, Nothing, If(resolvedTypeOrValueReceiver, propertyGroup.ReceiverOpt))
                propertyGroup = propertyGroup.Update(propertyGroup.Properties,
                                                     propertyGroup.ResultKind,
                                                     newReceiver,
                                                     propertyGroup.QualificationKind)

                Return New BoundPropertyAccess(
                    node,
                    [property],
                    propertyGroup,
                    PropertyAccessKind.Unknown,
                    [property].IsWritable(receiver, Me, isKnownTargetOfObjectMemberInitializer:=False),
                    receiver,
                    boundArguments,
                    argumentInfo.DefaultArguments,
                    hasErrors:=hasErrors)
            End If

        End Function

        Friend Sub WarnOnRecursiveAccess(propertyAccess As BoundPropertyAccess, accessKind As PropertyAccessKind, diagnostics As BindingDiagnosticBag)
            Dim [property] As PropertySymbol = propertyAccess.PropertySymbol

            If [property].ReducedFromDefinition Is Nothing AndAlso [property].ParameterCount = 0 AndAlso
               ([property].IsShared OrElse (propertyAccess.ReceiverOpt IsNot Nothing AndAlso propertyAccess.ReceiverOpt.Kind = BoundKind.MeReference)) Then

                Dim reportRecursiveCall As Boolean = False

                If [property].GetMethod Is ContainingMember Then
                    If (accessKind And PropertyAccessKind.Get) <> 0 AndAlso (propertyAccess.AccessKind And PropertyAccessKind.Get) = 0 Then
                        reportRecursiveCall = True
                    End If
                ElseIf [property].SetMethod Is ContainingMember Then
                    If (accessKind And PropertyAccessKind.Set) <> 0 AndAlso (propertyAccess.AccessKind And PropertyAccessKind.Set) = 0 Then
                        reportRecursiveCall = True
                    End If
                End If

                If reportRecursiveCall Then
                    ReportDiagnostic(diagnostics, propertyAccess.Syntax, ERRID.WRN_RecursivePropertyCall, [property])
                End If
            End If
        End Sub

        Friend Sub WarnOnRecursiveAccess(node As BoundExpression, accessKind As PropertyAccessKind, diagnostics As BindingDiagnosticBag)
            Select Case node.Kind
                Case BoundKind.XmlMemberAccess
                    ' Nothing to do 

                Case BoundKind.PropertyAccess
                    WarnOnRecursiveAccess(DirectCast(node, BoundPropertyAccess), accessKind, diagnostics)

                Case Else
                    Throw ExceptionUtilities.UnexpectedValue(node.Kind)

            End Select
        End Sub

        Private Function UpdateReceiverForExtensionMethodOrPropertyGroup(
            receiver As BoundExpression,
            targetType As TypeSymbol,
            thisParameterDefinition As ParameterSymbol,
            diagnostics As BindingDiagnosticBag
        ) As BoundExpression

            If receiver IsNot Nothing AndAlso
                receiver.IsValue AndAlso
                Not targetType.IsErrorType() AndAlso
                Not receiver.Type.IsErrorType() Then

                Dim oldReceiver As BoundExpression = receiver
                Dim useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics)
                receiver = PassArgument(receiver,
                                        Conversions.ClassifyConversion(receiver, targetType, Me, useSiteInfo),
                                        False,
                                        Conversions.ClassifyConversion(targetType, receiver.Type, useSiteInfo),
                                        targetType,
                                        thisParameterDefinition,
                                        diagnostics)

                diagnostics.Add(receiver, useSiteInfo)

                If oldReceiver.WasCompilerGenerated AndAlso receiver IsNot oldReceiver Then
                    Select Case oldReceiver.Kind
                        Case BoundKind.MeReference,
                             BoundKind.WithLValueExpressionPlaceholder,
                             BoundKind.WithRValueExpressionPlaceholder
                            receiver.SetWasCompilerGenerated()
                    End Select
                End If
            End If

            Return receiver
        End Function

        Private Function IsWellKnownTypeMember(memberId As WellKnownMember, method As MethodSymbol) As Boolean
            Return Compilation.GetWellKnownTypeMember(memberId) Is method
        End Function

        ''' <summary>
        ''' Optimizes some runtime library calls through replacing them with a literal if possible.
        ''' VB Spec 11.2 defines the following runtime functions as being constant:
        '''  - Microsoft.VisualBasic.Strings.ChrW
        '''  - Microsoft.VisualBasic.Strings.Chr, if the constant value is between 0 and 128
        '''  - Microsoft.VisualBasic.Strings.AscW, if the constant string is not empty
        '''  - Microsoft.VisualBasic.Strings.Asc, if the constant string is not empty
        ''' </summary>
        ''' <param name="method">The method.</param>
        ''' <param name="arguments">The arguments of the method call.</param>
        ''' <param name="syntax">The syntax node for report errors.</param>
        ''' <param name="diagnostics">The diagnostics.</param>
        ''' <param name="hasErrors">Set to true if there are conversion errors (e.g. Asc("")). Otherwise it's not written to.</param>
        ''' <returns>The constant value that replaces this node, or nothing.</returns>
        Private Function OptimizeLibraryCall(
            method As MethodSymbol,
            arguments As ImmutableArray(Of BoundExpression),
            syntax As SyntaxNode,
            ByRef hasErrors As Boolean,
            diagnostics As BindingDiagnosticBag
        ) As ConstantValue

            ' cheapest way to filter out methods that do not match
            If arguments.Length = 1 AndAlso arguments(0).IsConstant AndAlso Not arguments(0).ConstantValueOpt.IsBad Then

                ' only continue checking if containing type is Microsoft.VisualBasic.Strings
                If Compilation.GetWellKnownType(WellKnownType.Microsoft_VisualBasic_Strings) IsNot method.ContainingType Then
                    Return Nothing
                End If

                ' AscW(char) / AscW(String)
                ' all values can be optimized as a literal, except an empty string that produces a diagnostic
                If IsWellKnownTypeMember(WellKnownMember.Microsoft_VisualBasic_Strings__AscWCharInt32, method) OrElse
                    IsWellKnownTypeMember(WellKnownMember.Microsoft_VisualBasic_Strings__AscWStringInt32, method) Then

                    Dim argumentConstantValue = arguments(0).ConstantValueOpt
                    Dim argumentValue As String
                    If argumentConstantValue.IsNull Then
                        argumentValue = String.Empty
                    ElseIf argumentConstantValue.IsChar Then
                        argumentValue = argumentConstantValue.CharValue
                    Else
                        Debug.Assert(argumentConstantValue.IsString())
                        argumentValue = argumentConstantValue.StringValue
                    End If

                    If argumentValue.IsEmpty() Then
                        ReportDiagnostic(diagnostics, syntax, ERRID.ERR_CannotConvertValue2, argumentValue, method.ReturnType)

                        hasErrors = True
                        Return Nothing
                    End If

                    Return ConstantValue.Create(AscW(argumentValue))
                End If

                ' ChrW
                ' for -32768 < value or value > 65535 we show a diagnostic
                If IsWellKnownTypeMember(WellKnownMember.Microsoft_VisualBasic_Strings__ChrWInt32Char, method) Then
                    Dim argumentValue = arguments(0).ConstantValueOpt.Int32Value
                    If argumentValue < -32768 OrElse argumentValue > 65535 Then
                        ReportDiagnostic(diagnostics, syntax, ERRID.ERR_CannotConvertValue2, argumentValue, method.ReturnType)

                        hasErrors = True
                        Return Nothing
                    End If

                    Return ConstantValue.Create(ChrW(argumentValue))
                End If

                ' Asc(Char) / Asc(String)
                ' all values from 0 to 127 can be optimized to a literal.
                If IsWellKnownTypeMember(WellKnownMember.Microsoft_VisualBasic_Strings__AscCharInt32, method) OrElse
                    IsWellKnownTypeMember(WellKnownMember.Microsoft_VisualBasic_Strings__AscStringInt32, method) Then

                    Dim constantValue = arguments(0).ConstantValueOpt
                    Dim argumentValue As String
                    If constantValue.IsNull Then
                        argumentValue = String.Empty
                    ElseIf constantValue.IsChar Then
                        argumentValue = constantValue.CharValue
                    Else
                        Debug.Assert(constantValue.IsString())
                        argumentValue = constantValue.StringValue
                    End If

                    If argumentValue.IsEmpty() Then
                        ReportDiagnostic(diagnostics, syntax, ERRID.ERR_CannotConvertValue2, argumentValue, method.ReturnType)

                        hasErrors = True
                        Return Nothing
                    End If

                    ' we are only folding 7bit ASCII chars, so it's ok to use AscW here, although this is the Asc folding.
                    Dim charValue = AscW(argumentValue)
                    If charValue < 128 Then
                        Return ConstantValue.Create(charValue)
                    End If

                    Return Nothing
                End If

                ' Chr
                ' values from 0 to 127 can be optimized as a literal
                ' for -32768 < value or value > 65535 we show a diagnostic
                If IsWellKnownTypeMember(WellKnownMember.Microsoft_VisualBasic_Strings__ChrInt32Char, method) Then
                    Dim argumentValue = arguments(0).ConstantValueOpt.Int32Value
                    If argumentValue >= 0 AndAlso argumentValue < 128 Then
                        Return ConstantValue.Create(ChrW(argumentValue))
                    ElseIf argumentValue < -32768 OrElse argumentValue > 65535 Then
                        ReportDiagnostic(diagnostics, syntax, ERRID.ERR_CannotConvertValue2, argumentValue, method.ReturnType)

                        hasErrors = True
                        Return Nothing
                    End If
                End If
            End If

            Return Nothing
        End Function

        Private Function ReportOverloadResolutionFailureAndProduceBoundNode(
            node As SyntaxNode,
            group As BoundMethodOrPropertyGroup,
            boundArguments As ImmutableArray(Of BoundExpression),
            argumentNames As ImmutableArray(Of String),
            <[In]> ByRef results As OverloadResolution.OverloadResolutionResult,
            diagnostics As BindingDiagnosticBag,
            callerInfoOpt As SyntaxNode,
            Optional overrideCommonReturnType As TypeSymbol = Nothing,
            Optional queryMode As Boolean = False,
            Optional boundTypeExpression As BoundTypeExpression = Nothing,
            Optional representCandidateInDiagnosticsOpt As Symbol = Nothing,
            Optional diagnosticLocationOpt As Location = Nothing
        ) As BoundExpression
            Return ReportOverloadResolutionFailureAndProduceBoundNode(
                        node,
                        group.ResultKind,
                        boundArguments,
                        argumentNames,
                        results,
                        diagnostics,
                        callerInfoOpt,
                        group,
                        overrideCommonReturnType,
                        queryMode,
                        boundTypeExpression,
                        representCandidateInDiagnosticsOpt,
                        diagnosticLocationOpt)
        End Function

        Private Function ReportOverloadResolutionFailureAndProduceBoundNode(
            node As SyntaxNode,
            lookupResult As LookupResultKind,
            boundArguments As ImmutableArray(Of BoundExpression),
            argumentNames As ImmutableArray(Of String),
            <[In]> ByRef results As OverloadResolution.OverloadResolutionResult,
            diagnostics As BindingDiagnosticBag,
            callerInfoOpt As SyntaxNode,
            Optional groupOpt As BoundMethodOrPropertyGroup = Nothing,
            Optional overrideCommonReturnType As TypeSymbol = Nothing,
            Optional queryMode As Boolean = False,
            Optional boundTypeExpression As BoundTypeExpression = Nothing,
            Optional representCandidateInDiagnosticsOpt As Symbol = Nothing,
            Optional diagnosticLocationOpt As Location = Nothing
        ) As BoundExpression

            Dim bestCandidates = ArrayBuilder(Of OverloadResolution.CandidateAnalysisResult).GetInstance()
            Dim bestSymbols = ImmutableArray(Of Symbol).Empty

            Dim commonReturnType As TypeSymbol = GetSetOfTheBestCandidates(results, bestCandidates, bestSymbols)

            If overrideCommonReturnType IsNot Nothing Then
                commonReturnType = overrideCommonReturnType
            End If

            Dim result As BoundExpression = ReportOverloadResolutionFailureAndProduceBoundNode(
                node,
                lookupResult,
                bestCandidates,
                bestSymbols,
                commonReturnType,
                boundArguments,
                argumentNames,
                diagnostics,
                callerInfoOpt,
                groupOpt,
                Nothing,
                queryMode,
                boundTypeExpression,
                representCandidateInDiagnosticsOpt,
                diagnosticLocationOpt)

            bestCandidates.Free()

            Return result
        End Function

        Private Function ReportOverloadResolutionFailureAndProduceBoundNode(
            node As SyntaxNode,
            group As BoundMethodOrPropertyGroup,
            bestCandidates As ArrayBuilder(Of OverloadResolution.CandidateAnalysisResult),
            bestSymbols As ImmutableArray(Of Symbol),
            commonReturnType As TypeSymbol,
            boundArguments As ImmutableArray(Of BoundExpression),
            argumentNames As ImmutableArray(Of String),
            diagnostics As BindingDiagnosticBag,
            callerInfoOpt As SyntaxNode,
            Optional delegateSymbol As Symbol = Nothing,
            Optional queryMode As Boolean = False,
            Optional boundTypeExpression As BoundTypeExpression = Nothing,
            Optional representCandidateInDiagnosticsOpt As Symbol = Nothing
        ) As BoundExpression
            Return ReportOverloadResolutionFailureAndProduceBoundNode(
                       node,
                       group.ResultKind,
                       bestCandidates,
                       bestSymbols,
                       commonReturnType,
                       boundArguments,
                       argumentNames,
                       diagnostics,
                       callerInfoOpt,
                       group,
                       delegateSymbol,
                       queryMode,
                       boundTypeExpression,
                       representCandidateInDiagnosticsOpt)
        End Function

        Public Shared Function GetLocationForOverloadResolutionDiagnostic(node As SyntaxNode, Optional groupOpt As BoundMethodOrPropertyGroup = Nothing) As Location
            Dim result As SyntaxNode

            If groupOpt IsNot Nothing Then
                If node.SyntaxTree Is groupOpt.Syntax.SyntaxTree AndAlso node.Span.Contains(groupOpt.Syntax.Span) Then
                    result = groupOpt.Syntax

                    If result Is node AndAlso (groupOpt.ReceiverOpt Is Nothing OrElse groupOpt.ReceiverOpt.Syntax Is result) Then
                        Return result.GetLocation()
                    End If
                Else
                    Return node.GetLocation()
                End If

            ElseIf node.IsKind(SyntaxKind.InvocationExpression) Then
                result = If(DirectCast(node, InvocationExpressionSyntax).Expression, node)
            Else
                Return node.GetLocation()
            End If

            Select Case result.Kind
                Case SyntaxKind.QualifiedName
                    Return DirectCast(result, QualifiedNameSyntax).Right.GetLocation()

                Case SyntaxKind.SimpleMemberAccessExpression
                    If result.Parent IsNot Nothing AndAlso result.Parent.IsKind(SyntaxKind.AddressOfExpression) Then
                        Return result.GetLocation()
                    End If

                    Return DirectCast(result, MemberAccessExpressionSyntax).Name.GetLocation()

                Case SyntaxKind.XmlElementAccessExpression,
                     SyntaxKind.XmlDescendantAccessExpression,
                     SyntaxKind.XmlAttributeAccessExpression
                    Return DirectCast(result, XmlMemberAccessExpressionSyntax).Name.GetLocation()

                Case SyntaxKind.HandlesClauseItem
                    Return DirectCast(result, HandlesClauseItemSyntax).EventMember.GetLocation()
            End Select

            Return result.GetLocation()
        End Function

        Private Function ReportOverloadResolutionFailureAndProduceBoundNode(
            node As SyntaxNode,
            lookupResult As LookupResultKind,
            bestCandidates As ArrayBuilder(Of OverloadResolution.CandidateAnalysisResult),
            bestSymbols As ImmutableArray(Of Symbol),
            commonReturnType As TypeSymbol,
            boundArguments As ImmutableArray(Of BoundExpression),
            argumentNames As ImmutableArray(Of String),
            diagnostics As BindingDiagnosticBag,
            callerInfoOpt As SyntaxNode,
            Optional groupOpt As BoundMethodOrPropertyGroup = Nothing,
            Optional delegateSymbol As Symbol = Nothing,
            Optional queryMode As Boolean = False,
            Optional boundTypeExpression As BoundTypeExpression = Nothing,
            Optional representCandidateInDiagnosticsOpt As Symbol = Nothing,
            Optional diagnosticLocationOpt As Location = Nothing
        ) As BoundExpression

            Debug.Assert(commonReturnType IsNot Nothing AndAlso bestSymbols.Length > 0 AndAlso bestCandidates.Count >= bestSymbols.Length)
            Debug.Assert(groupOpt Is Nothing OrElse lookupResult = groupOpt.ResultKind)

            Dim state = OverloadResolution.CandidateAnalysisResultState.Count

            If bestCandidates.Count > 0 Then
                state = bestCandidates(0).State
            End If

            If boundArguments.IsDefault Then
                boundArguments = ImmutableArray(Of BoundExpression).Empty
            End If

            Dim singleCandidateAnalysisResult As OverloadResolution.CandidateAnalysisResult = Nothing
            Dim singleCandidate As OverloadResolution.Candidate = Nothing
            Dim allowUnexpandedParamArrayForm As Boolean = False
            Dim allowExpandedParamArrayForm As Boolean = False

            ' Figure out if we should report single candidate errors
            If bestSymbols.Length = 1 AndAlso bestCandidates.Count < 3 Then
                singleCandidateAnalysisResult = bestCandidates(0)
                singleCandidate = singleCandidateAnalysisResult.Candidate
                allowExpandedParamArrayForm = singleCandidateAnalysisResult.IsExpandedParamArrayForm
                allowUnexpandedParamArrayForm = Not allowExpandedParamArrayForm

                If bestCandidates.Count > 1 Then
                    If bestCandidates(1).IsExpandedParamArrayForm Then
                        allowExpandedParamArrayForm = True
                    Else
                        allowUnexpandedParamArrayForm = True
                    End If
                End If
            End If

            If lookupResult = LookupResultKind.Inaccessible Then
                If singleCandidate IsNot Nothing Then
                    ReportDiagnostic(diagnostics, If(groupOpt IsNot Nothing, groupOpt.Syntax, node), GetInaccessibleErrorInfo(singleCandidate.UnderlyingSymbol))
                Else
                    If Not queryMode Then
                        ReportDiagnostic(diagnostics, If(groupOpt IsNot Nothing, groupOpt.Syntax, node), ERRID.ERR_NoViableOverloadCandidates1, bestSymbols(0).Name)
                    End If

                    ' Do not report more errors.
                    GoTo ProduceBoundNode
                End If
            Else
                Debug.Assert(lookupResult = LookupResultKind.Good)
            End If

            If diagnosticLocationOpt Is Nothing Then
                diagnosticLocationOpt = GetLocationForOverloadResolutionDiagnostic(node, groupOpt)
            End If

            ' Report diagnostic according to the state of candidates
            Select Case state

                Case VisualBasic.OverloadResolution.CandidateAnalysisResultState.HasUseSiteError, OverloadResolution.CandidateAnalysisResultState.HasUnsupportedMetadata

                    If singleCandidate IsNot Nothing Then
                        ReportOverloadResolutionFailureForASingleCandidate(node, diagnosticLocationOpt, lookupResult, singleCandidateAnalysisResult,
                                                                 boundArguments, argumentNames,
                                                                 allowUnexpandedParamArrayForm,
                                                                 allowExpandedParamArrayForm,
                                                                 True,
                                                                 False,
                                                                 diagnostics,
                                                                 delegateSymbol:=delegateSymbol,
                                                                 queryMode:=queryMode,
                                                                 callerInfoOpt:=callerInfoOpt,
                                                                 representCandidateInDiagnosticsOpt:=representCandidateInDiagnosticsOpt)

                    Else
                        ReportOverloadResolutionFailureForASetOfCandidates(node, diagnosticLocationOpt, lookupResult,
                                                        ERRID.ERR_BadOverloadCandidates2,
                                                        bestCandidates,
                                                        boundArguments,
                                                        argumentNames,
                                                        diagnostics,
                                                        delegateSymbol:=delegateSymbol,
                                                        queryMode:=queryMode,
                                                        callerInfoOpt:=callerInfoOpt)
                    End If

                Case VisualBasic.OverloadResolution.CandidateAnalysisResultState.Ambiguous
                    Dim candidate As Symbol = bestSymbols(0).OriginalDefinition
                    Dim container As Symbol = candidate.ContainingSymbol
                    ReportDiagnostic(diagnostics, diagnosticLocationOpt, ERRID.ERR_MetadataMembersAmbiguous3, candidate.Name, container.GetKindText(), container)

                Case OverloadResolution.CandidateAnalysisResultState.BadGenericArity
                    Debug.Assert(groupOpt IsNot Nothing AndAlso groupOpt.Kind = BoundKind.MethodGroup)
                    Dim mg = DirectCast(groupOpt, BoundMethodGroup)

                    If singleCandidate IsNot Nothing Then
                        Dim typeArguments = If(mg.TypeArgumentsOpt IsNot Nothing, mg.TypeArgumentsOpt.Arguments, ImmutableArray(Of TypeSymbol).Empty)

                        If typeArguments.IsDefault Then
                            typeArguments = ImmutableArray(Of TypeSymbol).Empty
                        End If

                        Dim singleSymbol As Symbol = singleCandidate.UnderlyingSymbol
                        Dim isExtension As Boolean = singleCandidate.IsExtensionMethod

                        If singleCandidate.Arity < typeArguments.Length Then
                            If isExtension Then
                                ReportDiagnostic(diagnostics, mg.TypeArgumentsOpt.Syntax,
                                                 If(singleCandidate.Arity = 0, ERRID.ERR_TypeOrMemberNotGeneric2, ERRID.ERR_TooManyGenericArguments2),
                                                 singleSymbol, singleSymbol.ContainingType)
                            Else
                                ReportDiagnostic(diagnostics, mg.TypeArgumentsOpt.Syntax,
                                                 If(singleCandidate.Arity = 0, ERRID.ERR_TypeOrMemberNotGeneric1, ERRID.ERR_TooManyGenericArguments1),
                                                 singleSymbol)
                            End If
                        Else
                            Debug.Assert(singleCandidate.Arity > typeArguments.Length)

                            If isExtension Then
                                ReportDiagnostic(diagnostics, mg.TypeArgumentsOpt.Syntax,
                                                 ERRID.ERR_TooFewGenericArguments2,
                                                 singleSymbol, singleSymbol.ContainingType)
                            Else
                                ReportDiagnostic(diagnostics, mg.TypeArgumentsOpt.Syntax,
                                                 ERRID.ERR_TooFewGenericArguments1, singleSymbol)
                            End If
                        End If
                    Else
                        ReportDiagnostic(diagnostics, diagnosticLocationOpt, ERRID.ERR_NoTypeArgumentCountOverloadCand1, CustomSymbolDisplayFormatter.ShortErrorName(bestSymbols(0)))
                    End If

                Case OverloadResolution.CandidateAnalysisResultState.ArgumentCountMismatch

                    If node.Kind = SyntaxKind.IdentifierName AndAlso
                        node.Parent IsNot Nothing AndAlso
                        node.Parent.Kind = SyntaxKind.NamedFieldInitializer AndAlso
                        groupOpt IsNot Nothing AndAlso
                        groupOpt.Kind = BoundKind.PropertyGroup Then

                        ' report special diagnostics for a failed overload resolution because all available properties
                        ' require arguments in case this method was called while binding a object member initializer.
                        ReportDiagnostic(diagnostics,
                                         diagnosticLocationOpt,
                                         If(singleCandidate IsNot Nothing,
                                            ERRID.ERR_ParameterizedPropertyInAggrInit1,
                                            ERRID.ERR_NoZeroCountArgumentInitCandidates1),
                                         CustomSymbolDisplayFormatter.ShortErrorName(bestSymbols(0)))
                    Else
                        If singleCandidate IsNot Nothing AndAlso
                           (Not queryMode OrElse singleCandidate.ParameterCount <= boundArguments.Length) Then
                            ReportOverloadResolutionFailureForASingleCandidate(node, diagnosticLocationOpt, lookupResult, singleCandidateAnalysisResult,
                                                                         boundArguments, argumentNames,
                                                                         allowUnexpandedParamArrayForm,
                                                                         allowExpandedParamArrayForm,
                                                                         True,
                                                                         False,
                                                                         diagnostics,
                                                                         delegateSymbol:=delegateSymbol,
                                                                         queryMode:=queryMode,
                                                                         callerInfoOpt:=callerInfoOpt,
                                                                         representCandidateInDiagnosticsOpt:=representCandidateInDiagnosticsOpt)

                        Else
                            ReportDiagnostic(diagnostics, diagnosticLocationOpt, ERRID.ERR_NoArgumentCountOverloadCandidates1, CustomSymbolDisplayFormatter.ShortErrorName(bestSymbols(0)))
                        End If
                    End If

                Case OverloadResolution.CandidateAnalysisResultState.ArgumentMismatch,
                     OverloadResolution.CandidateAnalysisResultState.GenericConstraintsViolated

                    Dim haveBadArgument As Boolean = False

                    For i As Integer = 0 To boundArguments.Length - 1 Step 1
                        Dim type = boundArguments(i).Type

                        If boundArguments(i).HasErrors OrElse (type IsNot Nothing AndAlso type.IsErrorType()) Then
                            haveBadArgument = True
                            Exit For
                        End If
                    Next

                    If Not haveBadArgument Then
                        If singleCandidate IsNot Nothing Then
                            ReportOverloadResolutionFailureForASingleCandidate(node, diagnosticLocationOpt, lookupResult, singleCandidateAnalysisResult,
                                                                     boundArguments, argumentNames,
                                                                     allowUnexpandedParamArrayForm,
                                                                     allowExpandedParamArrayForm,
                                                                     True,
                                                                     False,
                                                                     diagnostics,
                                                                     delegateSymbol:=delegateSymbol,
                                                                     queryMode:=queryMode,
                                                                     callerInfoOpt:=callerInfoOpt,
                                                                     representCandidateInDiagnosticsOpt:=representCandidateInDiagnosticsOpt)

                        Else
                            ReportOverloadResolutionFailureForASetOfCandidates(node, diagnosticLocationOpt, lookupResult,
                                                            If(delegateSymbol Is Nothing,
                                                               ERRID.ERR_NoCallableOverloadCandidates2,
                                                               ERRID.ERR_DelegateBindingFailure3),
                                                            bestCandidates,
                                                            boundArguments,
                                                            argumentNames,
                                                            diagnostics,
                                                            delegateSymbol:=delegateSymbol,
                                                            queryMode:=queryMode,
                                                            callerInfoOpt:=callerInfoOpt)
                        End If
                    End If

                Case OverloadResolution.CandidateAnalysisResultState.TypeInferenceFailed

                    If singleCandidate IsNot Nothing Then
                        ReportOverloadResolutionFailureForASingleCandidate(node, diagnosticLocationOpt, lookupResult, singleCandidateAnalysisResult,
                                                                 boundArguments, argumentNames,
                                                                 allowUnexpandedParamArrayForm,
                                                                 allowExpandedParamArrayForm,
                                                                 True,
                                                                 False,
                                                                 diagnostics,
                                                                 delegateSymbol:=delegateSymbol,
                                                                 queryMode:=queryMode,
                                                                 callerInfoOpt:=callerInfoOpt,
                                                                 representCandidateInDiagnosticsOpt:=representCandidateInDiagnosticsOpt)

                    Else
                        ReportOverloadResolutionFailureForASetOfCandidates(node, diagnosticLocationOpt, lookupResult,
                                                        ERRID.ERR_NoCallableOverloadCandidates2,
                                                        bestCandidates,
                                                        boundArguments,
                                                        argumentNames,
                                                        diagnostics,
                                                        delegateSymbol:=delegateSymbol,
                                                        queryMode:=queryMode,
                                                        callerInfoOpt:=callerInfoOpt)
                    End If

                Case OverloadResolution.CandidateAnalysisResultState.Applicable

                    ' it is only possible to get overloading failure with a single candidate
                    ' if we have a paramarray with equally specific virtual signatures
                    Debug.Assert(singleCandidate Is Nothing OrElse
                                 singleCandidate.ParameterCount <> 0 AndAlso
                                 singleCandidate.Parameters(singleCandidate.ParameterCount - 1).IsParamArray)

                    If bestCandidates(0).RequiresNarrowingConversion Then
                        ReportOverloadResolutionFailureForASetOfCandidates(node, diagnosticLocationOpt, lookupResult,
                                                        If(delegateSymbol Is Nothing,
                                                            ERRID.ERR_NoNonNarrowingOverloadCandidates2,
                                                            ERRID.ERR_DelegateBindingFailure3),
                                                        bestCandidates,
                                                        boundArguments,
                                                        argumentNames,
                                                        diagnostics,
                                                        delegateSymbol:=delegateSymbol,
                                                        queryMode:=queryMode,
                                                        callerInfoOpt:=callerInfoOpt)
                    Else
                        ReportUnspecificProcedures(diagnosticLocationOpt, bestSymbols, diagnostics, (delegateSymbol IsNot Nothing))
                    End If

                Case Else
                    ' Unexpected
                    Throw ExceptionUtilities.UnexpectedValue(state)
            End Select

ProduceBoundNode:
            Dim childBoundNodes As ImmutableArray(Of BoundExpression)

            If boundArguments.IsEmpty AndAlso boundTypeExpression Is Nothing Then
                If groupOpt Is Nothing Then
                    childBoundNodes = ImmutableArray(Of BoundExpression).Empty
                Else
                    childBoundNodes = ImmutableArray.Create(Of BoundExpression)(groupOpt)
                End If
            Else
                Dim builder = ArrayBuilder(Of BoundExpression).GetInstance()

                If groupOpt IsNot Nothing Then
                    builder.Add(groupOpt)
                End If

                If Not boundArguments.IsEmpty Then
                    builder.AddRange(boundArguments)
                End If

                If boundTypeExpression IsNot Nothing Then
                    builder.Add(boundTypeExpression)
                End If

                childBoundNodes = builder.ToImmutableAndFree()
            End If

            Dim resultKind = LookupResultKind.OverloadResolutionFailure
            If lookupResult < resultKind Then
                resultKind = lookupResult
            End If

            Return New BoundBadExpression(node, resultKind, bestSymbols, childBoundNodes, commonReturnType, hasErrors:=True)
        End Function

        ''' <summary>
        '''Figure out the set of best candidates in the following preference order:
        '''  1) Applicable
        '''  2) ArgumentMismatch, GenericConstraintsViolated
        '''  3) TypeInferenceFailed
        '''  4) ArgumentCountMismatch
        '''  5) BadGenericArity
        '''  6) Ambiguous
        '''  7) HasUseSiteError
        '''  8) HasUnsupportedMetadata
        ''' 
        ''' Also return the set of unique symbols behind the set.
        ''' 
        ''' Returns type symbol for the common type, if any.
        ''' Otherwise returns ErrorTypeSymbol.UnknownResultType.
        ''' </summary>
        Private Shared Function GetSetOfTheBestCandidates(
            ByRef results As OverloadResolution.OverloadResolutionResult,
            bestCandidates As ArrayBuilder(Of OverloadResolution.CandidateAnalysisResult),
            ByRef bestSymbols As ImmutableArray(Of Symbol)
        ) As TypeSymbol
            Const Applicable = OverloadResolution.CandidateAnalysisResultState.Applicable
            Const ArgumentMismatch = OverloadResolution.CandidateAnalysisResultState.ArgumentMismatch
            Const GenericConstraintsViolated = OverloadResolution.CandidateAnalysisResultState.GenericConstraintsViolated
            Const TypeInferenceFailed = OverloadResolution.CandidateAnalysisResultState.TypeInferenceFailed
            Const ArgumentCountMismatch = OverloadResolution.CandidateAnalysisResultState.ArgumentCountMismatch
            Const BadGenericArity = OverloadResolution.CandidateAnalysisResultState.BadGenericArity
            Const Ambiguous = OverloadResolution.CandidateAnalysisResultState.Ambiguous
            Const HasUseSiteError = OverloadResolution.CandidateAnalysisResultState.HasUseSiteError
            Const HasUnsupportedMetadata = OverloadResolution.CandidateAnalysisResultState.HasUnsupportedMetadata

            Dim preference(OverloadResolution.CandidateAnalysisResultState.Count - 1) As Integer

            preference(Applicable) = 1
            preference(ArgumentMismatch) = 2
            preference(GenericConstraintsViolated) = 2
            preference(TypeInferenceFailed) = 3
            preference(ArgumentCountMismatch) = 4
            preference(BadGenericArity) = 5
            preference(Ambiguous) = 6
            preference(HasUseSiteError) = 7
            preference(HasUnsupportedMetadata) = 8

            For Each candidate In results.Candidates
                Dim prefNew = preference(candidate.State)

                If prefNew <> 0 Then
                    If bestCandidates.Count = 0 Then
                        bestCandidates.Add(candidate)
                    Else
                        Dim prefOld = preference(bestCandidates(0).State)

                        If prefNew = prefOld Then
                            bestCandidates.Add(candidate)

                        ElseIf prefNew < prefOld Then
                            bestCandidates.Clear()
                            bestCandidates.Add(candidate)
                        End If
                    End If
                End If
            Next

            ' Collect unique best symbols.
            Dim bestSymbolsBuilder = ArrayBuilder(Of Symbol).GetInstance(bestCandidates.Count)
            Dim commonReturnType As TypeSymbol = Nothing

            If bestCandidates.Count = 1 Then
                ' For multiple candidates we never pick common type that refers to method's type parameter
                ' because each method has distinct type parameters. For single candidate case we need to
                ' ensure this explicitly. 
                Dim underlyingSymbol As Symbol = bestCandidates(0).Candidate.UnderlyingSymbol
                bestSymbolsBuilder.Add(underlyingSymbol)
                commonReturnType = bestCandidates(0).Candidate.ReturnType

                If underlyingSymbol.Kind = SymbolKind.Method Then
                    Dim method = DirectCast(underlyingSymbol, MethodSymbol)

                    If method.IsGenericMethod AndAlso commonReturnType.ReferencesMethodsTypeParameter(method) Then
                        Select Case CInt(bestCandidates(0).State)
                            Case TypeInferenceFailed, HasUseSiteError, HasUnsupportedMetadata, BadGenericArity, ArgumentCountMismatch
                                commonReturnType = Nothing
                        End Select
                    End If
                End If
            Else
                For i As Integer = 0 To bestCandidates.Count - 1 Step 1
                    If i = 0 OrElse Not bestSymbolsBuilder(bestSymbolsBuilder.Count - 1).Equals(bestCandidates(i).Candidate.UnderlyingSymbol) Then
                        bestSymbolsBuilder.Add(bestCandidates(i).Candidate.UnderlyingSymbol)

                        Dim returnType = bestCandidates(i).Candidate.ReturnType

                        If commonReturnType Is Nothing Then
                            commonReturnType = returnType

                        ElseIf commonReturnType IsNot ErrorTypeSymbol.UnknownResultType AndAlso
                            Not commonReturnType.IsSameTypeIgnoringAll(returnType) Then
                            commonReturnType = ErrorTypeSymbol.UnknownResultType
                        End If
                    End If
                Next
            End If

            bestSymbols = bestSymbolsBuilder.ToImmutableAndFree()

            Return If(commonReturnType, ErrorTypeSymbol.UnknownResultType)
        End Function

        Private Shared Sub ReportUnspecificProcedures(
            diagnosticLocation As Location,
            bestSymbols As ImmutableArray(Of Symbol),
            diagnostics As BindingDiagnosticBag,
            isDelegateContext As Boolean
        )
            Dim diagnosticInfos = ArrayBuilder(Of DiagnosticInfo).GetInstance(bestSymbols.Length)
            Dim notMostSpecificMessage = ErrorFactory.ErrorInfo(ERRID.ERR_NotMostSpecificOverload)
            Dim withContainingTypeInDiagnostics As Boolean = False

            If Not bestSymbols(0).IsReducedExtensionMethod Then
                Dim container As NamedTypeSymbol = bestSymbols(0).ContainingType

                For i As Integer = 1 To bestSymbols.Length - 1 Step 1
                    If Not TypeSymbol.Equals(bestSymbols(i).ContainingType, container, TypeCompareKind.ConsiderEverything) Then
                        withContainingTypeInDiagnostics = True
                    End If
                Next
            End If

            For i As Integer = 0 To bestSymbols.Length - 1 Step 1

                ' in delegate context we just output for each candidates
                ' BC30794: No accessible 'goo' is most specific: 
                '     Public Sub goo(p As Integer)
                '     Public Sub goo(p As Integer)
                '
                ' in other contexts we give more information, e.g.
                ' BC30794: No accessible 'goo' is most specific: 
                '     Public Sub goo(p As Integer): <reason>
                '     Public Sub goo(p As Integer): <reason>
                Dim bestSymbol As Symbol = bestSymbols(i)
                Dim bestSymbolIsExtension As Boolean = bestSymbol.IsReducedExtensionMethod

                If isDelegateContext Then
                    If bestSymbolIsExtension Then
                        diagnosticInfos.Add(ErrorFactory.ErrorInfo(ERRID.ERR_ExtensionMethodOverloadCandidate2, bestSymbol, bestSymbol.ContainingType))
                    ElseIf withContainingTypeInDiagnostics Then
                        diagnosticInfos.Add(ErrorFactory.ErrorInfo(ERRID.ERR_OverloadCandidate1, CustomSymbolDisplayFormatter.WithContainingType(bestSymbol)))
                    Else
                        diagnosticInfos.Add(ErrorFactory.ErrorInfo(ERRID.ERR_OverloadCandidate1, bestSymbol))
                    End If
                Else
                    If bestSymbolIsExtension Then
                        diagnosticInfos.Add(ErrorFactory.ErrorInfo(ERRID.ERR_ExtensionMethodOverloadCandidate3, bestSymbol, bestSymbol.ContainingType, notMostSpecificMessage))
                    ElseIf withContainingTypeInDiagnostics Then
                        diagnosticInfos.Add(ErrorFactory.ErrorInfo(ERRID.ERR_OverloadCandidate2, CustomSymbolDisplayFormatter.WithContainingType(bestSymbol), notMostSpecificMessage))
                    Else
                        diagnosticInfos.Add(ErrorFactory.ErrorInfo(ERRID.ERR_OverloadCandidate2, bestSymbol, notMostSpecificMessage))
                    End If
                End If
            Next

            ReportDiagnostic(diagnostics, diagnosticLocation,
                             ErrorFactory.ErrorInfo(If(isDelegateContext, ERRID.ERR_AmbiguousDelegateBinding2, ERRID.ERR_NoMostSpecificOverload2),
                                                    CustomSymbolDisplayFormatter.ShortErrorName(bestSymbols(0)),
                                                    New CompoundDiagnosticInfo(diagnosticInfos.ToArrayAndFree())
                                                    ))
        End Sub

        Private Sub ReportOverloadResolutionFailureForASetOfCandidates(
            node As SyntaxNode,
            diagnosticLocation As Location,
            lookupResult As LookupResultKind,
            errorNo As ERRID,
            candidates As ArrayBuilder(Of OverloadResolution.CandidateAnalysisResult),
            arguments As ImmutableArray(Of BoundExpression),
            argumentNames As ImmutableArray(Of String),
            diagnostics As BindingDiagnosticBag,
            delegateSymbol As Symbol,
            queryMode As Boolean,
            callerInfoOpt As SyntaxNode
        )
            Dim diagnosticPerSymbol = ArrayBuilder(Of KeyValuePair(Of Symbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol))).GetInstance(candidates.Count)

            If arguments.IsDefault Then
                arguments = ImmutableArray(Of BoundExpression).Empty
            End If

            For i As Integer = 0 To candidates.Count - 1 Step 1

                ' See if we need to consider both expanded and unexpanded version of the same method.
                ' We want to report only one set of errors in this case.
                ' Note, that, when OverloadResolution collects candidates expanded form always 
                ' immediately follows unexpanded form, if both should be considered.
                Dim allowExpandedParamArrayForm As Boolean = candidates(i).IsExpandedParamArrayForm
                Dim allowUnexpandedParamArrayForm As Boolean = Not allowExpandedParamArrayForm

                If allowUnexpandedParamArrayForm AndAlso i + 1 < candidates.Count AndAlso
                   candidates(i + 1).IsExpandedParamArrayForm AndAlso
                   candidates(i + 1).Candidate.UnderlyingSymbol.Equals(candidates(i).Candidate.UnderlyingSymbol) Then
                    allowExpandedParamArrayForm = True
                    i += 1
                End If

                Dim candidateDiagnostics = BindingDiagnosticBag.GetInstance(diagnostics)

                ' Collect diagnostic for this candidate
                ReportOverloadResolutionFailureForASingleCandidate(node, diagnosticLocation, lookupResult, candidates(i), arguments, argumentNames,
                                                         allowUnexpandedParamArrayForm, allowExpandedParamArrayForm,
                                                         False,
                                                         errorNo = If(delegateSymbol Is Nothing, ERRID.ERR_NoNonNarrowingOverloadCandidates2, ERRID.ERR_DelegateBindingFailure3),
                                                         candidateDiagnostics,
                                                         delegateSymbol:=delegateSymbol,
                                                         queryMode:=queryMode,
                                                         callerInfoOpt:=callerInfoOpt,
                                                         representCandidateInDiagnosticsOpt:=Nothing)

                diagnosticPerSymbol.Add(KeyValuePair.Create(candidates(i).Candidate.UnderlyingSymbol, candidateDiagnostics.ToReadOnlyAndFree()))

            Next

            ' See if there are errors that are reported for each candidate at the same location within a lambda argument.  
            ' Report them and don't report remaining diagnostics for each symbol separately.
            If Not ReportCommonErrorsFromLambdas(diagnosticPerSymbol, arguments, diagnostics) Then
                Dim diagnosticInfos = ArrayBuilder(Of DiagnosticInfo).GetInstance(candidates.Count)

                For i As Integer = 0 To diagnosticPerSymbol.Count - 1
                    Dim symbol = diagnosticPerSymbol(i).Key
                    Dim isExtension As Boolean = symbol.IsReducedExtensionMethod()

                    Dim sealedCandidateDiagnostics = diagnosticPerSymbol(i).Value.Diagnostics

                    ' When reporting errors for an AddressOf, Dev 10 shows different error messages depending on how many
                    ' errors there are per candidate.
                    ' One narrowing error will be shown like:
                    '     'Public Sub goo6(p As Integer, p2 As Byte)': Option Strict On disallows implicit conversions from 'Integer' to 'Byte'.
                    ' More than one narrowing issues in the parameters are abbreviated with:
                    '     'Public Sub goo6(p As Byte, p2 As Byte)': Method does not have a signature compatible with the delegate.

                    If delegateSymbol Is Nothing OrElse Not sealedCandidateDiagnostics.Skip(1).Any() Then
                        If isExtension Then
                            For Each iDiagnostic In sealedCandidateDiagnostics
                                diagnosticInfos.Add(ErrorFactory.ErrorInfo(ERRID.ERR_ExtensionMethodOverloadCandidate3,
                                                                       symbol, symbol.ContainingType, DirectCast(iDiagnostic, DiagnosticWithInfo).Info))
                            Next
                        Else
                            For Each iDiagnostic In sealedCandidateDiagnostics
                                Dim msg = VisualBasicDiagnosticFormatter.Instance.Format(iDiagnostic.WithLocation(Location.None))
                                diagnosticInfos.Add(ErrorFactory.ErrorInfo(ERRID.ERR_OverloadCandidate2, symbol, DirectCast(iDiagnostic, DiagnosticWithInfo).Info))
                            Next
                        End If
                    Else
                        If isExtension Then
                            diagnosticInfos.Add(ErrorFactory.ErrorInfo(ERRID.ERR_ExtensionMethodOverloadCandidate3,
                                                                   symbol, symbol.ContainingType,
                                                                   ErrorFactory.ErrorInfo(ERRID.ERR_DelegateBindingMismatch, symbol)))
                        Else
                            diagnosticInfos.Add(ErrorFactory.ErrorInfo(ERRID.ERR_OverloadCandidate2,
                                                                   symbol,
                                                                   ErrorFactory.ErrorInfo(ERRID.ERR_DelegateBindingMismatch, symbol)))
                        End If
                    End If
                Next

                Dim diagnosticCompoundInfos() As DiagnosticInfo = diagnosticInfos.ToArrayAndFree()
                If delegateSymbol Is Nothing Then
                    ReportDiagnostic(diagnostics, diagnosticLocation,
                                 ErrorFactory.ErrorInfo(errorNo, CustomSymbolDisplayFormatter.ShortErrorName(candidates(0).Candidate.UnderlyingSymbol),
                                                        New CompoundDiagnosticInfo(diagnosticCompoundInfos)))
                Else
                    ReportDiagnostic(diagnostics, diagnosticLocation,
                                 ErrorFactory.ErrorInfo(errorNo, CustomSymbolDisplayFormatter.ShortErrorName(candidates(0).Candidate.UnderlyingSymbol),
                                                        CustomSymbolDisplayFormatter.DelegateSignature(delegateSymbol),
                                                        New CompoundDiagnosticInfo(diagnosticCompoundInfos)))
                End If
            End If

            diagnosticPerSymbol.Free()
        End Sub

        Private Shared Function ReportCommonErrorsFromLambdas(
            diagnosticPerSymbol As ArrayBuilder(Of KeyValuePair(Of Symbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol))),
            arguments As ImmutableArray(Of BoundExpression),
            diagnostics As BindingDiagnosticBag
        ) As Boolean
            Dim haveCommonErrors As Boolean = False

            For Each diagnostic In diagnosticPerSymbol(0).Value.Diagnostics
                If diagnostic.Severity <> DiagnosticSeverity.Error Then
                    Continue For
                End If

                For Each argument In arguments
                    If argument.Syntax.SyntaxTree Is diagnostic.Location.SourceTree AndAlso
                       argument.Kind = BoundKind.UnboundLambda Then
                        If argument.Syntax.Span.Contains(diagnostic.Location.SourceSpan) Then
                            Dim common As Boolean = True
                            For i As Integer = 1 To diagnosticPerSymbol.Count - 1
                                If Not diagnosticPerSymbol(i).Value.Diagnostics.Contains(diagnostic) Then
                                    common = False
                                    Exit For
                                End If
                            Next

                            If common Then
                                haveCommonErrors = True
                                diagnostics.Add(diagnostic)
                            End If

                            Exit For
                        End If
                    End If
                Next
            Next

            Return haveCommonErrors
        End Function

        ''' <summary>
        ''' Should be kept in sync with OverloadResolution.MatchArguments. Anything that 
        ''' OverloadResolution.MatchArguments flags as an error should be detected by 
        ''' this function as well. 
        ''' </summary>
        Private Sub ReportOverloadResolutionFailureForASingleCandidate(
            node As SyntaxNode,
            diagnosticLocation As Location,
            lookupResult As LookupResultKind,
            ByRef candidateAnalysisResult As OverloadResolution.CandidateAnalysisResult,
            arguments As ImmutableArray(Of BoundExpression),
            argumentNames As ImmutableArray(Of String),
            allowUnexpandedParamArrayForm As Boolean,
            allowExpandedParamArrayForm As Boolean,
            includeMethodNameInErrorMessages As Boolean,
            reportNarrowingConversions As Boolean,
            diagnostics As BindingDiagnosticBag,
            delegateSymbol As Symbol,
            queryMode As Boolean,
            callerInfoOpt As SyntaxNode,
            representCandidateInDiagnosticsOpt As Symbol
        )
            Dim candidate As OverloadResolution.Candidate = candidateAnalysisResult.Candidate

            If arguments.IsDefault Then
                arguments = ImmutableArray(Of BoundExpression).Empty
            End If

            Debug.Assert(argumentNames.IsDefaultOrEmpty OrElse (argumentNames.Length > 0 AndAlso argumentNames.Length = arguments.Length))
            Debug.Assert(allowUnexpandedParamArrayForm OrElse allowExpandedParamArrayForm)

            If candidateAnalysisResult.State = VisualBasic.OverloadResolution.CandidateAnalysisResultState.HasUseSiteError OrElse
               candidateAnalysisResult.State = VisualBasic.OverloadResolution.CandidateAnalysisResultState.HasUnsupportedMetadata Then
                If lookupResult <> LookupResultKind.Inaccessible Then
                    Debug.Assert(lookupResult = LookupResultKind.Good)
                    ReportUseSite(diagnostics, diagnosticLocation, candidate.UnderlyingSymbol.GetUseSiteInfo())
                End If

                Return
            End If

            ' To simplify following code
            If Not argumentNames.IsDefault AndAlso argumentNames.Length = 0 Then
                argumentNames = Nothing
            End If

            Dim parameterToArgumentMap As ArrayBuilder(Of Integer) = ArrayBuilder(Of Integer).GetInstance(candidate.ParameterCount, -1)
            Dim paramArrayItems As ArrayBuilder(Of Integer) = ArrayBuilder(Of Integer).GetInstance()

            Try
                '§11.8.2 Applicable Methods
                '1.	First, match each positional argument in order to the list of method parameters. 
                'If there are more positional arguments than parameters and the last parameter is not a paramarray, the method is not applicable. 
                'Otherwise, the paramarray parameter is expanded with parameters of the paramarray element type to match the number of positional arguments. 
                'If a positional argument is omitted, the method is not applicable.
                ' !!! Not sure about the last sentence: "If a positional argument is omitted, the method is not applicable."
                ' !!! Dev10 allows omitting positional argument as long as the corresponding parameter is optional.

                Dim positionalArguments As Integer = 0
                Dim paramIndex = 0
                Dim someArgumentsBad As Boolean = False
                Dim someParamArrayArgumentsBad As Boolean = False
                Dim seenOutOfPositionNamedArgIndex As Integer = -1

                Dim candidateSymbol As Symbol = candidate.UnderlyingSymbol
                Dim candidateIsExtension As Boolean = candidate.IsExtensionMethod

                For i As Integer = 0 To arguments.Length - 1 Step 1

                    ' A named argument which is used in-position counts as positional
                    If Not argumentNames.IsDefault AndAlso argumentNames(i) IsNot Nothing Then
                        If Not candidate.TryGetNamedParamIndex(argumentNames(i), paramIndex) Then
                            Exit For
                        End If

                        If paramIndex <> i Then
                            ' all remaining arguments must be named
                            seenOutOfPositionNamedArgIndex = i
                            Exit For
                        End If

                        If paramIndex = candidate.ParameterCount - 1 AndAlso candidate.Parameters(paramIndex).IsParamArray Then
                            Exit For
                        End If

                        Debug.Assert(parameterToArgumentMap(paramIndex) = -1)
                    End If

                    If paramIndex = candidate.ParameterCount Then
                        If Not someArgumentsBad Then
                            If Not includeMethodNameInErrorMessages Then
                                ReportDiagnostic(diagnostics, arguments(i).Syntax, ERRID.ERR_TooManyArgs)
                            ElseIf candidateIsExtension Then
                                ReportDiagnostic(diagnostics, arguments(i).Syntax,
                                                 ERRID.ERR_TooManyArgs2,
                                                 candidateSymbol, candidateSymbol.ContainingType)
                            Else
                                ReportDiagnostic(diagnostics, arguments(i).Syntax,
                                                 ERRID.ERR_TooManyArgs1, If(representCandidateInDiagnosticsOpt, candidateSymbol))
                            End If

                            someArgumentsBad = True
                        End If

                    ElseIf paramIndex = candidate.ParameterCount - 1 AndAlso
                           candidate.Parameters(paramIndex).IsParamArray Then

                        ' Collect ParamArray arguments
                        While i < arguments.Length

                            If Not argumentNames.IsDefault AndAlso argumentNames(i) IsNot Nothing Then
                                ' First named argument
                                Continue For
                            End If

                            If arguments(i).Kind = BoundKind.OmittedArgument Then
                                ReportDiagnostic(diagnostics, arguments(i).Syntax, ERRID.ERR_OmittedParamArrayArgument)
                                someParamArrayArgumentsBad = True
                            Else
                                paramArrayItems.Add(i)
                            End If

                            positionalArguments += 1
                            i += 1
                        End While

                        Exit For

                    Else
                        parameterToArgumentMap(paramIndex) = i
                        paramIndex += 1
                    End If

                    positionalArguments += 1
                Next

                Dim skippedSomeArguments As Boolean = False

                '§11.8.2 Applicable Methods
                '2.	Next, match each named argument to a parameter with the given name. 
                'If one of the named arguments fails to match, matches a paramarray parameter, 
                'or matches an argument already matched with another positional or named argument, 
                'the method is not applicable.
                For i As Integer = positionalArguments To arguments.Length - 1 Step 1

                    Debug.Assert(argumentNames(i) Is Nothing OrElse argumentNames(i).Length > 0)

                    If argumentNames(i) Is Nothing Then
                        ' Unnamed argument follows out-of-position named arguments
                        If Not someArgumentsBad Then
                            ReportDiagnostic(diagnostics, GetNamedArgumentIdentifier(arguments(seenOutOfPositionNamedArgIndex).Syntax),
                                         ERRID.ERR_BadNonTrailingNamedArgument, argumentNames(seenOutOfPositionNamedArgIndex))
                        End If
                        Return
                    End If

                    If Not candidate.TryGetNamedParamIndex(argumentNames(i), paramIndex) Then
                        ' ERRID_NamedParamNotFound1
                        ' ERRID_NamedParamNotFound2
                        If Not includeMethodNameInErrorMessages Then
                            ReportDiagnostic(diagnostics, GetNamedArgumentIdentifier(arguments(i).Syntax), ERRID.ERR_NamedParamNotFound1, argumentNames(i))
                        ElseIf candidateIsExtension Then
                            ReportDiagnostic(diagnostics, GetNamedArgumentIdentifier(arguments(i).Syntax),
                                             ERRID.ERR_NamedParamNotFound3, argumentNames(i),
                                             candidateSymbol, candidateSymbol.ContainingType)
                        Else
                            ReportDiagnostic(diagnostics, GetNamedArgumentIdentifier(arguments(i).Syntax),
                                             ERRID.ERR_NamedParamNotFound2, argumentNames(i), If(representCandidateInDiagnosticsOpt, candidateSymbol))
                        End If

                        someArgumentsBad = True
                        Continue For
                    End If

                    If paramIndex = candidate.ParameterCount - 1 AndAlso
                        candidate.Parameters(paramIndex).IsParamArray Then
                        ' ERRID_NamedParamArrayArgument
                        ReportDiagnostic(diagnostics, GetNamedArgumentIdentifier(arguments(i).Syntax), ERRID.ERR_NamedParamArrayArgument)
                        someArgumentsBad = True
                        Continue For
                    End If

                    If parameterToArgumentMap(paramIndex) <> -1 AndAlso arguments(parameterToArgumentMap(paramIndex)).Kind <> BoundKind.OmittedArgument Then
                        ' ERRID_NamedArgUsedTwice1
                        ' ERRID_NamedArgUsedTwice2
                        ' ERRID_NamedArgUsedTwice3
                        If Not includeMethodNameInErrorMessages Then
                            ReportDiagnostic(diagnostics, GetNamedArgumentIdentifier(arguments(i).Syntax), ERRID.ERR_NamedArgUsedTwice1, argumentNames(i))
                        ElseIf candidateIsExtension Then
                            ReportDiagnostic(diagnostics, GetNamedArgumentIdentifier(arguments(i).Syntax),
                                             ERRID.ERR_NamedArgUsedTwice3, argumentNames(i),
                                             candidateSymbol, candidateSymbol.ContainingType)
                        Else
                            ReportDiagnostic(diagnostics, GetNamedArgumentIdentifier(arguments(i).Syntax),
                                             ERRID.ERR_NamedArgUsedTwice2, argumentNames(i), If(representCandidateInDiagnosticsOpt, candidateSymbol))
                        End If

                        someArgumentsBad = True
                        Continue For
                    End If

                    ' It is an error for a named argument to specify
                    ' a value for an explicitly omitted positional argument.
                    If paramIndex < positionalArguments Then
                        'ERRID_NamedArgAlsoOmitted1
                        'ERRID_NamedArgAlsoOmitted2
                        'ERRID_NamedArgAlsoOmitted3
                        If Not includeMethodNameInErrorMessages Then
                            ReportDiagnostic(diagnostics, GetNamedArgumentIdentifier(arguments(i).Syntax), ERRID.ERR_NamedArgAlsoOmitted1, argumentNames(i))
                        ElseIf candidateIsExtension Then
                            ReportDiagnostic(diagnostics, GetNamedArgumentIdentifier(arguments(i).Syntax),
                                             ERRID.ERR_NamedArgAlsoOmitted3, argumentNames(i),
                                             candidateSymbol, candidateSymbol.ContainingType)
                        Else
                            ReportDiagnostic(diagnostics, GetNamedArgumentIdentifier(arguments(i).Syntax),
                                             ERRID.ERR_NamedArgAlsoOmitted2, argumentNames(i), If(representCandidateInDiagnosticsOpt, candidateSymbol))
                        End If

                        someArgumentsBad = True
                    End If

                    parameterToArgumentMap(paramIndex) = i
                Next

                ' Check whether type inference failed
                diagnostics.AddRange(candidateAnalysisResult.TypeArgumentInferenceDiagnosticsOpt)

                If candidate.IsGeneric AndAlso candidateAnalysisResult.State = OverloadResolution.CandidateAnalysisResultState.TypeInferenceFailed Then
                    ' Bug 122092: AddressOf doesn't want detailed info on which parameters could not be
                    ' inferred, just report the general type inference failed message in this case.
                    If delegateSymbol IsNot Nothing Then
                        ReportDiagnostic(diagnostics, diagnosticLocation, ERRID.ERR_DelegateBindingTypeInferenceFails)
                        Return
                    End If

                    If Not candidateAnalysisResult.SomeInferenceFailed Then

                        Dim reportedAnError As Boolean = False

                        For i As Integer = 0 To candidate.Arity - 1 Step 1
                            If candidateAnalysisResult.NotInferredTypeArguments(i) Then
                                If Not includeMethodNameInErrorMessages Then
                                    ReportDiagnostic(diagnostics, diagnosticLocation, ERRID.ERR_UnboundTypeParam1, candidate.TypeParameters(i))
                                ElseIf candidateIsExtension Then
                                    ReportDiagnostic(diagnostics, diagnosticLocation,
                                                     ERRID.ERR_UnboundTypeParam3, candidate.TypeParameters(i),
                                                     candidateSymbol, candidateSymbol.ContainingType)
                                Else
                                    ReportDiagnostic(diagnostics, diagnosticLocation,
                                                     ERRID.ERR_UnboundTypeParam2, candidate.TypeParameters(i), If(representCandidateInDiagnosticsOpt, candidateSymbol))
                                End If

                                reportedAnError = True
                            End If
                        Next

                        If reportedAnError Then
                            Return
                        End If
                    End If

                    Dim inferenceErrorReasons As InferenceErrorReasons = candidateAnalysisResult.InferenceErrorReasons

                    If (inferenceErrorReasons And InferenceErrorReasons.Ambiguous) <> 0 Then
                        If Not includeMethodNameInErrorMessages Then
                            ReportDiagnostic(diagnostics, diagnosticLocation, If(queryMode, ERRID.ERR_TypeInferenceFailureNoExplicitAmbiguous1, ERRID.ERR_TypeInferenceFailureAmbiguous1))
                        ElseIf candidateIsExtension Then
                            ReportDiagnostic(diagnostics, diagnosticLocation, If(queryMode, ERRID.ERR_TypeInferenceFailureNoExplicitAmbiguous3, ERRID.ERR_TypeInferenceFailureAmbiguous3), candidateSymbol, candidateSymbol.ContainingType)
                        Else
                            ReportDiagnostic(diagnostics, diagnosticLocation, If(queryMode, ERRID.ERR_TypeInferenceFailureNoExplicitAmbiguous2, ERRID.ERR_TypeInferenceFailureAmbiguous2), If(representCandidateInDiagnosticsOpt, candidateSymbol))
                        End If
                    ElseIf (inferenceErrorReasons And InferenceErrorReasons.NoBest) <> 0 Then
                        If Not includeMethodNameInErrorMessages Then
                            ReportDiagnostic(diagnostics, diagnosticLocation, If(queryMode, ERRID.ERR_TypeInferenceFailureNoExplicitNoBest1, ERRID.ERR_TypeInferenceFailureNoBest1))
                        ElseIf candidateIsExtension Then
                            ReportDiagnostic(diagnostics, diagnosticLocation, If(queryMode, ERRID.ERR_TypeInferenceFailureNoExplicitNoBest3, ERRID.ERR_TypeInferenceFailureNoBest3), candidateSymbol, candidateSymbol.ContainingType)
                        Else
                            ReportDiagnostic(diagnostics, diagnosticLocation, If(queryMode, ERRID.ERR_TypeInferenceFailureNoExplicitNoBest2, ERRID.ERR_TypeInferenceFailureNoBest2), If(representCandidateInDiagnosticsOpt, candidateSymbol))
                        End If
                    Else
                        If candidateAnalysisResult.TypeArgumentInferenceDiagnosticsOpt.HasAnyResolvedErrors Then
                            ' Already reported some errors, let's not report a general inference error
                            Return
                        End If

                        If Not includeMethodNameInErrorMessages Then
                            ReportDiagnostic(diagnostics, diagnosticLocation, If(queryMode, ERRID.ERR_TypeInferenceFailureNoExplicit1, ERRID.ERR_TypeInferenceFailure1))
                        ElseIf candidateIsExtension Then
                            ReportDiagnostic(diagnostics, diagnosticLocation, If(queryMode, ERRID.ERR_TypeInferenceFailureNoExplicit3, ERRID.ERR_TypeInferenceFailure3), candidateSymbol, candidateSymbol.ContainingType)
                        Else
                            ReportDiagnostic(diagnostics, diagnosticLocation, If(queryMode, ERRID.ERR_TypeInferenceFailureNoExplicit2, ERRID.ERR_TypeInferenceFailure2), If(representCandidateInDiagnosticsOpt, candidateSymbol))
                        End If
                    End If

                    Return
                End If

                ' Check generic constraints for method type arguments.
                If candidateAnalysisResult.State = OverloadResolution.CandidateAnalysisResultState.GenericConstraintsViolated Then
                    Debug.Assert(candidate.IsGeneric)
                    Debug.Assert(candidate.UnderlyingSymbol.Kind = SymbolKind.Method)

                    Dim method = DirectCast(candidate.UnderlyingSymbol, MethodSymbol)
                    ' TODO: Dev10 uses the location of the type parameter or argument that
                    ' violated the constraint, rather than  the entire invocation expression.
                    Dim succeeded = method.CheckConstraints(Compilation.LanguageVersion, diagnosticLocation, diagnostics, template:=GetNewCompoundUseSiteInfo(diagnostics))
                    Debug.Assert(Not succeeded)
                    Return
                End If

                If candidateAnalysisResult.TypeArgumentInferenceDiagnosticsOpt.HasAnyErrors Then
                    Return
                End If

                ' Traverse the parameters, converting corresponding arguments
                ' as appropriate.

                Dim argIndex As Integer
                Dim candidateIsAProperty As Boolean = (candidateSymbol.Kind = SymbolKind.Property)

                For paramIndex = 0 To candidate.ParameterCount - 1 Step 1

                    Dim param As ParameterSymbol = candidate.Parameters(paramIndex)
                    Dim isByRef As Boolean = param.IsByRef
                    Dim targetType As TypeSymbol = param.Type

                    Dim argument As BoundExpression = Nothing

                    If param.IsParamArray AndAlso paramIndex = candidate.ParameterCount - 1 Then

                        If targetType.Kind <> SymbolKind.ArrayType Then

                            If targetType.Kind <> SymbolKind.ErrorType Then
                                ' ERRID_ParamArrayWrongType
                                ReportDiagnostic(diagnostics, diagnosticLocation, ERRID.ERR_ParamArrayWrongType)
                            End If

                            someArgumentsBad = True
                            Continue For

                        ElseIf someParamArrayArgumentsBad Then
                            Continue For
                        End If

                        If paramArrayItems.Count = 1 Then
                            Dim paramArrayArgument = arguments(paramArrayItems(0))

                            '§11.8.2 Applicable Methods
                            'If the conversion from the type of the argument expression to the paramarray type is narrowing, 
                            'then the method is only applicable in its expanded form.
                            Dim arrayConversion As KeyValuePair(Of ConversionKind, MethodSymbol) = Nothing
                            If allowUnexpandedParamArrayForm AndAlso
                                Not (Not paramArrayArgument.HasErrors AndAlso
                                    OverloadResolution.CanPassToParamArray(paramArrayArgument, targetType, arrayConversion, Me, CompoundUseSiteInfo(Of AssemblySymbol).Discarded)) Then
                                allowUnexpandedParamArrayForm = False
                            End If

                            '§11.8.2 Applicable Methods
                            'If the argument expression is the literal Nothing, then the method is only applicable in its unexpanded form 
                            If allowExpandedParamArrayForm AndAlso
                                paramArrayArgument.IsNothingLiteral() Then
                                allowExpandedParamArrayForm = False
                            End If

                        Else
                            ' Unexpanded form is not applicable: there are either more than one value or no values. 
                            If Not allowExpandedParamArrayForm Then

                                If paramArrayItems.Count = 0 Then
                                    If Not includeMethodNameInErrorMessages Then
                                        ReportDiagnostic(diagnostics, diagnosticLocation, ERRID.ERR_OmittedArgument1, CustomSymbolDisplayFormatter.ShortErrorName(param))
                                    ElseIf candidateIsExtension Then
                                        ReportDiagnostic(diagnostics, diagnosticLocation,
                                                         ERRID.ERR_OmittedArgument3, CustomSymbolDisplayFormatter.ShortErrorName(param),
                                                         candidateSymbol, candidateSymbol.ContainingType)
                                    Else
                                        ReportDiagnostic(diagnostics, diagnosticLocation,
                                                         ERRID.ERR_OmittedArgument2, CustomSymbolDisplayFormatter.ShortErrorName(param),
                                                         If(representCandidateInDiagnosticsOpt, candidateSymbol))
                                    End If
                                Else
                                    If Not includeMethodNameInErrorMessages Then
                                        ReportDiagnostic(diagnostics, diagnosticLocation, ERRID.ERR_TooManyArgs)
                                    ElseIf candidateIsExtension Then
                                        ReportDiagnostic(diagnostics, diagnosticLocation,
                                                           ERRID.ERR_TooManyArgs2, candidateSymbol, candidateSymbol.ContainingType)
                                    Else
                                        ReportDiagnostic(diagnostics, diagnosticLocation,
                                                 ERRID.ERR_TooManyArgs1, If(representCandidateInDiagnosticsOpt, candidateSymbol))
                                    End If
                                End If

                                someArgumentsBad = True
                                Continue For
                            End If

                            allowUnexpandedParamArrayForm = False
                        End If

                        If allowUnexpandedParamArrayForm Then
                            argument = arguments(paramArrayItems(0))
                            ReportByValConversionErrors(param, argument, targetType, reportNarrowingConversions, diagnostics)

                        ElseIf allowExpandedParamArrayForm Then
                            Dim arrayType = DirectCast(targetType, ArrayTypeSymbol)

                            If Not arrayType.IsSZArray Then
                                ' ERRID_ParamArrayWrongType
                                ReportDiagnostic(diagnostics, diagnosticLocation, ERRID.ERR_ParamArrayWrongType)
                                someArgumentsBad = True
                                Continue For
                            End If

                            Dim arrayElementType = arrayType.ElementType

                            For i As Integer = 0 To paramArrayItems.Count - 1 Step 1
                                argument = arguments(paramArrayItems(i))
                                ReportByValConversionErrors(param, argument, arrayElementType, reportNarrowingConversions, diagnostics)
                            Next
                        Else
                            Debug.Assert(paramArrayItems.Count = 1)
                            Dim paramArrayArgument = arguments(paramArrayItems(0))
                            ReportDiagnostic(diagnostics, paramArrayArgument.Syntax, ERRID.ERR_ParamArrayArgumentMismatch)
                        End If

                        Continue For
                    End If

                    argIndex = parameterToArgumentMap(paramIndex)
                    argument = If(argIndex = -1, Nothing, arguments(argIndex))

                    ' Argument nothing when the argument syntax is missing or BoundKind.OmittedArgument when the argument list contains commas
                    ' for the missing syntax so we have to test for both.
                    If argument Is Nothing OrElse argument.Kind = BoundKind.OmittedArgument Then

                        If argument Is Nothing AndAlso skippedSomeArguments Then
                            someArgumentsBad = True
                            Continue For
                        End If

                        'See Section 3 of §11.8.2 Applicable Methods

                        ' Deal with Optional arguments
                        ' Need to handle optional arguments here, there could be conversion errors, etc.

                        ' reducedExtensionReceiverOpt is used to determine the default value of a CallerArgumentExpression when it refers to the first parameter of an extension method.
                        ' Don't bother with correctly determining the correct value for this case since we're in an error case anyway.
                        argument = GetArgumentForParameterDefaultValue(param, node, diagnostics, callerInfoOpt, parameterToArgumentMap, arguments, reducedExtensionReceiverOpt:=Nothing)

                        If argument Is Nothing Then
                            If Not includeMethodNameInErrorMessages Then
                                ReportDiagnostic(diagnostics, diagnosticLocation, ERRID.ERR_OmittedArgument1, CustomSymbolDisplayFormatter.ShortErrorName(param))
                            ElseIf candidateIsExtension Then
                                ReportDiagnostic(diagnostics, diagnosticLocation,
                                                 ERRID.ERR_OmittedArgument3, CustomSymbolDisplayFormatter.ShortErrorName(param),
                                                 candidateSymbol, candidateSymbol.ContainingType)
                            Else
                                ReportDiagnostic(diagnostics, diagnosticLocation,
                                                 ERRID.ERR_OmittedArgument2, CustomSymbolDisplayFormatter.ShortErrorName(param), If(representCandidateInDiagnosticsOpt, candidateSymbol))
                            End If

                            someArgumentsBad = True
                            Continue For
                        End If
                    End If

                    Debug.Assert(Not isByRef OrElse param.IsExplicitByRef OrElse targetType.IsStringType())

                    ' Arguments for properties are always passed with ByVal semantics. Even if
                    ' parameter in metadata is defined ByRef, we always pass corresponding argument 
                    ' through a temp without copy-back. Unlike with method calls, we rely on CodeGen
                    ' to introduce the temp (easy to do since there is no copy-back around it),
                    ' this allows us to keep the BoundPropertyAccess node simpler and allows to avoid
                    ' A LOT of complexity in UseTwiceRewriter, which we would otherwise have around
                    ' the temps.
                    ' Non-string arguments for implicitly ByRef string parameters of Declare functions
                    ' are passed through a temp without copy-back.
                    If isByRef AndAlso Not candidateIsAProperty AndAlso
                       (param.IsExplicitByRef OrElse (argument.Type IsNot Nothing AndAlso argument.Type.IsStringType())) Then
                        ReportByRefConversionErrors(candidate, param, argument, targetType, reportNarrowingConversions, diagnostics,
                                                    diagnosticNode:=node, delegateSymbol:=delegateSymbol)
                    Else
                        ReportByValConversionErrors(param, argument, targetType, reportNarrowingConversions, diagnostics,
                                                    diagnosticNode:=node, delegateSymbol:=delegateSymbol)
                    End If
                Next

            Finally
                paramArrayItems.Free()
                parameterToArgumentMap.Free()
            End Try
        End Sub

        ''' <summary>
        ''' Should be in sync with OverloadResolution.MatchArgumentToByRefParameter
        ''' </summary>
        Private Sub ReportByRefConversionErrors(
            candidate As OverloadResolution.Candidate,
            param As ParameterSymbol,
            argument As BoundExpression,
            targetType As TypeSymbol,
            reportNarrowingConversions As Boolean,
            diagnostics As BindingDiagnosticBag,
            Optional diagnosticNode As SyntaxNode = Nothing,
            Optional delegateSymbol As Symbol = Nothing
        )

            ' TODO: Do we need to do more thorough check for error types here, i.e. dig into generics, 
            ' arrays, etc., detect types from unreferenced assemblies, ... ?
            If targetType.IsErrorType() OrElse argument.HasErrors Then ' UNDONE: should HasErrors really always cause argument mismatch [petergo, 3/9/2011]
                Return
            End If

            If argument.IsSupportingAssignment() Then

                If Not (argument.IsLValue() AndAlso targetType.IsSameTypeIgnoringAll(argument.Type)) Then

                    If Not ReportByValConversionErrors(param, argument, targetType, reportNarrowingConversions, diagnostics,
                                                       diagnosticNode:=diagnosticNode,
                                                       delegateSymbol:=delegateSymbol) Then

                        ' Check copy back conversion
                        Dim boundTemp = New BoundRValuePlaceholder(argument.Syntax, targetType)
                        Dim copyBackType = argument.GetTypeOfAssignmentTarget()
                        Dim conv As KeyValuePair(Of ConversionKind, MethodSymbol) = Conversions.ClassifyConversion(boundTemp, copyBackType, Me, CompoundUseSiteInfo(Of AssemblySymbol).Discarded)

                        If Conversions.NoConversion(conv.Key) Then
                            ' Possible only with user-defined conversions, I think.
                            CreateConversionAndReportDiagnostic(argument.Syntax, boundTemp, conv, False, copyBackType, diagnostics, copybackConversionParamName:=param.Name)
                        ElseIf Conversions.IsNarrowingConversion(conv.Key) Then

                            Debug.Assert((conv.Key And ConversionKind.InvolvesNarrowingFromNumericConstant) = 0)

                            If OptionStrict = VisualBasic.OptionStrict.On Then
                                CreateConversionAndReportDiagnostic(argument.Syntax, boundTemp, conv, False, copyBackType, diagnostics, copybackConversionParamName:=param.Name)
                            ElseIf reportNarrowingConversions Then
                                ReportDiagnostic(diagnostics, argument.Syntax, ERRID.ERR_ArgumentCopyBackNarrowing3,
                                                       CustomSymbolDisplayFormatter.ShortErrorName(param), targetType, copyBackType)
                            End If
                        End If

                    End If

                End If

            Else
                ' No copy back needed

                ' If we are inside a lambda in a constructor and are passing ByRef a non-LValue field, which 
                ' would be an LValue field, if it were referred to in the constructor outside of a lambda, 
                ' we need to report an error because the operation will result in a simulated pass by
                ' ref (through a temp, without a copy back), which might be not the intent.
                If Report_ERRID_ReadOnlyInClosure(argument) Then
                    ReportDiagnostic(diagnostics, argument.Syntax, ERRID.ERR_ReadOnlyInClosure)
                End If

                ReportByValConversionErrors(param, argument, targetType, reportNarrowingConversions, diagnostics,
                                            diagnosticNode:=diagnosticNode,
                                            delegateSymbol:=delegateSymbol)
            End If

        End Sub

        ''' <summary>
        ''' Should be in sync with OverloadResolution.MatchArgumentToByValParameter.
        ''' </summary>
        Private Function ReportByValConversionErrors(
            param As ParameterSymbol,
            argument As BoundExpression,
            targetType As TypeSymbol,
            reportNarrowingConversions As Boolean,
            diagnostics As BindingDiagnosticBag,
            Optional diagnosticNode As SyntaxNode = Nothing,
            Optional delegateSymbol As Symbol = Nothing
        ) As Boolean

            ' TODO: Do we need to do more thorough check for error types here, i.e. dig into generics, 
            ' arrays, etc., detect types from unreferenced assemblies, ... ?
            If targetType.IsErrorType() OrElse argument.HasErrors Then ' UNDONE: should HasErrors really always cause argument mismatch [petergo, 3/9/2011]
                Return True
            End If

            Dim conv As KeyValuePair(Of ConversionKind, MethodSymbol) = Conversions.ClassifyConversion(argument, targetType, Me, CompoundUseSiteInfo(Of AssemblySymbol).Discarded)

            If Conversions.NoConversion(conv.Key) Then
                If delegateSymbol Is Nothing Then
                    CreateConversionAndReportDiagnostic(argument.Syntax, argument, conv, False, targetType, diagnostics)
                Else
                    ' in case of delegates, use the operand of the AddressOf as location for this error
                    CreateConversionAndReportDiagnostic(diagnosticNode, argument, conv, False, targetType, diagnostics)
                End If

                Return True
            End If

            Dim requiresNarrowingConversion As Boolean = False

            If Conversions.IsNarrowingConversion(conv.Key) Then

                If (conv.Key And ConversionKind.InvolvesNarrowingFromNumericConstant) = 0 Then

                    If OptionStrict = VisualBasic.OptionStrict.On Then
                        If delegateSymbol Is Nothing Then
                            CreateConversionAndReportDiagnostic(argument.Syntax, argument, conv, False, targetType, diagnostics)
                        Else
                            ' in case of delegates, use the operand of the AddressOf as location for this error
                            ' because delegates have different error messages in case there is one or more candidates for narrowing
                            ' indicate this as well.
                            CreateConversionAndReportDiagnostic(diagnosticNode, argument, conv, False, targetType, diagnostics)
                        End If

                        Return True
                    End If
                End If

                requiresNarrowingConversion = True

            ElseIf (conv.Key And ConversionKind.InvolvesNarrowingFromNumericConstant) <> 0 Then
                ' Dev10 overload resolution treats conversions that involve narrowing from numeric constant type
                ' as narrowing.
                requiresNarrowingConversion = True
            End If

            If reportNarrowingConversions AndAlso requiresNarrowingConversion Then
                Dim err As ERRID = ERRID.ERR_ArgumentNarrowing3

                Dim targetDelegateType = targetType.DelegateOrExpressionDelegate(Me)
                If argument.Kind = BoundKind.QueryLambda AndAlso targetDelegateType IsNot Nothing Then
                    Dim invoke As MethodSymbol = targetDelegateType.DelegateInvokeMethod

                    If invoke IsNot Nothing AndAlso Not invoke.IsSub Then
                        err = ERRID.ERR_NestedFunctionArgumentNarrowing3
                        argument = DirectCast(argument, BoundQueryLambda).Expression
                        targetType = invoke.ReturnType
                    End If
                End If

                If argument.Type Is Nothing Then
                    ReportDiagnostic(diagnostics, argument.Syntax, ERRID.ERR_ArgumentNarrowing2,
                                           CustomSymbolDisplayFormatter.ShortErrorName(param), targetType)
                Else
                    ReportDiagnostic(diagnostics, argument.Syntax, err,
                                           CustomSymbolDisplayFormatter.ShortErrorName(param), argument.Type, targetType)
                End If
            End If

            Return False
        End Function

        ''' <summary>
        ''' Should be kept in sync with OverloadResolution.MatchArguments, which populates 
        ''' data this function operates on.
        ''' </summary>
        Private Function PassArguments(
            node As SyntaxNode,
            ByRef candidate As OverloadResolution.CandidateAnalysisResult,
            arguments As ImmutableArray(Of BoundExpression),
            diagnostics As BindingDiagnosticBag
        ) As (Arguments As ImmutableArray(Of BoundExpression), DefaultArguments As BitVector)

            Debug.Assert(candidate.State = OverloadResolution.CandidateAnalysisResultState.Applicable)

            If (arguments.IsDefault) Then
                arguments = ImmutableArray(Of BoundExpression).Empty
            End If

            Dim paramCount As Integer = candidate.Candidate.ParameterCount

            Dim parameterToArgumentMap = ArrayBuilder(Of Integer).GetInstance(paramCount, -1)
            Dim argumentsInOrder = ArrayBuilder(Of BoundExpression).GetInstance(paramCount)
            Dim defaultArguments = BitVector.Null

            Dim paramArrayItems As ArrayBuilder(Of Integer) = Nothing

            If candidate.IsExpandedParamArrayForm Then
                paramArrayItems = ArrayBuilder(Of Integer).GetInstance()
            End If

            Dim paramIndex As Integer

            ' For each parameter figure out matching argument.
            If candidate.ArgsToParamsOpt.IsDefaultOrEmpty Then
                Dim regularParamCount As Integer = paramCount

                If candidate.IsExpandedParamArrayForm Then
                    regularParamCount -= 1
                End If

                For i As Integer = 0 To Math.Min(regularParamCount, arguments.Length) - 1 Step 1
                    If arguments(i).Kind <> BoundKind.OmittedArgument Then
                        parameterToArgumentMap(i) = i
                    End If
                Next

                If candidate.IsExpandedParamArrayForm Then
                    For i As Integer = regularParamCount To arguments.Length - 1 Step 1
                        paramArrayItems.Add(i)
                    Next
                End If
            Else
                Dim argsToParams = candidate.ArgsToParamsOpt

                For i As Integer = 0 To argsToParams.Length - 1 Step 1
                    paramIndex = argsToParams(i)

                    If arguments(i).Kind <> BoundKind.OmittedArgument Then
                        If (candidate.IsExpandedParamArrayForm AndAlso
                            paramIndex = candidate.Candidate.ParameterCount - 1) Then

                            paramArrayItems.Add(i)
                        Else
                            parameterToArgumentMap(paramIndex) = i
                        End If
                    End If
                Next
            End If

            ' Traverse the parameters, converting corresponding arguments
            ' as appropriate.
            Dim candidateIsAProperty As Boolean = (candidate.Candidate.UnderlyingSymbol.Kind = SymbolKind.Property)

            For paramIndex = 0 To paramCount - 1 Step 1

                Dim param As ParameterSymbol = candidate.Candidate.Parameters(paramIndex)
                Dim targetType As TypeSymbol = param.Type

                Dim argument As BoundExpression = Nothing
                Dim conversion As KeyValuePair(Of ConversionKind, MethodSymbol) = Conversions.Identity
                Dim conversionBack As KeyValuePair(Of ConversionKind, MethodSymbol) = Conversions.Identity

                If candidate.IsExpandedParamArrayForm AndAlso paramIndex = candidate.Candidate.ParameterCount - 1 Then
                    Dim arrayElementType = DirectCast(targetType, ArrayTypeSymbol).ElementType

                    Dim items = ArrayBuilder(Of BoundExpression).GetInstance(paramArrayItems.Count)

                    For i As Integer = 0 To paramArrayItems.Count - 1 Step 1
                        items.Add(PassArgumentByVal(arguments(paramArrayItems(i)),
                                                               If(candidate.ConversionsOpt.IsDefaultOrEmpty,
                                                                  Conversions.Identity,
                                                                  candidate.ConversionsOpt(paramArrayItems(i))),
                                                               arrayElementType, diagnostics))
                    Next

                    ' Create the bound array and ensure that it is marked as compiler generated.
                    argument = New BoundArrayCreation(node, True,
                                    (New BoundExpression() {New BoundLiteral(node,
                                        ConstantValue.Create(items.Count),
                                        GetSpecialType(SpecialType.System_Int32, node, diagnostics)).MakeCompilerGenerated()}).AsImmutableOrNull(),
                                    New BoundArrayInitialization(node, items.ToImmutableAndFree(), targetType).MakeCompilerGenerated(), Nothing, Nothing, targetType).MakeCompilerGenerated()
                Else
                    Dim argIndex As Integer
                    argIndex = parameterToArgumentMap(paramIndex)
                    argument = If(argIndex = -1, Nothing, arguments(argIndex))

                    If argument IsNot Nothing AndAlso paramIndex = candidate.Candidate.ParameterCount - 1 AndAlso
                       param.IsParamArray Then
                        argument = ApplyImplicitConversion(argument.Syntax, targetType, argument, diagnostics)
                        ' Leave both conversions at identity since we already applied the conversion
                    ElseIf argIndex > -1 Then
                        If Not candidate.ConversionsOpt.IsDefaultOrEmpty Then
                            conversion = candidate.ConversionsOpt(argIndex)
                        End If

                        If Not candidate.ConversionsBackOpt.IsDefaultOrEmpty Then
                            conversionBack = candidate.ConversionsBackOpt(argIndex)
                        End If
                    End If
                End If

                Dim argumentIsDefaultValue As Boolean = False

                If argument Is Nothing Then
                    Debug.Assert(Not candidate.OptionalArguments.IsEmpty, "Optional arguments expected")

                    If defaultArguments.IsNull Then
                        defaultArguments = BitVector.Create(paramCount)
                    End If

                    ' Deal with Optional arguments
                    Dim defaultArgument As OverloadResolution.OptionalArgument = candidate.OptionalArguments(paramIndex)
                    argument = defaultArgument.DefaultValue
                    diagnostics.AddDependencies(defaultArgument.Dependencies)
                    argumentIsDefaultValue = True
                    defaultArguments(paramIndex) = True
                    Debug.Assert(argument IsNot Nothing)
                    conversion = defaultArgument.Conversion

                    Dim argType = argument.Type
                    If argType IsNot Nothing Then
                        ' Report usesiteerror if it exists.
                        Dim useSiteInfo = argType.GetUseSiteInfo
                        ReportUseSite(diagnostics, argument.Syntax, useSiteInfo)
                    End If
                End If

                ' Arguments for properties are always passed with ByVal semantics. Even if
                ' parameter in metadata is defined ByRef, we always pass corresponding argument 
                ' through a temp without copy-back. Unlike with method calls, we rely on CodeGen
                ' to introduce the temp (easy to do since there is no copy-back around it),
                ' this allows us to keep the BoundPropertyAccess node simpler and allows to avoid
                ' A LOT of complexity in UseTwiceRewriter, which we would otherwise have around
                ' the temps.
                Debug.Assert(Not argumentIsDefaultValue OrElse argument.WasCompilerGenerated)
                Dim adjustedArgument As BoundExpression = PassArgument(argument, conversion, candidateIsAProperty, conversionBack, targetType, param, diagnostics)

                ' Keep SemanticModel happy.
                If argumentIsDefaultValue AndAlso adjustedArgument IsNot argument Then
                    adjustedArgument.SetWasCompilerGenerated()
                End If

                argumentsInOrder.Add(adjustedArgument)
            Next

            If paramArrayItems IsNot Nothing Then
                paramArrayItems.Free()
            End If

            parameterToArgumentMap.Free()
            Return (argumentsInOrder.ToImmutableAndFree(), defaultArguments)
        End Function

        Private Function PassArgument(
            argument As BoundExpression,
            conversionTo As KeyValuePair(Of ConversionKind, MethodSymbol),
            forceByValueSemantics As Boolean,
            conversionFrom As KeyValuePair(Of ConversionKind, MethodSymbol),
            targetType As TypeSymbol,
            param As ParameterSymbol,
            diagnostics As BindingDiagnosticBag
        ) As BoundExpression
            Debug.Assert(Not param.IsByRef OrElse param.IsExplicitByRef OrElse targetType.IsStringType())

            ' Non-string arguments for implicitly ByRef string parameters of Declare functions
            ' are passed through a temp without copy-back.
            If param.IsByRef AndAlso Not forceByValueSemantics AndAlso
               (param.IsExplicitByRef OrElse (argument.Type IsNot Nothing AndAlso argument.Type.IsStringType())) Then
                Return PassArgumentByRef(param.IsOut, argument, conversionTo, conversionFrom, targetType,
                                         param.Name, diagnostics)
            Else
                Return PassArgumentByVal(argument, conversionTo, targetType, diagnostics)
            End If
        End Function

        Private Function PassArgumentByRef(
            isOutParameter As Boolean,
            argument As BoundExpression,
            conversionTo As KeyValuePair(Of ConversionKind, MethodSymbol),
            conversionFrom As KeyValuePair(Of ConversionKind, MethodSymbol),
            targetType As TypeSymbol,
            parameterName As String,
            diagnostics As BindingDiagnosticBag
        ) As BoundExpression

#If DEBUG Then
            Dim checkAgainst As KeyValuePair(Of ConversionKind, MethodSymbol) = Conversions.ClassifyConversion(argument, targetType, Me, CompoundUseSiteInfo(Of AssemblySymbol).Discarded)
            Debug.Assert(conversionTo.Key = checkAgainst.Key)
            Debug.Assert(Equals(conversionTo.Value, checkAgainst.Value))
#End If

            ' TODO: Fields of MarshalByRef object are passed via temp.

            Dim isLValue As Boolean = argument.IsLValue()

            If isLValue AndAlso argument.Kind = BoundKind.PropertyAccess Then
                argument = argument.SetAccessKind(PropertyAccessKind.Get)
            End If

            If isLValue AndAlso Conversions.IsIdentityConversion(conversionTo.Key) Then
                'Nothing to do
                Debug.Assert(Conversions.IsIdentityConversion(conversionFrom.Key))
                Return argument

            ElseIf isLValue OrElse argument.IsSupportingAssignment() Then
                ' Need to allocate a temp of the target type,
                ' init it with argument's value,
                ' pass it ByRef,
                ' copy value back after the call.

                Dim inPlaceholder = New BoundByRefArgumentPlaceholder(argument.Syntax, isOutParameter, argument.Type, argument.HasErrors).MakeCompilerGenerated()
                Dim inConversion = CreateConversionAndReportDiagnostic(argument.Syntax,
                                                                       inPlaceholder,
                                                                       conversionTo,
                                                                       False, targetType, diagnostics)

                Dim outPlaceholder = New BoundRValuePlaceholder(argument.Syntax, targetType).MakeCompilerGenerated()
                Dim copyBackType = argument.GetTypeOfAssignmentTarget()

#If DEBUG Then
                checkAgainst = Conversions.ClassifyConversion(outPlaceholder, copyBackType, Me, CompoundUseSiteInfo(Of AssemblySymbol).Discarded)
                Debug.Assert(conversionFrom.Key = checkAgainst.Key)
                Debug.Assert(Equals(conversionFrom.Value, checkAgainst.Value))
#End If

                Dim outConversion = CreateConversionAndReportDiagnostic(argument.Syntax, outPlaceholder, conversionFrom,
                                                                      False, copyBackType, diagnostics,
                                                                      copybackConversionParamName:=parameterName).MakeCompilerGenerated()

                ' since we are going to assign to a latebound invocation
                ' force its arguments to be rvalues.
                If argument.Kind = BoundKind.LateInvocation Then
                    argument = MakeArgsRValues(DirectCast(argument, BoundLateInvocation), diagnostics)
                End If

                Dim copyBackExpression = BindAssignment(argument.Syntax, argument, outConversion, diagnostics)

                Debug.Assert(copyBackExpression.HasErrors OrElse
                             (copyBackExpression.Kind = BoundKind.AssignmentOperator AndAlso
                              DirectCast(copyBackExpression, BoundAssignmentOperator).Right Is outConversion))

                If Not isLValue Then
                    If argument.IsLateBound() Then
                        argument = argument.SetLateBoundAccessKind(LateBoundAccessKind.Get Or LateBoundAccessKind.Set)
                    Else
                        ' Diagnostics for PropertyAccessKind.Set case has been reported when we called BindAssignment.
                        WarnOnRecursiveAccess(argument, PropertyAccessKind.Get, diagnostics)
                        argument = argument.SetAccessKind(PropertyAccessKind.Get Or PropertyAccessKind.Set)
                    End If
                End If

                Return New BoundByRefArgumentWithCopyBack(argument.Syntax, argument,
                                                          inConversion, inPlaceholder,
                                                          outConversion, outPlaceholder,
                                                          targetType, copyBackExpression.HasErrors).MakeCompilerGenerated()
            Else
                Dim propertyAccess = TryCast(argument, BoundPropertyAccess)

                If propertyAccess IsNot Nothing AndAlso propertyAccess.AccessKind <> PropertyAccessKind.Get AndAlso
                   propertyAccess.PropertySymbol.SetMethod?.IsInitOnly Then

                    Debug.Assert(Not propertyAccess.IsWriteable) ' Used to be writable prior to VB 16.9, which caused a use-site error while binding an assignment above.
                    InternalSyntax.Parser.CheckFeatureAvailability(diagnostics,
                                                                   argument.Syntax.Location,
                                                                   DirectCast(argument.Syntax.SyntaxTree.Options, VisualBasicParseOptions).LanguageVersion,
                                                                   InternalSyntax.Feature.InitOnlySettersUsage)
                End If

                ' Need to allocate a temp of the target type,
                ' init it with argument's value,
                ' pass it ByRef. Code gen will do this.
                Return PassArgumentByVal(argument, conversionTo, targetType, diagnostics)
            End If
        End Function

        ' when latebound invocation acts as an LHS in an assignment
        ' its arguments are always passed ByVal since property parameters 
        ' are always treated as ByVal
        ' This method is used to force the arguments to be RValues
        Private Function MakeArgsRValues(ByVal invocation As BoundLateInvocation,
                                                  diagnostics As BindingDiagnosticBag) As BoundLateInvocation

            Dim args = invocation.ArgumentsOpt

            If Not args.IsEmpty Then
                Dim argBuilder As ArrayBuilder(Of BoundExpression) = Nothing

                For i As Integer = 0 To args.Length - 1
                    Dim arg = args(i)
                    Dim newArg = MakeRValue(arg, diagnostics)

                    If argBuilder Is Nothing AndAlso arg IsNot newArg Then
                        argBuilder = ArrayBuilder(Of BoundExpression).GetInstance
                        argBuilder.AddRange(args, i)
                    End If

                    If argBuilder IsNot Nothing Then
                        argBuilder.Add(newArg)
                    End If
                Next

                If argBuilder IsNot Nothing Then
                    invocation = invocation.Update(invocation.Member,
                                                    argBuilder.ToImmutableAndFree,
                                                    invocation.ArgumentNamesOpt,
                                                    invocation.AccessKind,
                                                    invocation.MethodOrPropertyGroupOpt,
                                                    invocation.Type)

                End If
            End If
            Return invocation
        End Function

        Friend Function PassArgumentByVal(
            argument As BoundExpression,
            conversion As KeyValuePair(Of ConversionKind, MethodSymbol),
            targetType As TypeSymbol,
            diagnostics As BindingDiagnosticBag
        ) As BoundExpression
#If DEBUG Then
            Dim checkAgainst As KeyValuePair(Of ConversionKind, MethodSymbol) = Conversions.ClassifyConversion(argument, targetType, Me, CompoundUseSiteInfo(Of AssemblySymbol).Discarded)
            Debug.Assert(conversion.Key = checkAgainst.Key)
            Debug.Assert(Equals(conversion.Value, checkAgainst.Value))
#End If

            argument = CreateConversionAndReportDiagnostic(argument.Syntax, argument, conversion, False, targetType, diagnostics)

            Debug.Assert(Not argument.IsLValue)
            Return argument
        End Function

        ' Given a list of arguments, create arrays of the bound arguments and the names of those arguments.
        Private Sub BindArgumentsAndNames(
            argumentListOpt As ArgumentListSyntax,
            ByRef boundArguments As ImmutableArray(Of BoundExpression),
            ByRef argumentNames As ImmutableArray(Of String),
            ByRef argumentNamesLocations As ImmutableArray(Of Location),
            diagnostics As BindingDiagnosticBag
        )
            Dim args As ImmutableArray(Of ArgumentSyntax) = Nothing

            If argumentListOpt IsNot Nothing Then
                Dim arguments = argumentListOpt.Arguments

                Dim argsArr(arguments.Count - 1) As ArgumentSyntax
                For i = 0 To argsArr.Length - 1
                    argsArr(i) = arguments(i)
                Next

                args = argsArr.AsImmutableOrNull
            End If

            BindArgumentsAndNames(
                args,
                boundArguments,
                argumentNames,
                argumentNamesLocations,
                diagnostics
            )
        End Sub

        ' Given a list of arguments, create arrays of the bound arguments and the names of those arguments.
        Private Sub BindArgumentsAndNames(
            arguments As ImmutableArray(Of ArgumentSyntax),
            ByRef boundArguments As ImmutableArray(Of BoundExpression),
            ByRef argumentNames As ImmutableArray(Of String),
            ByRef argumentNamesLocations As ImmutableArray(Of Location),
            diagnostics As BindingDiagnosticBag
        )

            ' With SeparatedSyntaxList, it is most efficient to iterate with foreach and not to access Count.

            If arguments.IsDefaultOrEmpty Then
                boundArguments = s_noArguments
                argumentNames = Nothing
                argumentNamesLocations = Nothing
            Else

                Dim boundArgumentsBuilder As ArrayBuilder(Of BoundExpression) = ArrayBuilder(Of BoundExpression).GetInstance
                Dim argumentNamesBuilder As ArrayBuilder(Of String) = Nothing
                Dim argumentNamesLocationsBuilder As ArrayBuilder(Of Location) = Nothing
                Dim argCount As Integer = 0
                Dim argumentSyntax As ArgumentSyntax

                For Each argumentSyntax In arguments
                    Select Case argumentSyntax.Kind
                        Case SyntaxKind.SimpleArgument
                            Dim simpleArgument = DirectCast(argumentSyntax, SimpleArgumentSyntax)
                            boundArgumentsBuilder.Add(BindValue(simpleArgument.Expression, diagnostics))

                            If simpleArgument.IsNamed Then
                                ' The common case is no named arguments. So we defer all work until the first named argument is seen.
                                If argumentNamesBuilder Is Nothing Then
                                    argumentNamesBuilder = ArrayBuilder(Of String).GetInstance()
                                    argumentNamesLocationsBuilder = ArrayBuilder(Of Location).GetInstance()

                                    For i = 0 To argCount - 1
                                        argumentNamesBuilder.Add(Nothing)
                                        argumentNamesLocationsBuilder.Add(Nothing)
                                    Next i
                                End If

                                Dim id = simpleArgument.NameColonEquals.Name.Identifier
                                If id.ValueText.Length > 0 Then
                                    argumentNamesBuilder.Add(id.ValueText)
                                Else
                                    argumentNamesBuilder.Add(Nothing)
                                End If

                                argumentNamesLocationsBuilder.Add(id.GetLocation())
                            ElseIf argumentNamesBuilder IsNot Nothing Then
                                argumentNamesBuilder.Add(Nothing)
                                argumentNamesLocationsBuilder.Add(Nothing)
                            End If

                        Case SyntaxKind.OmittedArgument
                            boundArgumentsBuilder.Add(New BoundOmittedArgument(argumentSyntax, Nothing))
                            If argumentNamesBuilder IsNot Nothing Then
                                argumentNamesBuilder.Add(Nothing)
                                argumentNamesLocationsBuilder.Add(Nothing)
                            End If

                        Case SyntaxKind.RangeArgument
                            ' NOTE: Redim statement supports range argument, like: Redim x(0 To 3)(0 To 6)
                            '       This behavior is misleading, because the 'range' (0 To 3) is actually 
                            '       being ignored and only upper bound is being used.
                            ' TODO: revise (add warning/error?)
                            Dim rangeArgument = DirectCast(argumentSyntax, RangeArgumentSyntax)
                            CheckRangeArgumentLowerBound(rangeArgument, diagnostics)
                            boundArgumentsBuilder.Add(BindValue(rangeArgument.UpperBound, diagnostics))
                            If argumentNamesBuilder IsNot Nothing Then
                                argumentNamesBuilder.Add(Nothing)
                                argumentNamesLocationsBuilder.Add(Nothing)
                            End If

                        Case Else
                            Throw ExceptionUtilities.UnexpectedValue(argumentSyntax.Kind)

                    End Select

                    argCount += 1
                Next

                boundArguments = boundArgumentsBuilder.ToImmutableAndFree
                argumentNames = If(argumentNamesBuilder Is Nothing, Nothing, argumentNamesBuilder.ToImmutableAndFree)
                argumentNamesLocations = If(argumentNamesLocationsBuilder Is Nothing, Nothing, argumentNamesLocationsBuilder.ToImmutableAndFree)
            End If

        End Sub

        Friend Function GetArgumentForParameterDefaultValue(param As ParameterSymbol,
                                                            syntax As SyntaxNode,
                                                            diagnostics As BindingDiagnosticBag,
                                                            callerInfoOpt As SyntaxNode,
                                                            parameterToArgumentMap As ArrayBuilder(Of Integer),
                                                            arguments As ImmutableArray(Of BoundExpression),
                                                            reducedExtensionReceiverOpt As BoundExpression) As BoundExpression
            Dim defaultArgument As BoundExpression = Nothing

            ' See Section 3 of §11.8.2 Applicable Methods
            ' Deal with Optional arguments. HasDefaultValue is true if the parameter is optional and has a default value.
            Dim defaultConstantValue As ConstantValue = If(param.IsOptional, param.ExplicitDefaultConstantValue(DefaultParametersInProgress), Nothing)
            If defaultConstantValue IsNot Nothing Then

                If callerInfoOpt IsNot Nothing AndAlso
                   callerInfoOpt.SyntaxTree IsNot Nothing AndAlso
                   Not callerInfoOpt.SyntaxTree.IsEmbeddedOrMyTemplateTree() AndAlso
                   Not SuppressCallerInfo Then

                    Dim isCallerLineNumber As Boolean = param.IsCallerLineNumber
                    Dim isCallerMemberName As Boolean = param.IsCallerMemberName
                    Dim isCallerFilePath As Boolean = param.IsCallerFilePath
                    Dim callerArgumentExpressionParameterIndex As Integer = param.CallerArgumentExpressionParameterIndex

                    Dim isCallerArgumentExpression = callerArgumentExpressionParameterIndex > -1 OrElse (reducedExtensionReceiverOpt IsNot Nothing AndAlso callerArgumentExpressionParameterIndex > -2)

                    If isCallerLineNumber OrElse isCallerMemberName OrElse isCallerFilePath OrElse isCallerArgumentExpression Then
                        Dim callerInfoValue As ConstantValue = Nothing

                        If isCallerLineNumber Then
                            callerInfoValue = ConstantValue.Create(callerInfoOpt.SyntaxTree.GetDisplayLineNumber(GetCallerLocation(callerInfoOpt)))
                        ElseIf isCallerMemberName Then
                            Dim container As Symbol = ContainingMember

                            While container IsNot Nothing
                                Select Case container.Kind
                                    Case SymbolKind.Field, SymbolKind.Property, SymbolKind.Event
                                        Exit While

                                    Case SymbolKind.Method
                                        If container.IsLambdaMethod Then
                                            container = container.ContainingSymbol
                                        Else
                                            Dim propertyOrEvent As Symbol = DirectCast(container, MethodSymbol).AssociatedSymbol

                                            If propertyOrEvent IsNot Nothing Then
                                                container = propertyOrEvent
                                            End If

                                            Exit While
                                        End If

                                    Case Else
                                        container = container.ContainingSymbol
                                End Select
                            End While

                            If container IsNot Nothing AndAlso container.Name IsNot Nothing Then
                                callerInfoValue = ConstantValue.Create(container.Name)
                            End If
                        ElseIf isCallerFilePath Then
                            callerInfoValue = ConstantValue.Create(callerInfoOpt.SyntaxTree.GetDisplayPath(callerInfoOpt.Span, Me.Compilation.Options.SourceReferenceResolver))
                        Else
                            Debug.Assert(callerArgumentExpressionParameterIndex > -1 OrElse (reducedExtensionReceiverOpt IsNot Nothing AndAlso callerArgumentExpressionParameterIndex > -2))

                            Dim argumentSyntax As SyntaxNode = Nothing
                            If callerArgumentExpressionParameterIndex = -1 Then
                                argumentSyntax = reducedExtensionReceiverOpt.Syntax
                            Else
                                Dim argumentIndex = parameterToArgumentMap(callerArgumentExpressionParameterIndex)
                                Debug.Assert(argumentIndex < arguments.Length)
                                If argumentIndex > -1 Then
                                    argumentSyntax = arguments(argumentIndex).Syntax
                                End If
                            End If

                            If argumentSyntax IsNot Nothing Then
                                callerInfoValue = ConstantValue.Create(argumentSyntax.ToString())
                            End If
                        End If

                        If callerInfoValue IsNot Nothing Then
                            ' Use the value only if it will not cause errors.
                            Dim ignoreDiagnostics = BindingDiagnosticBag.GetInstance(withDiagnostics:=True, withDependencies:=False)
                            Dim literal As BoundLiteral

                            If callerInfoValue.Discriminator = ConstantValueTypeDiscriminator.Int32 Then
                                literal = New BoundLiteral(syntax, callerInfoValue, GetSpecialType(SpecialType.System_Int32, syntax, ignoreDiagnostics))
                            Else
                                Debug.Assert(callerInfoValue.Discriminator = ConstantValueTypeDiscriminator.String)
                                literal = New BoundLiteral(syntax, callerInfoValue, GetSpecialType(SpecialType.System_String, syntax, ignoreDiagnostics))
                            End If

                            Dim convertedValue As BoundExpression = ApplyImplicitConversion(syntax, param.Type, literal, ignoreDiagnostics)

                            If Not convertedValue.HasErrors AndAlso Not ignoreDiagnostics.HasAnyErrors Then
                                ' Dev11 #248795: Caller info should be omitted if user defined conversion is involved.
                                If Not (convertedValue.Kind = BoundKind.Conversion AndAlso (DirectCast(convertedValue, BoundConversion).ConversionKind And ConversionKind.UserDefined) <> 0) Then
                                    defaultConstantValue = callerInfoValue
                                End If
                            End If

                            ignoreDiagnostics.Free()
                        End If
                    End If
                End If

                ' For compatibility with the native compiler bad metadata constants should be treated as default(T).  This 
                ' is a possible outcome of running an obfuscator over a valid DLL 
                If defaultConstantValue.IsBad Then
                    defaultConstantValue = ConstantValue.Null
                End If

                Dim defaultSpecialType = defaultConstantValue.SpecialType
                Dim defaultArgumentType As TypeSymbol = Nothing

                ' Constant has a type.
                Dim paramNullableUnderlyingTypeOrSelf As TypeSymbol = param.Type.GetNullableUnderlyingTypeOrSelf()

                If param.HasOptionCompare Then

                    ' If the argument has the OptionCompareAttribute
                    ' then use the setting for Option Compare [Binary|Text]
                    ' Other languages will use the default value specified.

                    If Me.OptionCompareText Then
                        defaultConstantValue = ConstantValue.Create(1)
                    Else
                        defaultConstantValue = ConstantValue.Default(SpecialType.System_Int32)
                    End If

                    If paramNullableUnderlyingTypeOrSelf.GetEnumUnderlyingTypeOrSelf().SpecialType = SpecialType.System_Int32 Then
                        defaultArgumentType = paramNullableUnderlyingTypeOrSelf
                    Else
                        defaultArgumentType = GetSpecialType(SpecialType.System_Int32, syntax, diagnostics)
                    End If

                ElseIf defaultSpecialType <> SpecialType.None Then
                    If paramNullableUnderlyingTypeOrSelf.GetEnumUnderlyingTypeOrSelf().SpecialType = defaultSpecialType Then
                        ' Enum default values are encoded as the underlying primitive type.  If the underlying types match then
                        ' use the parameter's enum type.
                        defaultArgumentType = paramNullableUnderlyingTypeOrSelf
                    Else
                        'Use the primitive type.
                        defaultArgumentType = GetSpecialType(defaultSpecialType, syntax, diagnostics)
                    End If
                Else
                    ' No type in constant.  Constant should be nothing
                    Debug.Assert(defaultConstantValue.IsNothing)
                End If

                defaultArgument = New BoundLiteral(syntax, defaultConstantValue, defaultArgumentType)

            ElseIf param.IsOptional Then

                ' Handle optional object type argument when no default value is specified.
                ' Section 3 of §11.8.2 Applicable Methods

                If param.Type.SpecialType = SpecialType.System_Object Then

                    Dim methodSymbol As MethodSymbol = Nothing
                    If param.IsMarshalAsObject Then
                        ' Nothing
                        defaultArgument = New BoundLiteral(syntax, ConstantValue.Null, Nothing)
                    ElseIf param.IsIDispatchConstant Then
                        ' new DispatchWrapper(nothing)
                        methodSymbol = DirectCast(GetWellKnownTypeMember(WellKnownMember.System_Runtime_InteropServices_DispatchWrapper__ctor, syntax, diagnostics), MethodSymbol)
                    ElseIf param.IsIUnknownConstant Then
                        ' new UnknownWrapper(nothing)
                        methodSymbol = DirectCast(GetWellKnownTypeMember(WellKnownMember.System_Runtime_InteropServices_UnknownWrapper__ctor, syntax, diagnostics), MethodSymbol)
                    Else
                        defaultArgument = New BoundOmittedArgument(syntax, param.Type)
                    End If

                    If methodSymbol IsNot Nothing Then
                        Dim argument = New BoundLiteral(syntax, ConstantValue.Null, param.Type).MakeCompilerGenerated()
                        defaultArgument = New BoundObjectCreationExpression(syntax, methodSymbol,
                                                                            ImmutableArray.Create(Of BoundExpression)(argument),
                                                                            Nothing,
                                                                            methodSymbol.ContainingType)
                    End If

                Else
                    defaultArgument = New BoundLiteral(syntax, ConstantValue.Null, Nothing)
                End If

            End If

            Return defaultArgument?.MakeCompilerGenerated()
        End Function

        Private Shared Function GetCallerLocation(syntax As SyntaxNode) As TextSpan
            Select Case syntax.Kind
                Case SyntaxKind.SimpleMemberAccessExpression
                    Return DirectCast(syntax, MemberAccessExpressionSyntax).Name.Span
                Case SyntaxKind.DictionaryAccessExpression
                    Return DirectCast(syntax, MemberAccessExpressionSyntax).OperatorToken.Span
                Case Else
                    Return syntax.Span
            End Select
        End Function

        ''' <summary>
        ''' Return true if the node is an immediate child of a call statement.
        ''' </summary>
        Private Shared Function IsCallStatementContext(node As InvocationExpressionSyntax) As Boolean
            Dim parent As VisualBasicSyntaxNode = node.Parent

            ' Dig through conditional access
            If parent IsNot Nothing AndAlso parent.Kind = SyntaxKind.ConditionalAccessExpression Then
                Dim conditional = DirectCast(parent, ConditionalAccessExpressionSyntax)

                If conditional.WhenNotNull Is node Then
                    parent = conditional.Parent
                End If
            End If

            Return parent IsNot Nothing AndAlso (parent.Kind = SyntaxKind.CallStatement OrElse parent.Kind = SyntaxKind.ExpressionStatement)
        End Function

    End Class

End Namespace