Exemplo n.º 1
0
        public static BoundCall ErrorCall(
            CSharpSyntaxNode node,
            BoundExpression receiverOpt,
            MethodSymbol method,
            ImmutableArray <BoundExpression> arguments,
            ImmutableArray <string> namedArguments,
            ImmutableArray <RefKind> refKinds,
            bool isDelegateCall,
            bool invokedAsExtensionMethod,
            ImmutableArray <MethodSymbol> originalMethods,
            LookupResultKind resultKind)
        {
            if (!originalMethods.IsEmpty)
            {
                resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
            }

            Debug.Assert(arguments.IsDefaultOrEmpty || (object)receiverOpt != (object)arguments[0]);

            var call = new BoundCall(node, receiverOpt, method, arguments, namedArguments,
                                     refKinds, isDelegateCall: isDelegateCall, expanded: false, invokedAsExtensionMethod: invokedAsExtensionMethod, argsToParamsOpt: default(ImmutableArray <int>),
                                     resultKind: resultKind, type: method.ReturnType, hasErrors: true);

            call.OriginalMethodsOpt = originalMethods;
            return(call);
        }
Exemplo n.º 2
0
        public static BoundCall ErrorCall(
            SyntaxNode node,
            BoundExpression receiverOpt,
            MethodSymbol method,
            ImmutableArray <BoundExpression> arguments,
            ImmutableArray <string> namedArguments,
            ImmutableArray <RefKind> refKinds,
            bool isDelegateCall,
            bool invokedAsExtensionMethod,
            ImmutableArray <MethodSymbol> originalMethods,
            LookupResultKind resultKind,
            Binder binder
            )
        {
            if (!originalMethods.IsEmpty)
            {
                resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
            }

            Debug.Assert(arguments.IsDefaultOrEmpty || (object)receiverOpt != (object)arguments[0]);

            return(new BoundCall(
                       syntax: node,
                       receiverOpt: binder.BindToTypeForErrorRecovery(receiverOpt),
                       method: method,
                       arguments: arguments.SelectAsArray(
                           (e, binder) => binder.BindToTypeForErrorRecovery(e),
                           binder
                           ),
                       argumentNamesOpt: namedArguments,
                       argumentRefKindsOpt: refKinds,
                       isDelegateCall: isDelegateCall,
                       expanded: false,
                       invokedAsExtensionMethod: invokedAsExtensionMethod,
                       argsToParamsOpt: default(ImmutableArray <int>),
                       defaultArguments: default(BitVector),
                       resultKind: resultKind,
                       originalMethodsOpt: originalMethods,
                       type: method.ReturnType,
                       hasErrors: true
                       ));
        }
Exemplo n.º 3
0
        public static BoundCall ErrorCall(
            CSharpSyntaxNode node,
            BoundExpression receiverOpt,
            MethodSymbol method,
            ImmutableArray<BoundExpression> arguments,
            ImmutableArray<string> namedArguments,
            ImmutableArray<RefKind> refKinds,
            bool isDelegateCall,
            bool invokedAsExtensionMethod,
            ImmutableArray<MethodSymbol> originalMethods,
            LookupResultKind resultKind)
        {
            if (!originalMethods.IsEmpty)
                resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);

            var call = new BoundCall(node, receiverOpt, method, arguments, namedArguments,
                refKinds, isDelegateCall: isDelegateCall, expanded: false, invokedAsExtensionMethod: invokedAsExtensionMethod, argsToParamsOpt: default(ImmutableArray<int>),
                resultKind: resultKind, type: method.ReturnType, hasErrors: true);
            call.OriginalMethodsOpt = originalMethods;
            return call;
        }
Exemplo n.º 4
0
        protected virtual MethodSymbol BindAttributeConstructor(
            AttributeSyntax node,
            NamedTypeSymbol attributeType,
            AnalyzedArguments boundConstructorArguments,
            DiagnosticBag diagnostics,
            ref LookupResultKind resultKind,
            bool suppressErrors,
            ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            MemberResolutionResult<MethodSymbol> memberResolutionResult;
            ImmutableArray<MethodSymbol> candidateConstructors;
            if (!TryPerformConstructorOverloadResolution(
                attributeType,
                boundConstructorArguments,
                attributeType.Name,
                node.Location,
                suppressErrors, //don't cascade in these cases
                diagnostics,
                out memberResolutionResult,
                out candidateConstructors,
                allowProtectedConstructorsOfBaseType: true))
            {
                resultKind = resultKind.WorseResultKind(
                    memberResolutionResult.IsValid && !IsConstructorAccessible(memberResolutionResult.Member, ref useSiteDiagnostics) ?
                        LookupResultKind.Inaccessible :
                        LookupResultKind.OverloadResolutionFailure);
            }

            return memberResolutionResult.Member;
        }
Exemplo n.º 5
0
        // Get the symbols and possible method group associated with a method group bound node, as
        // they should be exposed through GetSemanticInfo.
        // NB: It is not safe to pass a null binderOpt during speculative binding.
        // 
        // If the parent node of the method group syntax node provides information (such as arguments) 
        // that allows us to return more specific symbols (a specific overload or applicable candidates)
        // we return these. The complete set of symbols of the method group is then returned in methodGroup parameter.
        private ImmutableArray<Symbol> GetMethodGroupSemanticSymbols(
            BoundMethodGroup boundNode,
            BoundNode boundNodeForSyntacticParent,
            Binder binderOpt,
            out LookupResultKind resultKind,
            out bool isDynamic,
            out ImmutableArray<Symbol> methodGroup)
        {
            Debug.Assert(binderOpt != null || IsInTree(boundNode.Syntax));

            ImmutableArray<Symbol> symbols = ImmutableArray<Symbol>.Empty;

            resultKind = boundNode.ResultKind;
            if (resultKind == LookupResultKind.Empty)
            {
                resultKind = LookupResultKind.Viable;
            }

            isDynamic = false;

            // The method group needs filtering.
            Binder binder = binderOpt ?? GetEnclosingBinder(GetAdjustedNodePosition(boundNode.Syntax));
            methodGroup = GetReducedAndFilteredMethodGroupSymbols(binder, boundNode).Cast<MethodSymbol, Symbol>();

            // We want to get the actual node chosen by overload resolution, if possible. 
            if (boundNodeForSyntacticParent != null)
            {
                switch (boundNodeForSyntacticParent.Kind)
                {
                    case BoundKind.Call:
                        // If we are looking for info on M in M(args), we want the symbol that overload resolution
                        // chose for M.
                        var call = (BoundCall)boundNodeForSyntacticParent;
                        InvocationExpressionSyntax invocation = call.Syntax as InvocationExpressionSyntax;
                        if (invocation != null && invocation.Expression.SkipParens() == boundNode.Syntax.SkipParens() && (object)call.Method != null)
                        {
                            if (call.OriginalMethodsOpt.IsDefault)
                            {
                                // Overload resolution succeeded.
                                symbols = CreateReducedExtensionMethodIfPossible(call);
                                resultKind = LookupResultKind.Viable;
                            }
                            else
                            {
                                resultKind = call.ResultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
                                symbols = StaticCast<Symbol>.From(CreateReducedExtensionMethodsFromOriginalsIfNecessary(call));
                            }
                        }
                        break;

                    case BoundKind.DelegateCreationExpression:
                        // If we are looking for info on "M" in "new Action(M)" 
                        // we want to get the symbol that overload resolution chose for M, not the whole method group M.
                        var delegateCreation = (BoundDelegateCreationExpression)boundNodeForSyntacticParent;
                        if (delegateCreation.Argument == boundNode && (object)delegateCreation.MethodOpt != null)
                        {
                            symbols = CreateReducedExtensionMethodIfPossible(delegateCreation, boundNode.ReceiverOpt);
                        }
                        break;

                    case BoundKind.Conversion:
                        // If we are looking for info on "M" in "(Action)M" 
                        // we want to get the symbol that overload resolution chose for M, not the whole method group M.
                        var conversion = (BoundConversion)boundNodeForSyntacticParent;

                        var method = conversion.SymbolOpt;
                        if ((object)method != null)
                        {
                            Debug.Assert(conversion.ConversionKind == ConversionKind.MethodGroup);

                            if (conversion.IsExtensionMethod)
                            {
                                method = ReducedExtensionMethodSymbol.Create(method);
                            }

                            symbols = ImmutableArray.Create((Symbol)method);
                            resultKind = conversion.ResultKind;
                        }
                        else
                        {
                            goto default;
                        }

                        break;

                    case BoundKind.DynamicInvocation:
                        var dynamicInvocation = (BoundDynamicInvocation)boundNodeForSyntacticParent;
                        symbols = dynamicInvocation.ApplicableMethods.Cast<MethodSymbol, Symbol>();
                        isDynamic = true;
                        break;

                    case BoundKind.BadExpression:
                        // If the bad expression has symbol(s) from this method group, it better indicates any problems.
                        ImmutableArray<Symbol> myMethodGroup = methodGroup;

                        symbols = ((BoundBadExpression)boundNodeForSyntacticParent).Symbols.WhereAsArray(sym => myMethodGroup.Contains(sym));
                        if (symbols.Any())
                        {
                            resultKind = ((BoundBadExpression)boundNodeForSyntacticParent).ResultKind;
                        }
                        break;

                    case BoundKind.NameOfOperator:
                        symbols = methodGroup;
                        resultKind = resultKind.WorseResultKind(LookupResultKind.MemberGroup);
                        break;

                    default:
                        symbols = methodGroup;
                        if (symbols.Length > 0)
                        {
                            resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
                        }
                        break;
                }
            }
            else if (methodGroup.Length == 1 && !boundNode.HasAnyErrors)
            {
                // During speculative binding, there won't be a parent bound node. The parent bound
                // node may also be absent if the syntactic parent has errors or if one is simply
                // not specified (see SemanticModel.GetSymbolInfoForNode). However, if there's exactly
                // one candidate, then we should probably succeed.

                symbols = methodGroup;
                if (symbols.Length > 0)
                {
                    resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
                }
            }

            if (!symbols.Any())
            {
                // If we didn't find a better set of symbols, then assume this is a method group that didn't
                // get resolved. Return all members of the method group, with a resultKind of OverloadResolutionFailure
                // (unless the method group already has a worse result kind).
                symbols = methodGroup;
                if (!isDynamic && resultKind > LookupResultKind.OverloadResolutionFailure)
                {
                    resultKind = LookupResultKind.OverloadResolutionFailure;
                }
            }

            return symbols;
        }
Exemplo n.º 6
0
        private void AdjustSymbolsForObjectCreation(
            BoundNode lowestBoundNode,
            NamedTypeSymbol typeSymbolOpt,
            MethodSymbol constructorOpt,
            Binder binderOpt,
            ref LookupResultKind resultKind,
            ref ImmutableArray<Symbol> symbols,
            ref ImmutableArray<Symbol> memberGroup)
        {
            Debug.Assert(lowestBoundNode != null);
            Debug.Assert(binderOpt != null || IsInTree(lowestBoundNode.Syntax));

            if ((object)typeSymbolOpt != null)
            {
                Debug.Assert(lowestBoundNode.Syntax != null);

                // Filter typeSymbol's instance constructors by accessibility.
                // If all the instance constructors are inaccessible, we retain
                // all of them for correct semantic info.
                Binder binder = binderOpt ?? GetEnclosingBinder(GetAdjustedNodePosition(lowestBoundNode.Syntax));
                ImmutableArray<MethodSymbol> candidateConstructors;

                if (binder != null)
                {
                    var instanceConstructors = typeSymbolOpt.IsInterfaceType() && (object)typeSymbolOpt.ComImportCoClass != null ?
                        typeSymbolOpt.ComImportCoClass.InstanceConstructors :
                        typeSymbolOpt.InstanceConstructors;

                    HashSet<DiagnosticInfo> useSiteDiagnostics = null;
                    candidateConstructors = binder.FilterInaccessibleConstructors(instanceConstructors, allowProtectedConstructorsOfBaseType: false, useSiteDiagnostics: ref useSiteDiagnostics);

                    if ((object)constructorOpt == null ? !candidateConstructors.Any() : !candidateConstructors.Contains(constructorOpt))
                    {
                        // All instance constructors are inaccessible or if the specified constructor
                        // isn't a candidate, then we retain all of them for correct semantic info.
                        Debug.Assert(resultKind != LookupResultKind.Viable);
                        candidateConstructors = instanceConstructors;
                    }
                }
                else
                {
                    candidateConstructors = ImmutableArray<MethodSymbol>.Empty;
                }

                if ((object)constructorOpt != null)
                {
                    Debug.Assert(candidateConstructors.Contains(constructorOpt));
                    symbols = ImmutableArray.Create<Symbol>(constructorOpt);
                }
                else if (candidateConstructors.Length > 0)
                {
                    symbols = StaticCast<Symbol>.From(candidateConstructors);
                    Debug.Assert(resultKind != LookupResultKind.Viable);
                    resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
                }

                memberGroup = candidateConstructors.Cast<MethodSymbol, Symbol>();
            }
        }
Exemplo n.º 7
0
        // In cases where we are binding C in "[C(...)]", the bound nodes return the symbol for the type. However, we've
        // decided that we want this case to return the constructor of the type instead. This affects attributes. 
        // This method checks for this situation and adjusts the syntax and method or property group.
        private void AdjustSymbolsForObjectCreation(BoundExpression boundNode,
                                                    BoundNode boundNodeForSyntacticParent,
                                                    Binder binderOpt,
                                                    ref LookupResultKind resultKind,
                                                    ref ImmutableArray<Symbol> symbols,
                                                    ref ImmutableArray<Symbol> memberGroup)
        {
            NamedTypeSymbol typeSymbol = null;
            MethodSymbol constructor = null;

            // Check if boundNode.Syntax is the type-name child of an Attribute.
            CSharpSyntaxNode parentSyntax = boundNodeForSyntacticParent.Syntax;
            if (parentSyntax != null &&
                parentSyntax == boundNode.Syntax.Parent &&
                parentSyntax.Kind() == SyntaxKind.Attribute && ((AttributeSyntax)parentSyntax).Name == boundNode.Syntax)
            {
                var unwrappedSymbols = UnwrapAliases(symbols);

                switch (boundNodeForSyntacticParent.Kind)
                {
                    case BoundKind.Attribute:
                        BoundAttribute boundAttribute = (BoundAttribute)boundNodeForSyntacticParent;

                        if (unwrappedSymbols.Length == 1 && unwrappedSymbols[0].Kind == SymbolKind.NamedType)
                        {
                            Debug.Assert(resultKind != LookupResultKind.Viable || unwrappedSymbols[0] == boundAttribute.Type.GetNonErrorGuess());

                            typeSymbol = (NamedTypeSymbol)unwrappedSymbols[0];
                            constructor = boundAttribute.Constructor;
                            resultKind = resultKind.WorseResultKind(boundAttribute.ResultKind);
                        }
                        break;

                    case BoundKind.BadExpression:
                        BoundBadExpression boundBadExpression = (BoundBadExpression)boundNodeForSyntacticParent;
                        if (unwrappedSymbols.Length == 1)
                        {
                            resultKind = resultKind.WorseResultKind(boundBadExpression.ResultKind);
                            typeSymbol = unwrappedSymbols[0] as NamedTypeSymbol;
                        }
                        break;

                    default:
                        throw ExceptionUtilities.UnexpectedValue(boundNodeForSyntacticParent.Kind);
                }

                AdjustSymbolsForObjectCreation(boundNode, typeSymbol, constructor, binderOpt, ref resultKind, ref symbols, ref memberGroup);
            }
        }
Exemplo n.º 8
0
        // Get the symbols and possible method or property group associated with a bound node, as
        // they should be exposed through GetSemanticInfo.
        // NB: It is not safe to pass a null binderOpt during speculative binding.
        private ImmutableArray<Symbol> GetSemanticSymbols(BoundExpression boundNode,
            BoundNode boundNodeForSyntacticParent,
            Binder binderOpt,
            SymbolInfoOptions options,
            out bool isDynamic,
            out LookupResultKind resultKind,
            out ImmutableArray<Symbol> memberGroup)
        {
            memberGroup = ImmutableArray<Symbol>.Empty;
            ImmutableArray<Symbol> symbols = ImmutableArray<Symbol>.Empty;
            resultKind = LookupResultKind.Viable;
            isDynamic = false;

            switch (boundNode.Kind)
            {
                case BoundKind.MethodGroup:
                    symbols = GetMethodGroupSemanticSymbols((BoundMethodGroup)boundNode, boundNodeForSyntacticParent, binderOpt, out resultKind, out isDynamic, out memberGroup);
                    break;

                case BoundKind.PropertyGroup:
                    symbols = GetPropertyGroupSemanticSymbols((BoundPropertyGroup)boundNode, boundNodeForSyntacticParent, binderOpt, out resultKind, out memberGroup);
                    break;

                case BoundKind.BadExpression:
                    {
                        var expr = (BoundBadExpression)boundNode;
                        resultKind = expr.ResultKind;

                        if (expr.Syntax.Kind() == SyntaxKind.ObjectCreationExpression)
                        {
                            if (resultKind == LookupResultKind.NotCreatable)
                            {
                                return expr.Symbols;
                            }
                            else if (expr.Type.IsDelegateType())
                            {
                                resultKind = LookupResultKind.Empty;
                                return symbols;
                            }

                            memberGroup = expr.Symbols;
                        }

                        return expr.Symbols;
                    }

                case BoundKind.DelegateCreationExpression:
                    break;

                case BoundKind.TypeExpression:
                    {
                        var boundType = (BoundTypeExpression)boundNode;

                        // Watch out for not creatable types within object creation syntax
                        if (boundNodeForSyntacticParent != null &&
                           boundNodeForSyntacticParent.Syntax.Kind() == SyntaxKind.ObjectCreationExpression &&
                           ((ObjectCreationExpressionSyntax)boundNodeForSyntacticParent.Syntax).Type == boundType.Syntax &&
                           boundNodeForSyntacticParent.Kind == BoundKind.BadExpression &&
                           ((BoundBadExpression)boundNodeForSyntacticParent).ResultKind == LookupResultKind.NotCreatable)
                        {
                            resultKind = LookupResultKind.NotCreatable;
                        }

                        // could be a type or alias.
                        var typeSymbol = boundType.AliasOpt ?? (Symbol)boundType.Type;

                        var originalErrorType = typeSymbol.OriginalDefinition as ErrorTypeSymbol;
                        if ((object)originalErrorType != null)
                        {
                            resultKind = originalErrorType.ResultKind;
                            symbols = originalErrorType.CandidateSymbols;
                        }
                        else
                        {
                            symbols = ImmutableArray.Create<Symbol>(typeSymbol);
                        }
                    }
                    break;

                case BoundKind.TypeOrValueExpression:
                    {
                        // If we're seeing a node of this kind, then we failed to resolve the member access
                        // as either a type or a property/field/event/local/parameter.  In such cases,
                        // the second interpretation applies so just visit the node for that.
                        BoundExpression valueExpression = ((BoundTypeOrValueExpression)boundNode).Data.ValueExpression;
                        return GetSemanticSymbols(valueExpression, boundNodeForSyntacticParent, binderOpt, options, out isDynamic, out resultKind, out memberGroup);
                    }

                case BoundKind.Call:
                    {
                        // Either overload resolution succeeded for this call or it did not. If it
                        // did not succeed then we've stashed the original method symbols from the
                        // method group, and we should use those as the symbols displayed for the
                        // call. If it did succeed then we did not stash any symbols; just fall
                        // through to the default case.

                        var call = (BoundCall)boundNode;
                        if (call.OriginalMethodsOpt.IsDefault)
                        {
                            if ((object)call.Method != null)
                            {
                                symbols = CreateReducedExtensionMethodIfPossible(call);
                                resultKind = call.ResultKind;
                            }
                        }
                        else
                        {
                            symbols = StaticCast<Symbol>.From(CreateReducedExtensionMethodsFromOriginalsIfNecessary(call));
                            resultKind = call.ResultKind;
                        }
                    }
                    break;

                case BoundKind.IndexerAccess:
                    {
                        // As for BoundCall, pull out stashed candidates if overload resolution failed.

                        BoundIndexerAccess indexerAccess = (BoundIndexerAccess)boundNode;
                        Debug.Assert((object)indexerAccess.Indexer != null);

                        resultKind = indexerAccess.ResultKind;

                        ImmutableArray<PropertySymbol> originalIndexersOpt = indexerAccess.OriginalIndexersOpt;
                        symbols = originalIndexersOpt.IsDefault ? ImmutableArray.Create<Symbol>(indexerAccess.Indexer) : StaticCast<Symbol>.From(originalIndexersOpt);
                    }
                    break;

                case BoundKind.EventAssignmentOperator:
                    var eventAssignment = (BoundEventAssignmentOperator)boundNode;
                    isDynamic = eventAssignment.IsDynamic;
                    var eventSymbol = eventAssignment.Event;
                    var methodSymbol = eventAssignment.IsAddition ? eventSymbol.AddMethod : eventSymbol.RemoveMethod;
                    if ((object)methodSymbol == null)
                    {
                        symbols = ImmutableArray<Symbol>.Empty;
                        resultKind = LookupResultKind.Empty;
                    }
                    else
                    {
                        symbols = ImmutableArray.Create<Symbol>(methodSymbol);
                        resultKind = eventAssignment.ResultKind;
                    }
                    break;

                case BoundKind.Conversion:
                    var conversion = (BoundConversion)boundNode;
                    isDynamic = conversion.ConversionKind.IsDynamic();
                    if (!isDynamic)
                    {
                        if ((conversion.ConversionKind == ConversionKind.MethodGroup) && conversion.IsExtensionMethod)
                        {
                            var symbol = conversion.SymbolOpt;
                            Debug.Assert((object)symbol != null);
                            symbols = ImmutableArray.Create<Symbol>(ReducedExtensionMethodSymbol.Create(symbol));
                            resultKind = conversion.ResultKind;
                        }
                        else if (conversion.ConversionKind.IsUserDefinedConversion())
                        {
                            GetSymbolsAndResultKind(conversion, conversion.SymbolOpt, conversion.OriginalUserDefinedConversionsOpt, out symbols, out resultKind);
                        }
                        else
                        {
                            goto default;
                        }
                    }
                    break;

                case BoundKind.BinaryOperator:
                    GetSymbolsAndResultKind((BoundBinaryOperator)boundNode, out isDynamic, ref resultKind, ref symbols);
                    break;

                case BoundKind.UnaryOperator:
                    GetSymbolsAndResultKind((BoundUnaryOperator)boundNode, out isDynamic, ref resultKind, ref symbols);
                    break;

                case BoundKind.UserDefinedConditionalLogicalOperator:
                    var @operator = (BoundUserDefinedConditionalLogicalOperator)boundNode;
                    isDynamic = false;
                    GetSymbolsAndResultKind(@operator, @operator.LogicalOperator, @operator.OriginalUserDefinedOperatorsOpt, out symbols, out resultKind);
                    break;

                case BoundKind.CompoundAssignmentOperator:
                    GetSymbolsAndResultKind((BoundCompoundAssignmentOperator)boundNode, out isDynamic, ref resultKind, ref symbols);
                    break;

                case BoundKind.IncrementOperator:
                    GetSymbolsAndResultKind((BoundIncrementOperator)boundNode, out isDynamic, ref resultKind, ref symbols);
                    break;

                case BoundKind.AwaitExpression:
                    var await = (BoundAwaitExpression)boundNode;
                    isDynamic = await.IsDynamic;
                    // TODO:
                    goto default;

                case BoundKind.ConditionalOperator:
                    Debug.Assert((object)boundNode.ExpressionSymbol == null);
                    var conditional = (BoundConditionalOperator)boundNode;
                    isDynamic = conditional.IsDynamic;
                    goto default;

                case BoundKind.Attribute:
                    {
                        Debug.Assert(boundNodeForSyntacticParent == null);
                        var attribute = (BoundAttribute)boundNode;
                        resultKind = attribute.ResultKind;

                        // If attribute name bound to a single named type or an error type
                        // with a single named type candidate symbol, we will return constructors
                        // of the named type in the semantic info.
                        // Otherwise, we will return the error type candidate symbols.

                        var namedType = (NamedTypeSymbol)attribute.Type;
                        if (namedType.IsErrorType())
                        {
                            Debug.Assert(resultKind != LookupResultKind.Viable);
                            var errorType = (ErrorTypeSymbol)namedType;
                            var candidateSymbols = errorType.CandidateSymbols;

                            // If error type has a single named type candidate symbol, we want to 
                            // use that type for symbol info. 
                            if (candidateSymbols.Length == 1 && candidateSymbols[0] is NamedTypeSymbol)
                            {
                                namedType = (NamedTypeSymbol)candidateSymbols[0];
                            }
                            else
                            {
                                symbols = candidateSymbols;
                                break;
                            }
                        }

                        AdjustSymbolsForObjectCreation(attribute, namedType, attribute.Constructor, binderOpt, ref resultKind, ref symbols, ref memberGroup);
                    }
                    break;

                case BoundKind.QueryClause:
                    {
                        var query = (BoundQueryClause)boundNode;
                        var builder = ArrayBuilder<Symbol>.GetInstance();
                        if (query.Operation != null && (object)query.Operation.ExpressionSymbol != null) builder.Add(query.Operation.ExpressionSymbol);
                        if ((object)query.DefinedSymbol != null) builder.Add(query.DefinedSymbol);
                        if (query.Cast != null && (object)query.Cast.ExpressionSymbol != null) builder.Add(query.Cast.ExpressionSymbol);
                        symbols = builder.ToImmutableAndFree();
                    }
                    break;

                case BoundKind.DynamicInvocation:
                    Debug.Assert((object)boundNode.ExpressionSymbol == null);
                    var dynamicInvocation = (BoundDynamicInvocation)boundNode;
                    symbols = memberGroup = dynamicInvocation.ApplicableMethods.Cast<MethodSymbol, Symbol>();
                    isDynamic = true;
                    break;

                case BoundKind.DynamicCollectionElementInitializer:
                    Debug.Assert((object)boundNode.ExpressionSymbol == null);
                    var collectionInit = (BoundDynamicCollectionElementInitializer)boundNode;
                    symbols = memberGroup = collectionInit.ApplicableMethods.Cast<MethodSymbol, Symbol>();
                    isDynamic = true;
                    break;

                case BoundKind.DynamicIndexerAccess:
                    Debug.Assert((object)boundNode.ExpressionSymbol == null);
                    var dynamicIndexer = (BoundDynamicIndexerAccess)boundNode;
                    symbols = memberGroup = dynamicIndexer.ApplicableIndexers.Cast<PropertySymbol, Symbol>();
                    isDynamic = true;
                    break;

                case BoundKind.DynamicMemberAccess:
                    Debug.Assert((object)boundNode.ExpressionSymbol == null);
                    isDynamic = true;
                    break;

                case BoundKind.DynamicObjectCreationExpression:
                    var objectCreation = (BoundDynamicObjectCreationExpression)boundNode;
                    symbols = memberGroup = objectCreation.ApplicableMethods.Cast<MethodSymbol, Symbol>();
                    isDynamic = true;
                    break;

                case BoundKind.ObjectCreationExpression:
                    var boundObjectCreation = (BoundObjectCreationExpression)boundNode;

                    if ((object)boundObjectCreation.Constructor != null)
                    {
                        Debug.Assert(boundObjectCreation.ConstructorsGroup.Contains(boundObjectCreation.Constructor));
                        symbols = ImmutableArray.Create<Symbol>(boundObjectCreation.Constructor);
                    }
                    else if (boundObjectCreation.ConstructorsGroup.Length > 0)
                    {
                        symbols = StaticCast<Symbol>.From(boundObjectCreation.ConstructorsGroup);
                        resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
                    }

                    memberGroup = boundObjectCreation.ConstructorsGroup.Cast<MethodSymbol, Symbol>();
                    break;

                case BoundKind.ThisReference:
                case BoundKind.BaseReference:
                    {
                        Binder binder = binderOpt ?? GetEnclosingBinder(GetAdjustedNodePosition(boundNode.Syntax));
                        NamedTypeSymbol containingType = binder.ContainingType;
                        var containingMember = binder.ContainingMember();

                        var thisParam = GetThisParameter(boundNode.Type, containingType, containingMember, out resultKind);
                        symbols = ImmutableArray.Create<Symbol>(thisParam);
                    }
                    break;

                default:
                    {
                        var symbol = boundNode.ExpressionSymbol;
                        if ((object)symbol != null)
                        {
                            symbols = ImmutableArray.Create(symbol);
                            resultKind = boundNode.ResultKind;
                        }
                    }
                    break;
            }

            if (boundNodeForSyntacticParent != null && (options & SymbolInfoOptions.PreferConstructorsToType) != 0)
            {
                // Adjust symbols to get the constructors if we're T in a "new T(...)".
                AdjustSymbolsForObjectCreation(boundNode, boundNodeForSyntacticParent, binderOpt, ref resultKind, ref symbols, ref memberGroup);
            }

            return symbols;
        }