File: Binding\Binder_Invocation.vb
Web Access
Project: src\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(KeyValuePairUtil.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(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