// Rewrite collection initializer element Add method call:
        //  new List<int> { 1, 2, 3 };  OR  new List<int> { { 1, 2 }, 3 };
        //                  ~                               ~~~~~~~~
        private BoundExpression MakeCollectionInitializer(BoundExpression rewrittenReceiver, BoundCollectionElementInitializer initializer)
        {
            MethodSymbol addMethod = initializer.AddMethod;

            Debug.Assert(addMethod.Name == "Add");
            Debug.Assert(addMethod.Parameters
                         .Skip(addMethod.IsExtensionMethod ? 1 : 0)
                         .All(p => p.RefKind == RefKind.None || p.RefKind == RefKind.In));
            Debug.Assert(initializer.Arguments.Any());
            Debug.Assert(rewrittenReceiver != null || _inExpressionLambda);

            var syntax = initializer.Syntax;

            if (_allowOmissionOfConditionalCalls)
            {
                // NOTE: Calls cannot be omitted within an expression tree (CS0765); this should already
                // have been checked.
                if (addMethod.CallsAreOmitted(initializer.SyntaxTree))
                {
                    return(null);
                }
            }

            var rewrittenArguments = VisitList(initializer.Arguments);
            var rewrittenType      = VisitType(initializer.Type);

            // We have already lowered each argument, but we may need some additional rewriting for the arguments,
            // such as generating a params array, re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
            ImmutableArray <LocalSymbol> temps;
            var argumentRefKindsOpt = default(ImmutableArray <RefKind>);

            if (addMethod.Parameters[0].RefKind == RefKind.Ref)
            {
                // If the Add method is an extension which takes a `ref this` as the first parameter, implicitly add a `ref` to the argument
                // Initializer element syntax cannot have `ref`, `in`, or `out` keywords.
                // Arguments to `in` parameters will be converted to have RefKind.In later on.
                var builder = ArrayBuilder <RefKind> .GetInstance(addMethod.Parameters.Length, RefKind.None);

                builder[0]          = RefKind.Ref;
                argumentRefKindsOpt = builder.ToImmutableAndFree();
            }

            rewrittenArguments = MakeArguments(syntax, rewrittenArguments, addMethod, addMethod, initializer.Expanded, initializer.ArgsToParamsOpt, ref argumentRefKindsOpt, out temps, enableCallerInfo: ThreeState.True);

            if (initializer.InvokedAsExtensionMethod)
            {
                // the add method was found as an extension method.  Replace the implicit receiver (first argument) with the rewritten receiver.
                Debug.Assert(addMethod.IsStatic && addMethod.IsExtensionMethod);
                Debug.Assert(rewrittenArguments[0].Kind == BoundKind.ImplicitReceiver);
                Debug.Assert(!_inExpressionLambda, "Expression trees do not support extension Add");
                rewrittenArguments = rewrittenArguments.SetItem(0, rewrittenReceiver);
                rewrittenReceiver  = null;
            }

            if (_inExpressionLambda)
            {
                return(initializer.Update(addMethod, rewrittenArguments, rewrittenReceiver, expanded: false, argsToParamsOpt: default, initializer.InvokedAsExtensionMethod, initializer.ResultKind, initializer.BinderOpt, rewrittenType));
        private void VisitCall(
            MethodSymbol method,
            PropertySymbol propertyAccess,
            ImmutableArray <BoundExpression> arguments,
            ImmutableArray <RefKind> argumentRefKindsOpt,
            ImmutableArray <string> argumentNamesOpt,
            BitVector defaultArguments,
            BoundNode node
            )
        {
            Debug.Assert((object)method != null);
            Debug.Assert(
                ((object)propertyAccess == null) ||
                (method == propertyAccess.GetOwnOrInheritedGetMethod()) ||
                (method == propertyAccess.GetOwnOrInheritedSetMethod()) ||
                propertyAccess.MustCallMethodsDirectly
                );

            CheckArguments(argumentRefKindsOpt, arguments, method);

            if (_inExpressionLambda)
            {
                if (method.CallsAreOmitted(node.SyntaxTree))
                {
                    Error(ErrorCode.ERR_PartialMethodInExpressionTree, node);
                }
                else if (
                    (object)propertyAccess != null &&
                    propertyAccess.IsIndexedProperty() &&
                    !propertyAccess.IsIndexer
                    )
                {
                    Error(ErrorCode.ERR_ExpressionTreeContainsIndexedProperty, node);
                }
                else if (hasDefaultArgument(arguments, defaultArguments))
                {
                    Error(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, node);
                }
                else if (!argumentNamesOpt.IsDefaultOrEmpty)
                {
                    Error(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, node);
                }
                else if (IsComCallWithRefOmitted(method, arguments, argumentRefKindsOpt))
                {
                    Error(ErrorCode.ERR_ComRefCallInExpressionTree, node);
                }
                else if (method.MethodKind == MethodKind.LocalFunction)
                {
                    Error(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, node);
                }
                else if (method.RefKind != RefKind.None)
                {
                    Error(ErrorCode.ERR_RefReturningCallInExpressionTree, node);
                }
            }
        // Rewrite collection initializer element Add method call:
        //  new List<int> { 1, 2, 3 };  OR  new List<int> { { 1, 2 }, 3 };
        //                  ~                               ~~~~~~~~
        private BoundExpression MakeCollectionInitializer(BoundExpression rewrittenReceiver, BoundCollectionElementInitializer initializer)
        {
            Debug.Assert(initializer.AddMethod.Name == "Add");
            Debug.Assert(initializer.Arguments.Any());
            Debug.Assert(rewrittenReceiver != null || _inExpressionLambda);

            var          syntax    = initializer.Syntax;
            MethodSymbol addMethod = initializer.AddMethod;

            if (_allowOmissionOfConditionalCalls)
            {
                // NOTE: Calls cannot be omitted within an expression tree (CS0765); this should already
                // have been checked.
                if (addMethod.CallsAreOmitted(initializer.SyntaxTree))
                {
                    return(null);
                }
            }

            var rewrittenArguments = VisitList(initializer.Arguments);
            var rewrittenType      = VisitType(initializer.Type);

            // We have already lowered each argument, but we may need some additional rewriting for the arguments,
            // such as generating a params array, re-ordering arguments based on argsToParamsOpt map, inserting arguments for optional parameters, etc.
            ImmutableArray <LocalSymbol> temps;
            var argumentRefKindsOpt = default(ImmutableArray <RefKind>);

            rewrittenArguments = MakeArguments(syntax, rewrittenArguments, addMethod, addMethod, initializer.Expanded, initializer.ArgsToParamsOpt, ref argumentRefKindsOpt, out temps, enableCallerInfo: ThreeState.True);
            Debug.Assert(argumentRefKindsOpt.IsDefault);

            if (initializer.InvokedAsExtensionMethod)
            {
                // the add method was found as an extension method.  Replace the implicit receiver (first argument) with the rewritten receiver.
                Debug.Assert(addMethod.IsStatic && addMethod.IsExtensionMethod);
                Debug.Assert(rewrittenArguments[0].Kind == BoundKind.ImplicitReceiver);
                var newArgs = ArrayBuilder <BoundExpression> .GetInstance();

                newArgs.AddRange(rewrittenArguments);
                newArgs[0]         = rewrittenReceiver;
                rewrittenArguments = newArgs.ToImmutableAndFree();
                rewrittenReceiver  = null;
            }

            if (_inExpressionLambda)
            {
                return(initializer.Update(addMethod, rewrittenArguments, false, default(ImmutableArray <int>), initializer.InvokedAsExtensionMethod, initializer.ResultKind, rewrittenType));
            }

            return(MakeCall(null, syntax, rewrittenReceiver, addMethod, rewrittenArguments, default(ImmutableArray <RefKind>), initializer.InvokedAsExtensionMethod, initializer.ResultKind, addMethod.ReturnType, temps));
        }
Exemple #4
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 void VisitCall(
            MethodSymbol method,
            PropertySymbol propertyAccess,
            ImmutableArray <BoundExpression> arguments,
            ImmutableArray <RefKind> argumentRefKindsOpt,
            ImmutableArray <string> argumentNamesOpt,
            bool expanded,
            BoundNode node)
        {
            Debug.Assert((object)method != null);
            Debug.Assert(((object)propertyAccess == null) ||
                         (method == propertyAccess.GetOwnOrInheritedGetMethod()) ||
                         (method == propertyAccess.GetOwnOrInheritedSetMethod()) ||
                         propertyAccess.MustCallMethodsDirectly);

            CheckArguments(argumentRefKindsOpt, arguments, method);

            if (_inExpressionLambda)
            {
                if (method.CallsAreOmitted(node.SyntaxTree))
                {
                    Error(ErrorCode.ERR_PartialMethodInExpressionTree, node);
                }
                else if ((object)propertyAccess != null && propertyAccess.IsIndexedProperty() && !propertyAccess.IsIndexer)
                {
                    Error(ErrorCode.ERR_ExpressionTreeContainsIndexedProperty, node);
                }
                else if (arguments.Length < (((object)propertyAccess != null) ? propertyAccess.ParameterCount : method.ParameterCount) + (expanded ? -1 : 0))
                {
                    Error(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, node);
                }
                else if (!argumentNamesOpt.IsDefault)
                {
                    Error(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, node);
                }
                else if (IsComCallWithRefOmitted(method, arguments, argumentRefKindsOpt))
                {
                    Error(ErrorCode.ERR_ComRefCallInExpressionTree, node);
                }
            }
        }