Пример #1
0
        public MethodGroupResolution(
            MethodGroup methodGroup,
            Symbol otherSymbol,
            OverloadResolutionResult<MethodSymbol> overloadResolutionResult,
            AnalyzedArguments analyzedArguments,
            LookupResultKind resultKind,
            ImmutableArray<Diagnostic> diagnostics,
            bool extensionMethodsOfSameViabilityAreAvailable)
        {
            Debug.Assert((methodGroup == null) || (methodGroup.Methods.Count > 0));
            Debug.Assert((methodGroup == null) || ((object)otherSymbol == null));
            // Methods should be represented in the method group.
            Debug.Assert(((object)otherSymbol == null) || (otherSymbol.Kind != SymbolKind.Method));
            Debug.Assert(resultKind != LookupResultKind.Ambiguous); // HasAnyApplicableMethod is expecting Viable methods.
            Debug.Assert(!diagnostics.IsDefault);
            Debug.Assert(!extensionMethodsOfSameViabilityAreAvailable || methodGroup == null || !methodGroup.IsExtensionMethodGroup);

            this.MethodGroup = methodGroup;
            this.OtherSymbol = otherSymbol;
            this.OverloadResolutionResult = overloadResolutionResult;
            this.AnalyzedArguments = analyzedArguments;
            this.ResultKind = resultKind;
            this.Diagnostics = diagnostics;
            this.ExtensionMethodsOfSameViabilityAreAvailable = extensionMethodsOfSameViabilityAreAvailable;
        }
Пример #2
0
 public MethodGroupResolution(
     MethodGroup methodGroup,
     OverloadResolutionResult<MethodSymbol> overloadResolutionResult,
     AnalyzedArguments analyzedArguments,
     ImmutableArray<Diagnostic> diagnostics)
     : this(methodGroup, null, overloadResolutionResult, analyzedArguments, methodGroup.ResultKind, diagnostics)
 {
 }
Пример #3
0
        protected BoundExpression MakeConstruction(CSharpSyntaxNode node, NamedTypeSymbol toCreate, ImmutableArray <BoundExpression> args, DiagnosticBag diagnostics)
        {
            AnalyzedArguments analyzedArguments = AnalyzedArguments.GetInstance();

            analyzedArguments.Arguments.AddRange(args);
            var result = BindClassCreationExpression(node, toCreate.Name, node, toCreate, analyzedArguments, diagnostics);

            result.WasCompilerGenerated = true;
            analyzedArguments.Free();
            return(result);
        }
Пример #4
0
 /// <summary>
 /// Resolve method group based on the optional delegate invoke method.
 /// If the invoke method is null, ignore arguments in resolution.
 /// </summary>
 private static MethodGroupResolution ResolveDelegateMethodGroup(Binder binder, BoundMethodGroup source, MethodSymbol delegateInvokeMethodOpt, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
 {
     if ((object)delegateInvokeMethodOpt != null)
     {
         var analyzedArguments = new AnalyzedArguments();
         GetDelegateArguments(source.Syntax, analyzedArguments, delegateInvokeMethodOpt.Parameters, binder.Compilation);
         var resolution = binder.ResolveMethodGroup(source, analyzedArguments, isMethodGroupConversion: true, inferWithDynamic: true, useSiteDiagnostics: ref useSiteDiagnostics);
         return(resolution);
     }
     else
     {
         return(binder.ResolveMethodGroup(source, null, isMethodGroupConversion: true, useSiteDiagnostics: ref useSiteDiagnostics));
     }
 }
Пример #5
0
        /// <summary>
        /// The overload resolution portion of FindForEachPatternMethod.
        /// </summary>
        private MethodSymbol PerformForEachPatternOverloadResolution(TypeSymbol patternType, ArrayBuilder <MethodSymbol> candidateMethods, bool warningsOnly, DiagnosticBag diagnostics)
        {
            ArrayBuilder <TypeSymbol> typeArguments = ArrayBuilder <TypeSymbol> .GetInstance();

            AnalyzedArguments arguments = AnalyzedArguments.GetInstance();
            OverloadResolutionResult <MethodSymbol> overloadResolutionResult = OverloadResolutionResult <MethodSymbol> .GetInstance();

            HashSet <DiagnosticInfo> useSiteDiagnostics = null;

            this.OverloadResolution.MethodInvocationOverloadResolution(candidateMethods, typeArguments, arguments, overloadResolutionResult, ref useSiteDiagnostics);
            diagnostics.Add(syntax.Expression, useSiteDiagnostics);

            MethodSymbol result = null;

            if (overloadResolutionResult.Succeeded)
            {
                result = overloadResolutionResult.ValidResult.Member;

                if (result.IsStatic || result.DeclaredAccessibility != Accessibility.Public)
                {
                    if (warningsOnly)
                    {
                        diagnostics.Add(ErrorCode.WRN_PatternStaticOrInaccessible, syntax.Expression.Location, patternType, MessageID.IDS_Collection.Localize(), result);
                    }
                    result = null;
                }
                else if (result.CallsAreOmitted(syntax.SyntaxTree))
                {
                    // Calls to this method are omitted in the current syntax tree, i.e it is either a partial method with no implementation part OR a conditional method whose condition is not true in this source file.
                    // We don't want to want to allow this case, see StatementBinder::bindPatternToMethod.
                    result = null;
                }
            }
            else if (overloadResolutionResult.Results.Length > 1)
            {
                if (warningsOnly)
                {
                    diagnostics.Add(ErrorCode.WRN_PatternIsAmbiguous, syntax.Expression.Location, patternType, MessageID.IDS_Collection.Localize(),
                                    overloadResolutionResult.Results[0].Member, overloadResolutionResult.Results[1].Member);
                }
            }

            overloadResolutionResult.Free();
            arguments.Free();
            typeArguments.Free();

            return(result);
        }
        private static ArgumentAnalysisResult AnalyzeArgumentsForNormalFormNoNamedArguments(
            ImmutableArray <ParameterSymbol> parameters,
            AnalyzedArguments arguments,
            bool isMethodGroupConversion,
            bool isVararg
            )
        {
            Debug.Assert(!parameters.IsDefault);
            Debug.Assert(arguments != null);
            Debug.Assert(arguments.Names.Count == 0);

            // We simulate an additional non-optional parameter for a vararg method.
            int parameterCount = parameters.Length + (isVararg ? 1 : 0);
            int argumentCount  = arguments.Arguments.Count;

            // If there are no named arguments then analyzing the argument and parameter
            // matching in normal form is simple: each argument corresponds exactly to
            // the matching parameter, and if there are not enough arguments then the
            // unmatched parameters had better all be optional. If there are too
            // few parameters then one of the arguments has no matching parameter.
            // Otherwise, everything is just right.

            if (argumentCount < parameterCount)
            {
                for (
                    int parameterPosition = argumentCount;
                    parameterPosition < parameterCount;
                    ++parameterPosition
                    )
                {
                    if (
                        parameters.Length == parameterPosition ||
                        !CanBeOptional(parameters[parameterPosition], isMethodGroupConversion)
                        )
                    {
                        return(ArgumentAnalysisResult.RequiredParameterMissing(parameterPosition));
                    }
                }
            }
            else if (parameterCount < argumentCount)
            {
                return(ArgumentAnalysisResult.NoCorrespondingParameter(parameterCount));
            }

            // A null map means that every argument in the argument list corresponds exactly to
            // the same position in the formal parameter list.
            return(ArgumentAnalysisResult.NormalForm(default(ImmutableArray <int>)));
        }
Пример #7
0
        public Conversion MethodGroupConversion(CSharpSyntaxNode syntax, MethodGroup methodGroup, NamedTypeSymbol delegateType, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            var analyzedArguments = AnalyzedArguments.GetInstance();
            var result            = OverloadResolutionResult <MethodSymbol> .GetInstance();

            Debug.Assert((object)delegateType.DelegateInvokeMethod != null && !delegateType.DelegateInvokeMethod.HasUseSiteError,
                         "This method should only be called for valid delegate types");
            GetDelegateArguments(syntax, analyzedArguments, delegateType.DelegateInvokeMethod.Parameters, Compilation);
            _binder.OverloadResolution.MethodInvocationOverloadResolution(
                methodGroup.Methods, methodGroup.TypeArguments, analyzedArguments, result, ref useSiteDiagnostics, isMethodGroupConversion: true);
            var conversion = ToConversion(result, methodGroup, delegateType);

            analyzedArguments.Free();
            result.Free();
            return(conversion);
        }
Пример #8
0
 /// <summary>
 /// Resolve method group based on the optional delegate invoke method.
 /// If the invoke method is null, ignore arguments in resolution.
 /// </summary>
 private static MethodGroupResolution ResolveDelegateOrFunctionPointerMethodGroup(Binder binder, BoundMethodGroup source, MethodSymbol delegateInvokeMethodOpt, bool isFunctionPointer, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
 {
     if ((object)delegateInvokeMethodOpt != null)
     {
         var analyzedArguments = AnalyzedArguments.GetInstance();
         GetDelegateArguments(source.Syntax, analyzedArguments, delegateInvokeMethodOpt.Parameters, binder.Compilation);
         var resolution = binder.ResolveMethodGroup(source, analyzedArguments, useSiteDiagnostics: ref useSiteDiagnostics, inferWithDynamic: true,
                                                    isMethodGroupConversion: true, returnRefKind: delegateInvokeMethodOpt.RefKind, returnType: delegateInvokeMethodOpt.ReturnType,
                                                    isFunctionPointerResolution: isFunctionPointer, callingConvention: delegateInvokeMethodOpt.CallingConvention);
         analyzedArguments.Free();
         return(resolution);
     }
     else
     {
         return(binder.ResolveMethodGroup(source, analyzedArguments: null, isMethodGroupConversion: true, ref useSiteDiagnostics));
     }
 }
Пример #9
0
        private static bool ReportQueryInferenceFailedSelectMany(
            FromClauseSyntax fromClause,
            string methodName,
            BoundExpression receiver,
            AnalyzedArguments arguments,
            ImmutableArray <Symbol> symbols,
            BindingDiagnosticBag diagnostics
            )
        {
            Debug.Assert(methodName == "SelectMany");

            // Estimate the return type of Select's lambda argument
            BoundExpression arg  = arguments.Argument(arguments.IsExtensionMethodInvocation ? 1 : 0);
            TypeSymbol      type = null;

            if (arg.Kind == BoundKind.UnboundLambda)
            {
                var unbound = (UnboundLambda)arg;
                foreach (var t in unbound.Data.InferredReturnTypes())
                {
                    if (!t.IsErrorType())
                    {
                        type = t;
                        break;
                    }
                }
            }

            if ((object)type == null || type.IsErrorType())
            {
                return(false);
            }

            TypeSymbol receiverType = receiver?.Type;

            diagnostics.Add(
                new DiagnosticInfoWithSymbols(
                    ErrorCode.ERR_QueryTypeInferenceFailedSelectMany,
                    new object[] { type, receiverType, methodName },
                    symbols
                    ),
                fromClause.Expression.Location
                );
            return(true);
        }
Пример #10
0
        internal void ResolveOverloads <TMember>(
            ImmutableArray <TMember> members,
            ImmutableArray <TypeSymbol> typeArguments,
            ImmutableArray <ArgumentSyntax> arguments,
            OverloadResolutionResult <TMember> result,
            ref HashSet <DiagnosticInfo> useSiteDiagnostics,
            bool allowRefOmittedArguments)
            where TMember : Symbol
        {
            var methodsBuilder = ArrayBuilder <TMember> .GetInstance(members.Length);

            methodsBuilder.AddRange(members);

            var typeArgumentsBuilder = ArrayBuilder <TypeSymbol> .GetInstance(typeArguments.Length);

            typeArgumentsBuilder.AddRange(typeArguments);

            var analyzedArguments = AnalyzedArguments.GetInstance();
            var unusedDiagnostics = DiagnosticBag.GetInstance();

            foreach (var argumentSyntax in arguments)
            {
                var argument = this.BindExpression(argumentSyntax.Expression, unusedDiagnostics);

                analyzedArguments.Arguments.Add(argument);
                analyzedArguments.RefKinds.Add(argumentSyntax.RefOrOutKeyword.CSharpKind().GetRefKind());
                analyzedArguments.Names.Add(argumentSyntax.NameColon == null
                    ? null
                    : argumentSyntax.NameColon.Name);
            }

            OverloadResolution.MethodOrPropertyOverloadResolution(
                methodsBuilder,
                typeArgumentsBuilder,
                analyzedArguments,
                result,
                isMethodGroupConversion: false,
                allowRefOmittedArguments: allowRefOmittedArguments,
                useSiteDiagnostics: ref useSiteDiagnostics);

            methodsBuilder.Free();
            typeArgumentsBuilder.Free();
            analyzedArguments.Free();
            unusedDiagnostics.Free();
        }
        private static int?CheckForBadNonTrailingNamedArgument(
            AnalyzedArguments arguments,
            ParameterMap argsToParameters,
            ImmutableArray <ParameterSymbol> parameters
            )
        {
            // Is there any named argument used out-of-position and followed by unnamed arguments?

            // If the map is trivial then clearly not.
            if (argsToParameters.IsTrivial)
            {
                return(null);
            }

            // Find the first named argument which is used out-of-position
            int foundPosition = -1;
            int length        = arguments.Arguments.Count;

            for (int i = 0; i < length; i++)
            {
                int parameter = argsToParameters[i];
                if (parameter != -1 && parameter != i && arguments.Name(i) != null)
                {
                    foundPosition = i;
                    break;
                }
            }

            if (foundPosition != -1)
            {
                // Verify that all the following arguments are named
                for (int i = foundPosition + 1; i < length; i++)
                {
                    if (arguments.Name(i) == null)
                    {
                        return(foundPosition);
                    }
                }
            }

            return(null);
        }
        private static int?NameUsedForPositional(
            AnalyzedArguments arguments,
            ParameterMap argsToParameters
            )
        {
            // Was there a named argument used for a previously-supplied positional argument?

            // If the map is trivial then clearly not.
            if (argsToParameters.IsTrivial)
            {
                return(null);
            }

            // PERFORMANCE: This is an O(n-squared) algorithm, but n will typically be small.  We could rewrite this
            // PERFORMANCE: as a linear algorithm if we wanted to allocate more memory.

            for (
                int argumentPosition = 0;
                argumentPosition < argsToParameters.Length;
                ++argumentPosition
                )
            {
                if (arguments.Name(argumentPosition) != null)
                {
                    for (int i = 0; i < argumentPosition; ++i)
                    {
                        if (arguments.Name(i) == null)
                        {
                            if (argsToParameters[argumentPosition] == argsToParameters[i])
                            {
                                // Error; we've got a named argument that corresponds to
                                // a previously-given positional argument.
                                return(argumentPosition);
                            }
                        }
                    }
                }
            }

            return(null);
        }
Пример #13
0
        internal void ResolveOverloads <TMember>(
            ImmutableArray <TMember> members,
            ImmutableArray <TypeSymbol> typeArguments,
            ImmutableArray <ArgumentSyntax> arguments,
            OverloadResolutionResult <TMember> result,
            ref HashSet <DiagnosticInfo> useSiteDiagnostics,
            bool allowRefOmittedArguments)
            where TMember : Symbol
        {
            var methodsBuilder = ArrayBuilder <TMember> .GetInstance(members.Length);

            methodsBuilder.AddRange(members);

            var typeArgumentsBuilder = ArrayBuilder <TypeSymbol> .GetInstance(typeArguments.Length);

            typeArgumentsBuilder.AddRange(typeArguments);

            var analyzedArguments = AnalyzedArguments.GetInstance();
            var unusedDiagnostics = DiagnosticBag.GetInstance();

            foreach (var argumentSyntax in arguments)
            {
                BindArgumentAndName(analyzedArguments, unusedDiagnostics, false, argumentSyntax, allowArglist: false);
            }

            OverloadResolution.MethodOrPropertyOverloadResolution(
                methodsBuilder,
                typeArgumentsBuilder,
                analyzedArguments,
                result,
                isMethodGroupConversion: false,
                allowRefOmittedArguments: allowRefOmittedArguments,
                useSiteDiagnostics: ref useSiteDiagnostics);

            methodsBuilder.Free();
            typeArgumentsBuilder.Free();
            analyzedArguments.Free();
            unusedDiagnostics.Free();
        }
Пример #14
0
        public MethodGroupResolution(
            MethodGroup methodGroup,
            Symbol otherSymbol,
            OverloadResolutionResult <MethodSymbol> overloadResolutionResult,
            AnalyzedArguments analyzedArguments,
            LookupResultKind resultKind,
            ImmutableArray <Diagnostic> diagnostics)
        {
            Debug.Assert((methodGroup == null) || (methodGroup.Methods.Count > 0));
            Debug.Assert((methodGroup == null) || ((object)otherSymbol == null));
            // Methods should be represented in the method group.
            Debug.Assert(((object)otherSymbol == null) || (otherSymbol.Kind != SymbolKind.Method));
            Debug.Assert(resultKind != LookupResultKind.Ambiguous); // HasAnyApplicableMethod is expecting Viable methods.
            Debug.Assert(!diagnostics.IsDefault);

            this.MethodGroup = methodGroup;
            this.OtherSymbol = otherSymbol;
            this.OverloadResolutionResult = overloadResolutionResult;
            this.AnalyzedArguments        = analyzedArguments;
            this.ResultKind  = resultKind;
            this.Diagnostics = diagnostics;
        }
Пример #15
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;
        }
Пример #16
0
        private void BindPCallNativeAndDelegate(InvocationExpressionSyntax node, ArrayBuilder <BoundExpression> args,
                                                DiagnosticBag diagnostics, TypeSyntax type)
        {
            var    XNode  = node.XNode as XP.MethodCallContext;
            string method = XNode?.Expr.GetText();

            if (string.IsNullOrEmpty(method))
            {
                method = "PCALLNATIVE";
            }
            if (!ValidatePCallArguments(node, args, diagnostics, method))
            {
                return;
            }
            // Our parent is the invocation expression of the delegate
            AnalyzedArguments analyzedArguments = AnalyzedArguments.GetInstance();

            try
            {
                var ts = FindPCallDelegateType(type as IdentifierNameSyntax);
                if (ts != null && ts.IsDelegateType())
                {
                    SourceDelegateMethodSymbol delmeth = ts.DelegateInvokeMethod() as SourceDelegateMethodSymbol;
                    // create new parameters based on the parameters from out parent call
                    var invoke    = node.Parent as InvocationExpressionSyntax;
                    var realargs  = invoke.ArgumentList;
                    var delparams = ts.DelegateParameters();
                    BindArgumentsAndNames(realargs, diagnostics, analyzedArguments);
                    var builder = ArrayBuilder <ParameterSymbol> .GetInstance();

                    int i = 0;
                    foreach (var expr in analyzedArguments.Arguments)
                    {
                        var ptype = expr.Type;
                        if (ptype == null)
                        {
                            ptype = new PointerTypeSymbol(Compilation.GetSpecialType(SpecialType.System_Void));
                        }
                        var parameter = new SourceSimpleParameterSymbol(
                            delmeth,
                            ptype,
                            i,
                            delparams[i].RefKind,
                            delparams[i].Name,
                            delparams[i].Locations);
                        builder.Add(parameter);
                        i++;
                    }
                    delmeth.InitializeParameters(builder.ToImmutableAndFree());
                }
                else
                {
                    Error(diagnostics, ErrorCode.ERR_PCallResolveGeneratedDelegate, node, method, type.ToString());
                }

                return;
            }
            finally
            {
                analyzedArguments.Free();
            }
        }
Пример #17
0
 internal AnalyzedAttributeArguments(AnalyzedArguments constructorArguments, ImmutableArray<BoundExpression> namedArguments)
 {
     this.ConstructorArguments = constructorArguments;
     this.NamedArguments = namedArguments;
 }
Пример #18
0
        private static ArgumentAnalysisResult AnalyzeArguments(
            Symbol symbol,
            AnalyzedArguments arguments,
            bool isMethodGroupConversion,
            bool expanded)
        {
            Debug.Assert((object)symbol != null);
            Debug.Assert(arguments != null);

            ImmutableArray <ParameterSymbol> parameters = symbol.GetParameters();
            bool isVararg = symbol.GetIsVararg();

            // The easy out is that we have no named arguments and are in normal form.
            if (!expanded && arguments.Names.Count == 0)
            {
                return(AnalyzeArgumentsForNormalFormNoNamedArguments(parameters, arguments, isMethodGroupConversion, isVararg));
            }

            // We simulate an additional non-optional parameter for a vararg method.

            int argumentCount = arguments.Arguments.Count;

            int[] parametersPositions      = null;
            int?  unmatchedArgumentIndex   = null;
            bool? unmatchedArgumentIsNamed = null;

            // Try to map every argument position to a formal parameter position:

            bool seenNamedParams = false;
            bool seenOutOfPositionNamedArgument = false;
            bool isValidParams = IsValidParams(symbol);

            for (int argumentPosition = 0; argumentPosition < argumentCount; ++argumentPosition)
            {
                // We use -1 as a sentinel to mean that no parameter was found that corresponded to this argument.
                bool isNamedArgument;
                int  parameterPosition = CorrespondsToAnyParameter(parameters, expanded, arguments, argumentPosition,
                                                                   isValidParams, isVararg, out isNamedArgument, ref seenNamedParams, ref seenOutOfPositionNamedArgument) ?? -1;

                if (parameterPosition == -1 && unmatchedArgumentIndex == null)
                {
                    unmatchedArgumentIndex   = argumentPosition;
                    unmatchedArgumentIsNamed = isNamedArgument;
                }

                if (parameterPosition != argumentPosition && parametersPositions == null)
                {
                    parametersPositions = new int[argumentCount];
                    for (int i = 0; i < argumentPosition; ++i)
                    {
                        parametersPositions[i] = i;
                    }
                }

                if (parametersPositions != null)
                {
                    parametersPositions[argumentPosition] = parameterPosition;
                }
            }

            ParameterMap argsToParameters = new ParameterMap(parametersPositions, argumentCount);

            // We have analyzed every argument and tried to make it correspond to a particular parameter.
            // We must now answer the following questions:
            //
            // (1) Is there any named argument used out-of-position and followed by unnamed arguments?
            // (2) Is there any argument without a corresponding parameter?
            // (3) Was there any named argument that specified a parameter that was already
            //     supplied with a positional parameter?
            // (4) Is there any non-optional parameter without a corresponding argument?
            // (5) Is there any named argument that were specified twice?
            //
            // If the answer to any of these questions is "yes" then the method is not applicable.
            // It is possible that the answer to any number of these questions is "yes", and so
            // we must decide which error condition to prioritize when reporting the error,
            // should we need to report why a given method is not applicable. We prioritize
            // them in the given order.

            // (1) Is there any named argument used out-of-position and followed by unnamed arguments?

            int?badNonTrailingNamedArgument = CheckForBadNonTrailingNamedArgument(arguments, argsToParameters, parameters);

            if (badNonTrailingNamedArgument != null)
            {
                return(ArgumentAnalysisResult.BadNonTrailingNamedArgument(badNonTrailingNamedArgument.Value));
            }

            // (2) Is there any argument without a corresponding parameter?

            if (unmatchedArgumentIndex != null)
            {
                if (unmatchedArgumentIsNamed.Value)
                {
                    return(ArgumentAnalysisResult.NoCorrespondingNamedParameter(unmatchedArgumentIndex.Value));
                }
                else
                {
                    return(ArgumentAnalysisResult.NoCorrespondingParameter(unmatchedArgumentIndex.Value));
                }
            }

            // (3) was there any named argument that specified a parameter that was already
            //     supplied with a positional parameter?

            int?nameUsedForPositional = NameUsedForPositional(arguments, argsToParameters);

            if (nameUsedForPositional != null)
            {
                return(ArgumentAnalysisResult.NameUsedForPositional(nameUsedForPositional.Value));
            }

            // (4) Is there any non-optional parameter without a corresponding argument?

            int?requiredParameterMissing = CheckForMissingRequiredParameter(argsToParameters, parameters, isMethodGroupConversion, expanded);

            if (requiredParameterMissing != null)
            {
                return(ArgumentAnalysisResult.RequiredParameterMissing(requiredParameterMissing.Value));
            }

            // __arglist cannot be used with named arguments (as it doesn't have a name)
            if (arguments.Names.Any() && arguments.Names.Last() != null && isVararg)
            {
                return(ArgumentAnalysisResult.RequiredParameterMissing(parameters.Length));
            }

            // (5) Is there any named argument that were specified twice?

            int?duplicateNamedArgument = CheckForDuplicateNamedArgument(arguments);

            if (duplicateNamedArgument != null)
            {
                return(ArgumentAnalysisResult.DuplicateNamedArgument(duplicateNamedArgument.Value));
            }

            // We're good; this one might be applicable in the given form.

            return(expanded ?
                   ArgumentAnalysisResult.ExpandedForm(argsToParameters.ToImmutableArray()) :
                   ArgumentAnalysisResult.NormalForm(argsToParameters.ToImmutableArray()));
        }
Пример #19
0
 private void BindPCall(InvocationExpressionSyntax node, DiagnosticBag diagnostics, AnalyzedArguments analyzedArguments)
 {
     if (node.XPCall && node.Expression is GenericNameSyntax)
     {
         var  gns         = node.Expression as GenericNameSyntax;
         var  arg         = gns.TypeArgumentList.Arguments[0];
         var  method      = arg.ToFullString();
         bool pcallnative = method.IndexOf(XSharpSpecialNames.PCallNativePrefix, XSharpString.Comparison) >= 0;
         if (pcallnative)
         {
             BindPCallNativeAndDelegate(node, analyzedArguments.Arguments, diagnostics, arg);
         }
         else
         {
             BindPCallAndDelegate(node, analyzedArguments.Arguments, diagnostics, arg);
         }
     }
 }
Пример #20
0
        /// <summary>
        /// Find the Deconstruct method for the expression on the right, that will fit the number of assignable variables on the left.
        /// Returns an invocation expression if the Deconstruct method is found.
        ///     If so, it outputs placeholders that were coerced to the output types of the resolved Deconstruct method.
        /// The overload resolution is similar to writing `receiver.Deconstruct(out var x1, out var x2, ...)`.
        /// </summary>
        private BoundExpression MakeDeconstructInvocationExpression(
            int numCheckedVariables, BoundExpression receiver, CSharpSyntaxNode syntax,
            DiagnosticBag diagnostics, out ImmutableArray <BoundDeconstructValuePlaceholder> outPlaceholders)
        {
            var receiverSyntax = receiver.Syntax;

            if (receiver.Type.IsDynamic())
            {
                Error(diagnostics, ErrorCode.ERR_CannotDeconstructDynamic, receiverSyntax);
                outPlaceholders = default(ImmutableArray <BoundDeconstructValuePlaceholder>);

                return(BadExpression(receiverSyntax, receiver));
            }

            var analyzedArguments = AnalyzedArguments.GetInstance();
            var outVars           = ArrayBuilder <OutDeconstructVarPendingInference> .GetInstance(numCheckedVariables);

            DiagnosticBag bag = null;

            try
            {
                for (int i = 0; i < numCheckedVariables; i++)
                {
                    var variable = new OutDeconstructVarPendingInference(syntax);
                    analyzedArguments.Arguments.Add(variable);
                    analyzedArguments.RefKinds.Add(RefKind.Out);
                    outVars.Add(variable);
                }

                const string methodName   = "Deconstruct";
                var          memberAccess = BindInstanceMemberAccess(
                    receiverSyntax, receiverSyntax, receiver, methodName, rightArity: 0,
                    typeArgumentsSyntax: default(SeparatedSyntaxList <TypeSyntax>), typeArguments: default(ImmutableArray <TypeSymbol>),
                    invoked: true, diagnostics: diagnostics);

                memberAccess = CheckValue(memberAccess, BindValueKind.RValueOrMethodGroup, diagnostics);
                memberAccess.WasCompilerGenerated = true;

                if (memberAccess.Kind != BoundKind.MethodGroup)
                {
                    return(MissingDeconstruct(receiver, syntax, numCheckedVariables, diagnostics, out outPlaceholders, receiver));
                }

                // After the overload resolution completes, the last step is to coerce the arguments with inferred types.
                // That step returns placeholder (of correct type) instead of the outVar nodes that were passed in as arguments.
                // So the generated invocation expression will contain placeholders instead of those outVar nodes.
                // Those placeholders are also recorded in the outVar for easy access below, by the `SetInferredType` call on the outVar nodes.
                bag = DiagnosticBag.GetInstance();
                BoundExpression result = BindMethodGroupInvocation(
                    receiverSyntax, receiverSyntax, methodName, (BoundMethodGroup)memberAccess, analyzedArguments, bag, queryClause: null,
                    allowUnexpandedForm: true);

                result.WasCompilerGenerated = true;
                diagnostics.AddRange(bag);

                if (bag.HasAnyErrors())
                {
                    return(MissingDeconstruct(receiver, syntax, numCheckedVariables, diagnostics, out outPlaceholders, result));
                }

                // Verify all the parameters (except "this" for extension methods) are out parameters
                if (result.Kind != BoundKind.Call)
                {
                    return(MissingDeconstruct(receiver, syntax, numCheckedVariables, diagnostics, out outPlaceholders, result));
                }

                var deconstructMethod = ((BoundCall)result).Method;
                var parameters        = deconstructMethod.Parameters;
                for (int i = (deconstructMethod.IsExtensionMethod ? 1 : 0); i < parameters.Length; i++)
                {
                    if (parameters[i].RefKind != RefKind.Out)
                    {
                        return(MissingDeconstruct(receiver, syntax, numCheckedVariables, diagnostics, out outPlaceholders, result));
                    }
                }

                if (outVars.Any(v => (object)v.Placeholder == null))
                {
                    return(MissingDeconstruct(receiver, syntax, numCheckedVariables, diagnostics, out outPlaceholders, result));
                }

                outPlaceholders = outVars.SelectAsArray(v => v.Placeholder);

                return(result);
            }
            finally
            {
                analyzedArguments.Free();
                outVars.Free();

                if (bag != null)
                {
                    bag.Free();
                }
            }
        }
Пример #21
0
        private static int?CorrespondsToAnyParameter(
            ImmutableArray <ParameterSymbol> memberParameters,
            bool expanded,
            AnalyzedArguments arguments,
            int argumentPosition,
            bool isValidParams,
            bool isVararg,
            out bool isNamedArgument,
            ref bool seenNamedParams,
            ref bool seenOutOfPositionNamedArgument)
        {
            // Spec 7.5.1.1: Corresponding parameters:
            // For each argument in an argument list there has to be a corresponding parameter in
            // the function member or delegate being invoked. The parameter list used in the
            // following is determined as follows:
            // - For virtual methods and indexers defined in classes, the parameter list is picked from the most specific
            //   declaration or override of the function member, starting with the static type of the receiver, and searching through its base classes.
            // - For interface methods and indexers, the parameter list is picked form the most specific definition of the member,
            //   starting with the interface type and searching through the base interfaces. If no unique parameter list is found,
            //   a parameter list with inaccessible names and no optional parameters is constructed, so that invocations cannot use
            //   named parameters or omit optional arguments.
            // - For partial methods, the parameter list of the defining partial method declaration is used.
            // - For all other function members and delegates there is only a single parameter list, which is the one used.
            //
            // The position of an argument or parameter is defined as the number of arguments or
            // parameters preceding it in the argument list or parameter list.
            //
            // The corresponding parameters for function member arguments are established as follows:
            //
            // Arguments in the argument-list of instance constructors, methods, indexers and delegates:

            isNamedArgument = arguments.Names.Count > argumentPosition && arguments.Names[argumentPosition] != null;

            if (!isNamedArgument)
            {
                // Spec:
                // - A positional argument where a fixed parameter occurs at the same position in the
                //   parameter list corresponds to that parameter.
                // - A positional argument of a function member with a parameter array invoked in its
                //   normal form corresponds to the parameter array, which must occur at the same
                //   position in the parameter list.
                // - A positional argument of a function member with a parameter array invoked in its
                //   expanded form, where no fixed parameter occurs at the same position in the
                //   parameter list, corresponds to an element in the parameter array.

                if (seenNamedParams)
                {
                    // Unnamed arguments after a named argument corresponding to a params parameter cannot correspond to any parameters
                    return(null);
                }

                if (seenOutOfPositionNamedArgument)
                {
                    // Unnamed arguments after an out-of-position named argument cannot correspond to any parameters
                    return(null);
                }

                int parameterCount = memberParameters.Length + (isVararg ? 1 : 0);
                if (argumentPosition >= parameterCount)
                {
                    return(expanded ? parameterCount - 1 : (int?)null);
                }

                return(argumentPosition);
            }
            else
            {
                // SPEC: A named argument corresponds to the parameter of the same name in the parameter list.

                // SPEC VIOLATION: The intention of this line of the specification, when contrasted with
                // SPEC VIOLATION: the lines on positional arguments quoted above, was to disallow a named
                // SPEC VIOLATION: argument from corresponding to an element of a parameter array when
                // SPEC VIOLATION: the method was invoked in its expanded form. That is to say that in
                // SPEC VIOLATION: this case:  M(params int[] x) ... M(x : 1234); the named argument
                // SPEC VIOLATION: corresponds to x in the normal form (and is then inapplicable), but
                // SPEC VIOLATION: the named argument does *not* correspond to a member of params array
                // SPEC VIOLATION: x in the expanded form.
                // SPEC VIOLATION: Sadly that is not what we implemented in C# 4, and not what we are
                // SPEC VIOLATION: implementing here. If you do that, we make x correspond to the
                // SPEC VIOLATION: parameter array and allow the candidate to be applicable in its
                // SPEC VIOLATION: expanded form.

                var name = arguments.Names[argumentPosition];
                for (int p = 0; p < memberParameters.Length; ++p)
                {
                    // p is initialized to zero; it is ok for a named argument to "correspond" to
                    // _any_ parameter (not just the parameters past the point of positional arguments)
                    if (memberParameters[p].Name == name.Identifier.ValueText)
                    {
                        if (isValidParams && p == memberParameters.Length - 1)
                        {
                            seenNamedParams = true;
                        }

                        if (p != argumentPosition)
                        {
                            seenOutOfPositionNamedArgument = true;
                        }

                        return(p);
                    }
                }
            }

            return(null);
        }
        private static int? NameUsedForPositional(AnalyzedArguments arguments, ParameterMap argsToParameters)
        {
            // Was there a named argument used for a previously-supplied positional argument?

            // If the map is trivial then clearly not. 
            if (argsToParameters.IsTrivial)
            {
                return null;
            }

            // PERFORMANCE: This is an O(n-squared) algorithm, but n will typically be small.  We could rewrite this
            // PERFORMANCE: as a linear algorithm if we wanted to allocate more memory.

            for (int argumentPosition = 0; argumentPosition < argsToParameters.Length; ++argumentPosition)
            {
                if (arguments.Name(argumentPosition) != null)
                {
                    for (int i = 0; i < argumentPosition; ++i)
                    {
                        if (arguments.Name(i) == null)
                        {
                            if (argsToParameters[argumentPosition] == argsToParameters[i])
                            {
                                // Error; we've got a named argument that corresponds to 
                                // a previously-given positional argument.
                                return argumentPosition;
                            }
                        }
                    }
                }
            }

            return null;
        }
        private static ArgumentAnalysisResult AnalyzeArguments(
            Symbol symbol,
            AnalyzedArguments arguments,
            bool isMethodGroupConversion,
            bool expanded)
        {
            Debug.Assert((object)symbol != null);
            Debug.Assert(arguments != null);

            ImmutableArray<ParameterSymbol> parameters = symbol.GetParameters();

            // The easy out is that we have no named arguments and are in normal form.
            if (!expanded && arguments.Names.Count == 0)
            {
                return AnalyzeArgumentsForNormalFormNoNamedArguments(parameters, arguments, isMethodGroupConversion, symbol.GetIsVararg());
            }

            // We simulate an additional non-optional parameter for a vararg method.

            int argumentCount = arguments.Arguments.Count;

            int[] parametersPositions = null;
            int? unmatchedArgumentIndex = null;
            bool? unmatchedArgumentIsNamed = null;

            // Try to map every argument position to a formal parameter position:

            for (int argumentPosition = 0; argumentPosition < argumentCount; ++argumentPosition)
            {
                // We use -1 as a sentinel to mean that no parameter was found that corresponded to this argument.
                bool isNamedArgument;
                int parameterPosition = CorrespondsToAnyParameter(parameters, expanded, arguments, argumentPosition, out isNamedArgument) ?? -1;
                if (parameterPosition == -1 && unmatchedArgumentIndex == null)
                {
                    unmatchedArgumentIndex = argumentPosition;
                    unmatchedArgumentIsNamed = isNamedArgument;
                }

                if (parameterPosition != argumentPosition && parametersPositions == null)
                {
                    parametersPositions = new int[argumentCount];
                    for (int i = 0; i < argumentPosition; ++i)
                    {
                        parametersPositions[i] = i;
                    }
                }

                if (parametersPositions != null)
                {
                    parametersPositions[argumentPosition] = parameterPosition;
                }
            }

            ParameterMap argsToParameters = new ParameterMap(parametersPositions, argumentCount);

            // We have analyzed every argument and tried to make it correspond to a particular parameter. 
            // There are now three questions we must answer:
            //
            // (1) Is there any argument without a corresponding parameter?
            // (2) was there any named argument that specified a parameter that was already
            //     supplied with a positional parameter?
            // (3) Is there any non-optional parameter without a corresponding argument?
            //
            // If the answer to any of these questions is "yes" then the method is not applicable.
            // It is possible that the answer to any number of these questions is "yes", and so
            // we must decide which error condition to prioritize when reporting the error, 
            // should we need to report why a given method is not applicable. We prioritize
            // them in the given order.

            // (1) Is there any argument without a corresponding parameter?

            if (unmatchedArgumentIndex != null)
            {
                if (unmatchedArgumentIsNamed.Value)
                {
                    return ArgumentAnalysisResult.NoCorrespondingNamedParameter(unmatchedArgumentIndex.Value);
                }
                else
                {
                    return ArgumentAnalysisResult.NoCorrespondingParameter(unmatchedArgumentIndex.Value);
                }
            }

            // (2) was there any named argument that specified a parameter that was already
            //     supplied with a positional parameter?

            int? nameUsedForPositional = NameUsedForPositional(arguments, argsToParameters);
            if (nameUsedForPositional != null)
            {
                return ArgumentAnalysisResult.NameUsedForPositional(nameUsedForPositional.Value);
            }

            // (3) Is there any non-optional parameter without a corresponding argument?

            int? requiredParameterMissing = CheckForMissingRequiredParameter(argsToParameters, parameters, isMethodGroupConversion, expanded);
            if (requiredParameterMissing != null)
            {
                return ArgumentAnalysisResult.RequiredParameterMissing(requiredParameterMissing.Value);
            }

            // __arglist cannot be used with named arguments (as it doesn't have a name)
            if (arguments.Names.Count != 0 && symbol.GetIsVararg())
            {
                return ArgumentAnalysisResult.RequiredParameterMissing(parameters.Length);
            }

            // We're good; this one might be applicable in the given form.

            return expanded ?
                ArgumentAnalysisResult.ExpandedForm(argsToParameters.ToImmutableArray()) :
                ArgumentAnalysisResult.NormalForm(argsToParameters.ToImmutableArray());
        }
        private static int? CorrespondsToAnyParameter(
            ImmutableArray<ParameterSymbol> memberParameters,
            bool expanded,
            AnalyzedArguments arguments,
            int argumentPosition,
            out bool isNamedArgument)
        {
            // Spec 7.5.1.1: Corresponding parameters:
            // For each argument in an argument list there has to be a corresponding parameter in
            // the function member or delegate being invoked. The parameter list used in the
            // following is determined as follows:
            // - For virtual methods and indexers defined in classes, the parameter list is picked from the most specific 
            //   declaration or override of the function member, starting with the static type of the receiver, and searching through its base classes.
            // - For interface methods and indexers, the parameter list is picked form the most specific definition of the member, 
            //   starting with the interface type and searching through the base interfaces. If no unique parameter list is found, 
            //   a parameter list with inaccessible names and no optional parameters is constructed, so that invocations cannot use 
            //   named parameters or omit optional arguments.
            // - For partial methods, the parameter list of the defining partial method declaration is used.
            // - For all other other function members and delegates there is only a single parameter list, which is the one used.
            //
            // The position of an argument or parameter is defined as the number of arguments or
            // parameters preceding it in the argument list or parameter list.
            //
            // The corresponding parameters for function member arguments are established as follows:
            // 
            // Arguments in the argument-list of instance constructors, methods, indexers and delegates:

            isNamedArgument = arguments.Names.Count > argumentPosition && arguments.Names[argumentPosition] != null;

            if (!isNamedArgument)
            {
                // Spec:
                // - A positional argument where a fixed parameter occurs at the same position in the
                //   parameter list corresponds to that parameter.
                // - A positional argument of a function member with a parameter array invoked in its
                //   normal form corresponds to the parameter array, which must occur at the same
                //   position in the parameter list.
                // - A positional argument of a function member with a parameter array invoked in its
                //   expanded form, where no fixed parameter occurs at the same position in the
                //   parameter list, corresponds to an element in the parameter array.

                if (argumentPosition >= memberParameters.Length)
                {
                    return expanded ? memberParameters.Length - 1 : (int?)null;
                }

                return argumentPosition;
            }
            else
            {
                // SPEC: A named argument corresponds to the parameter of the same name in the parameter list. 

                // SPEC VIOLATION: The intention of this line of the specification, when contrasted with
                // SPEC VIOLATION: the lines on positional arguments quoted above, was to disallow a named
                // SPEC VIOLATION: argument from corresponding to an element of a parameter array when 
                // SPEC VIOLATION: the method was invoked in its expanded form. That is to say that in
                // SPEC VIOLATION: this case:  M(params int[] x) ... M(x : 1234); the named argument 
                // SPEC VIOLATION: corresponds to x in the normal form (and is then inapplicable), but
                // SPEC VIOLATION: the named argument does *not* correspond to a member of params array
                // SPEC VIOLATION: x in the expanded form.
                // SPEC VIOLATION: Sadly that is not what we implemented in C# 4, and not what we are 
                // SPEC VIOLATION: implementing here. If you do that, we make x correspond to the 
                // SPEC VIOLATION: parameter array and allow the candidate to be applicable in its
                // SPEC VIOLATION: expanded form.

                var name = arguments.Names[argumentPosition];
                for (int p = 0; p < memberParameters.Length; ++p)
                {
                    // TODO: p is initialized to zero; is it ok for a named argument to "correspond" to
                    // _any_ parameter, or just the parameters past the point of positional arguments?
                    if (memberParameters[p].Name == name.Identifier.ValueText)
                    {
                        return p;
                    }
                }
            }

            return null;
        }
        private static ArgumentAnalysisResult AnalyzeArgumentsForNormalFormNoNamedArguments(
            ImmutableArray<ParameterSymbol> parameters,
            AnalyzedArguments arguments,
            bool isMethodGroupConversion,
            bool isVararg)
        {
            Debug.Assert(!parameters.IsDefault);
            Debug.Assert(arguments != null);
            Debug.Assert(arguments.Names.Count == 0);

            // We simulate an additional non-optional parameter for a vararg method.
            int parameterCount = parameters.Length + (isVararg ? 1 : 0);
            int argumentCount = arguments.Arguments.Count;

            // If there are no named arguments then analyzing the argument and parameter
            // matching in normal form is simple: each argument corresponds exactly to
            // the matching parameter, and if there are not enough arguments then the
            // unmatched parameters had better all be optional. If there are too 
            // few parameters then one of the arguments has no matching parameter. 
            // Otherwise, everything is just right.

            if (argumentCount < parameterCount)
            {
                for (int parameterPosition = argumentCount; parameterPosition < parameterCount; ++parameterPosition)
                {
                    if (parameters.Length == parameterPosition || !CanBeOptional(parameters[parameterPosition], isMethodGroupConversion))
                    {
                        return ArgumentAnalysisResult.RequiredParameterMissing(parameterPosition);
                    }
                }
            }
            else if (parameterCount < argumentCount)
            {
                return ArgumentAnalysisResult.NoCorrespondingParameter(parameterCount);
            }

            // A null map means that every argument in the argument list corresponds exactly to
            // the same position in the formal parameter list.
            return ArgumentAnalysisResult.NormalForm(default(ImmutableArray<int>));
        }
Пример #26
0
        private static bool ReportQueryInferenceFailedSelectMany(FromClauseSyntax fromClause, string methodName, BoundExpression receiver, AnalyzedArguments arguments, ImmutableArray<Symbol> symbols, DiagnosticBag diagnostics)
        {
            Debug.Assert(methodName == "SelectMany");

            // Estimate the return type of Select's lambda argument
            BoundExpression arg = arguments.Argument(arguments.IsExtensionMethodInvocation ? 1 : 0);
            TypeSymbol type = null;
            if (arg.Kind == BoundKind.UnboundLambda)
            {
                var unbound = (UnboundLambda)arg;
                foreach (var t in unbound.Data.InferredReturnTypes())
                {
                    if (!t.IsErrorType())
                    {
                        type = t;
                        break;
                    }
                }
            }

            if ((object)type == null || type.IsErrorType())
            {
                return false;
            }

            TypeSymbol receiverType = receiver?.Type;
            diagnostics.Add(new DiagnosticInfoWithSymbols(
                ErrorCode.ERR_QueryTypeInferenceFailedSelectMany,
                new object[] { type, receiverType, methodName },
                symbols), fromClause.Expression.Location);
            return true;
        }
Пример #27
0
        internal static void ReportQueryInferenceFailed(CSharpSyntaxNode queryClause, string methodName, BoundExpression receiver, AnalyzedArguments arguments, ImmutableArray <Symbol> symbols, DiagnosticBag diagnostics)
        {
            string clauseKind = null;
            bool   multiple   = false;

            switch (queryClause.Kind)
            {
            case SyntaxKind.JoinClause:
                clauseKind = SyntaxFacts.GetText(SyntaxKind.JoinKeyword);
                multiple   = true;
                break;

            case SyntaxKind.LetClause:
                clauseKind = SyntaxFacts.GetText(SyntaxKind.LetKeyword);
                break;

            case SyntaxKind.SelectClause:
                clauseKind = SyntaxFacts.GetText(SyntaxKind.SelectKeyword);
                break;

            case SyntaxKind.WhereClause:
                clauseKind = SyntaxFacts.GetText(SyntaxKind.WhereKeyword);
                break;

            case SyntaxKind.OrderByClause:
            case SyntaxKind.AscendingOrdering:
            case SyntaxKind.DescendingOrdering:
                clauseKind = SyntaxFacts.GetText(SyntaxKind.OrderByKeyword);
                multiple   = true;
                break;

            case SyntaxKind.QueryContinuation:
                clauseKind = SyntaxFacts.GetText(SyntaxKind.IntoKeyword);
                break;

            case SyntaxKind.GroupClause:
                clauseKind = SyntaxFacts.GetText(SyntaxKind.GroupKeyword) + " " + SyntaxFacts.GetText(SyntaxKind.ByKeyword);
                multiple   = true;
                break;

            case SyntaxKind.FromClause:
                if (ReportQueryInferenceFailedSelectMany((FromClauseSyntax)queryClause, methodName, receiver, arguments, symbols, diagnostics))
                {
                    return;
                }
                clauseKind = SyntaxFacts.GetText(SyntaxKind.FromKeyword);
                break;

            default:
                clauseKind = "unknown";
                Debug.Assert(false, "invalid query clause kind " + queryClause.Kind);
                break;
            }

            diagnostics.Add(new DiagnosticInfoWithSymbols(
                                multiple ? ErrorCode.ERR_QueryTypeInferenceFailedMulti : ErrorCode.ERR_QueryTypeInferenceFailed,
                                new object[] { clauseKind, methodName },
                                symbols), queryClause.GetFirstToken().GetLocation());
        }
        internal static void ReportQueryInferenceFailed(CSharpSyntaxNode queryClause, string methodName, BoundExpression receiver, AnalyzedArguments arguments, ImmutableArray<Symbol> symbols, DiagnosticBag diagnostics)
        {
            string clauseKind = null;
            bool multiple = false;
            switch (queryClause.Kind)
            {
                case SyntaxKind.JoinClause:
                    clauseKind = "join"; // TODO: should be ErrorCode.IDS_JoinClause.Localize();
                    multiple = true;
                    break;
                case SyntaxKind.LetClause:
                    clauseKind = "let"; // TODO: ErrorCode.IDS_LetClause
                    break;
                case SyntaxKind.SelectClause:
                    clauseKind = "select"; // TODO ErrorCode.IDS_Select
                    break;
                case SyntaxKind.WhereClause:
                    clauseKind = "where"; // TODO: ErrorCode.IDS_Where
                    break;
                case SyntaxKind.OrderByClause:
                case SyntaxKind.AscendingOrdering:
                case SyntaxKind.DescendingOrdering:
                    clauseKind = "order by"; // TODO: ErrorCode.IDS_OrderByClause
                    multiple = true;
                    break;
                case SyntaxKind.QueryContinuation:
                    clauseKind = "into"; // TODO: ErrorCode.IDS_ContinuationClause
                    break;
                case SyntaxKind.GroupClause:
                    clauseKind = "group by"; // TODO: ErrorCode.IDS_GroupByClause
                    multiple = true;
                    break;
                case SyntaxKind.FromClause:
                    if (ReportQueryInferenceFailedSelectMany((FromClauseSyntax)queryClause, methodName, receiver, arguments, symbols, diagnostics))
                    {
                        return;
                    }
                    clauseKind = "from"; // TODO: ErrorCode.IDS_FromClause
                    break;
                default:
                    clauseKind = "unknown";
                    Debug.Assert(false, "invalid query clause kind " + queryClause.Kind);
                    break;
            }

            diagnostics.Add(new DiagnosticInfoWithSymbols(
                multiple ? ErrorCode.ERR_QueryTypeInferenceFailedMulti : ErrorCode.ERR_QueryTypeInferenceFailed,
                new object[] { clauseKind, methodName },
                symbols), queryClause.GetFirstToken().GetLocation());
        }
 /// <summary>
 /// Resolve method group based on the optional delegate invoke method.
 /// If the invoke method is null, ignore arguments in resolution.
 /// </summary>
 private static MethodGroupResolution ResolveDelegateMethodGroup(Binder binder, BoundMethodGroup source, MethodSymbol delegateInvokeMethodOpt, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
 {
     if ((object)delegateInvokeMethodOpt != null)
     {
         var analyzedArguments = new AnalyzedArguments();
         GetDelegateArguments(source.Syntax, analyzedArguments, delegateInvokeMethodOpt.Parameters, binder.Compilation);
         var resolution = binder.ResolveMethodGroup(source, analyzedArguments, isMethodGroupConversion: true, inferWithDynamic: true, useSiteDiagnostics: ref useSiteDiagnostics);
         return resolution;
     }
     else
     {
         return binder.ResolveMethodGroup(source, null, isMethodGroupConversion: true, useSiteDiagnostics: ref useSiteDiagnostics);
     }
 }
Пример #30
0
        internal static void ReportQueryInferenceFailed(CSharpSyntaxNode queryClause, string methodName, BoundExpression receiver, AnalyzedArguments arguments, ImmutableArray<Symbol> symbols, DiagnosticBag diagnostics)
        {
            string clauseKind = null;
            bool multiple = false;
            switch (queryClause.Kind())
            {
                case SyntaxKind.JoinClause:
                    clauseKind = SyntaxFacts.GetText(SyntaxKind.JoinKeyword);
                    multiple = true;
                    break;
                case SyntaxKind.LetClause:
                    clauseKind = SyntaxFacts.GetText(SyntaxKind.LetKeyword);
                    break;
                case SyntaxKind.SelectClause:
                    clauseKind = SyntaxFacts.GetText(SyntaxKind.SelectKeyword);
                    break;
                case SyntaxKind.WhereClause:
                    clauseKind = SyntaxFacts.GetText(SyntaxKind.WhereKeyword);
                    break;
                case SyntaxKind.OrderByClause:
                case SyntaxKind.AscendingOrdering:
                case SyntaxKind.DescendingOrdering:
                    clauseKind = SyntaxFacts.GetText(SyntaxKind.OrderByKeyword);
                    multiple = true;
                    break;
                case SyntaxKind.QueryContinuation:
                    clauseKind = SyntaxFacts.GetText(SyntaxKind.IntoKeyword);
                    break;
                case SyntaxKind.GroupClause:
                    clauseKind = SyntaxFacts.GetText(SyntaxKind.GroupKeyword) + " " + SyntaxFacts.GetText(SyntaxKind.ByKeyword);
                    multiple = true;
                    break;
                case SyntaxKind.FromClause:
                    if (ReportQueryInferenceFailedSelectMany((FromClauseSyntax)queryClause, methodName, receiver, arguments, symbols, diagnostics))
                    {
                        return;
                    }
                    clauseKind = SyntaxFacts.GetText(SyntaxKind.FromKeyword);
                    break;
                default:
                    clauseKind = "unknown";
                    Debug.Assert(false, "invalid query clause kind " + queryClause.Kind());
                    break;
            }

            diagnostics.Add(new DiagnosticInfoWithSymbols(
                multiple ? ErrorCode.ERR_QueryTypeInferenceFailedMulti : ErrorCode.ERR_QueryTypeInferenceFailed,
                new object[] { clauseKind, methodName },
                symbols), queryClause.GetFirstToken().GetLocation());
        }
        public static void GetDelegateArguments(CSharpSyntaxNode syntax, AnalyzedArguments analyzedArguments, ImmutableArray<ParameterSymbol> delegateParameters, CSharpCompilation compilation)
        {
            foreach (var p in delegateParameters)
            {
                ParameterSymbol parameter = p;

                // In ExpressionBinder::BindGrpConversion, the native compiler substitutes object in place of dynamic.  This is
                // necessary because conversions from expressions of type dynamic always succeed, whereas conversions from the
                // type generally fail (modulo identity conversions).  This is not reflected in the C# 4 spec, but will be
                // incorporated going forward.  See DevDiv #742345 for additional details.
                // NOTE: Dev11 does a deep substitution (e.g. C<C<C<dynamic>>> -> C<C<C<object>>>), but that seems redundant.
                if (parameter.Type.IsDynamic())
                {
                    // If we don't have System.Object, then we'll get an error type, which will cause overload resolution to fail, 
                    // which will cause some error to be reported.  That's sufficient (i.e. no need to specifically report its absence here).
                    parameter = new SignatureOnlyParameterSymbol(
                        compilation.GetSpecialType(SpecialType.System_Object), parameter.CustomModifiers, parameter.IsParams, parameter.RefKind);
                }

                analyzedArguments.Arguments.Add(new BoundParameter(syntax, parameter) { WasCompilerGenerated = true });
                analyzedArguments.RefKinds.Add(parameter.RefKind);
            }
        }
Пример #32
0
        internal static void ReportQueryInferenceFailed(CSharpSyntaxNode queryClause, string methodName, BoundExpression receiver, AnalyzedArguments arguments, ImmutableArray <Symbol> symbols, DiagnosticBag diagnostics)
        {
            string clauseKind = null;
            bool   multiple   = false;

            switch (queryClause.Kind)
            {
            case SyntaxKind.JoinClause:
                clauseKind = "join";     // TODO: should be ErrorCode.IDS_JoinClause.Localize();
                multiple   = true;
                break;

            case SyntaxKind.LetClause:
                clauseKind = "let";     // TODO: ErrorCode.IDS_LetClause
                break;

            case SyntaxKind.SelectClause:
                clauseKind = "select";     // TODO ErrorCode.IDS_Select
                break;

            case SyntaxKind.WhereClause:
                clauseKind = "where";     // TODO: ErrorCode.IDS_Where
                break;

            case SyntaxKind.OrderByClause:
            case SyntaxKind.AscendingOrdering:
            case SyntaxKind.DescendingOrdering:
                clauseKind = "order by";     // TODO: ErrorCode.IDS_OrderByClause
                multiple   = true;
                break;

            case SyntaxKind.QueryContinuation:
                clauseKind = "into";     // TODO: ErrorCode.IDS_ContinuationClause
                break;

            case SyntaxKind.GroupClause:
                clauseKind = "group by";     // TODO: ErrorCode.IDS_GroupByClause
                multiple   = true;
                break;

            case SyntaxKind.FromClause:
                if (ReportQueryInferenceFailedSelectMany((FromClauseSyntax)queryClause, methodName, receiver, arguments, symbols, diagnostics))
                {
                    return;
                }
                clauseKind = "from";     // TODO: ErrorCode.IDS_FromClause
                break;

            default:
                clauseKind = "unknown";
                Debug.Assert(false, "invalid query clause kind " + queryClause.Kind);
                break;
            }

            diagnostics.Add(new DiagnosticInfoWithSymbols(
                                multiple ? ErrorCode.ERR_QueryTypeInferenceFailedMulti : ErrorCode.ERR_QueryTypeInferenceFailed,
                                new object[] { clauseKind, methodName },
                                symbols), queryClause.GetFirstToken().GetLocation());
        }