// 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)); }
/// <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); } } }