private UnboundLambda BindAnonymousFunction(CSharpSyntaxNode syntax, DiagnosticBag diagnostics) { Debug.Assert(syntax != null); Debug.Assert(syntax.IsAnonymousFunction()); var results = AnalyzeAnonymousFunction(syntax, diagnostics); var refKinds = results.Item1; var types = results.Item2; var names = results.Item3; var isAsync = results.Item4; if (!types.IsDefault) { foreach (var type in types) { // UNDONE: Where do we report improper use of pointer types? if ((object)type != null && type.IsStatic) { Error(diagnostics, ErrorCode.ERR_ParameterIsStaticClass, syntax, type); } } } var lambda = new UnboundLambda(syntax, this, refKinds, types, names, isAsync); if (!names.IsDefault) { var binder = new LocalScopeBinder(this); var pNames = PooledHashSet <string> .GetInstance(); for (int i = 0; i < lambda.ParameterCount; i++) { var name = lambda.ParameterName(i); if (string.IsNullOrEmpty(name)) { continue; } if (pNames.Contains(name)) { // The parameter name '{0}' is a duplicate diagnostics.Add(ErrorCode.ERR_DuplicateParamName, lambda.ParameterLocation(i), name); } else { pNames.Add(name); binder.ValidateLambdaParameterNameConflictsInScope(lambda.ParameterLocation(i), name, diagnostics); } } pNames.Free(); } return(lambda); }
private UnboundLambda BindAnonymousFunction(CSharpSyntaxNode syntax, DiagnosticBag diagnostics) { Debug.Assert(syntax != null); Debug.Assert(syntax.IsAnonymousFunction()); var(refKinds, types, names, isAsync) = AnalyzeAnonymousFunction(syntax, diagnostics); if (!types.IsDefault) { foreach (var type in types) { // UNDONE: Where do we report improper use of pointer types? if (type.HasType && type.IsStatic) { Error(diagnostics, ErrorCode.ERR_ParameterIsStaticClass, syntax, type.Type); } } } var lambda = new UnboundLambda(syntax, this, refKinds, types, names, isAsync); if (!names.IsDefault) { var binder = new LocalScopeBinder(this); bool allowShadowingNames = binder.Compilation.IsFeatureEnabled(MessageID.IDS_FeatureNameShadowingInNestedFunctions); var pNames = PooledHashSet <string> .GetInstance(); for (int i = 0; i < lambda.ParameterCount; i++) { var name = lambda.ParameterName(i); if (string.IsNullOrEmpty(name)) { continue; } if (!pNames.Add(name)) { // The parameter name '{0}' is a duplicate diagnostics.Add(ErrorCode.ERR_DuplicateParamName, lambda.ParameterLocation(i), name); } else if (!allowShadowingNames) { binder.ValidateLambdaParameterNameConflictsInScope(lambda.ParameterLocation(i), name, diagnostics); } } pNames.Free(); } return(lambda); }
private UnboundLambda BindAnonymousFunction(CSharpSyntaxNode syntax, DiagnosticBag diagnostics) { Debug.Assert(syntax != null); Debug.Assert(syntax.IsAnonymousFunction()); var results = AnalyzeAnonymousFunction(syntax, diagnostics); var refKinds = results.Item1; var types = results.Item2; var names = results.Item3; var isAsync = results.Item4; if (!types.IsDefault) { foreach (var type in types) { // UNDONE: Where do we report improper use of pointer types? if ((object)type != null && type.IsStatic) { Error(diagnostics, ErrorCode.ERR_ParameterIsStaticClass, syntax, type); } } } var lambda = new UnboundLambda(syntax, this, refKinds, types, names, isAsync); if (!names.IsDefault) { var binder = new LocalScopeBinder(this.ContainingMemberOrLambda as MethodSymbol, this); for (int n = 0; n < names.Length; ++n) { string name = lambda.ParameterName(n); binder.ValidateLambdaParameterNameConflictsInScope(lambda.ParameterLocation(n), name, diagnostics); } } return(lambda); }
internal void GenerateAnonymousFunctionConversionError(DiagnosticBag diagnostics, CSharpSyntaxNode syntax, UnboundLambda anonymousFunction, TypeSymbol targetType) { Debug.Assert((object)targetType != null); Debug.Assert(anonymousFunction != null); // Is the target type simply bad? // If the target type is an error then we've already reported a diagnostic. Don't bother // reporting the conversion error. if (targetType.IsErrorType() || syntax.HasErrors) { return; } // CONSIDER: Instead of computing this again, cache the reason why the conversion failed in // CONSIDER: the Conversion result, and simply report that. var reason = Conversions.IsAnonymousFunctionCompatibleWithType(anonymousFunction, targetType); // It is possible that the conversion from lambda to delegate is just fine, and // that we ended up here because the target type, though itself is not an error // type, contains a type argument which is an error type. For example, converting // (Foo foo)=>{} to Action<Foo> is a perfectly legal conversion even if Foo is undefined! // In that case we have already reported an error that Foo is undefined, so just bail out. if (reason == LambdaConversionResult.Success) { return; } var id = anonymousFunction.MessageID.Localize(); if (reason == LambdaConversionResult.BadTargetType) { if (ReportDelegateInvokeUseSiteDiagnostic(diagnostics, targetType, node: syntax)) { return; } // Cannot convert {0} to type '{1}' because it is not a delegate type Error(diagnostics, ErrorCode.ERR_AnonMethToNonDel, syntax, id, targetType); return; } if (reason == LambdaConversionResult.ExpressionTreeMustHaveDelegateTypeArgument) { Debug.Assert(targetType.IsExpressionTree()); Error(diagnostics, ErrorCode.ERR_ExpressionTreeMustHaveDelegate, syntax, ((NamedTypeSymbol)targetType).TypeArgumentsNoUseSiteDiagnostics[0]); return; } if (reason == LambdaConversionResult.ExpressionTreeFromAnonymousMethod) { Debug.Assert(targetType.IsExpressionTree()); Error(diagnostics, ErrorCode.ERR_AnonymousMethodToExpressionTree, syntax); return; } // At this point we know that we have either a delegate type or an expression type for the target. var delegateType = targetType.GetDelegateType(); // The target type is a vaid delegate or expression tree type. Is there something wrong with the // parameter list? // First off, is there a parameter list at all? if (reason == LambdaConversionResult.MissingSignatureWithOutParameter) { // COMPATIBILITY: The C# 4 compiler produces two errors for: // // delegate void D (out int x); // ... // D d = delegate {}; // // error CS1676: Parameter 1 must be declared with the 'out' keyword // error CS1688: Cannot convert anonymous method block without a parameter list // to delegate type 'D' because it has one or more out parameters // // This seems redundant, (because there is no "parameter 1" in the source code) // and unnecessary. I propose that we eliminate the first error. Error(diagnostics, ErrorCode.ERR_CantConvAnonMethNoParams, syntax, targetType); return; } // There is a parameter list. Does it have the right number of elements? if (reason == LambdaConversionResult.BadParameterCount) { // Delegate '{0}' does not take {1} arguments Error(diagnostics, ErrorCode.ERR_BadDelArgCount, syntax, targetType, anonymousFunction.ParameterCount); return; } // The parameter list exists and had the right number of parameters. Were any of its types bad? // If any parameter type of the lambda is an error type then suppress // further errors. We've already reported errors on the bad type. if (anonymousFunction.HasExplicitlyTypedParameterList) { for (int i = 0; i < anonymousFunction.ParameterCount; ++i) { if (anonymousFunction.ParameterType(i).IsErrorType()) { return; } } } // The parameter list exists and had the right number of parameters. Were any of its types // mismatched with the delegate parameter types? // The simplest possible case is (x, y, z)=>whatever where the target type has a ref or out parameter. var delegateParameters = delegateType.DelegateParameters(); if (reason == LambdaConversionResult.RefInImplicitlyTypedLambda) { for (int i = 0; i < anonymousFunction.ParameterCount; ++i) { var delegateRefKind = delegateParameters[i].RefKind; if (delegateRefKind != RefKind.None) { // Parameter {0} must be declared with the '{1}' keyword Error(diagnostics, ErrorCode.ERR_BadParamRef, anonymousFunction.ParameterLocation(i), i + 1, delegateRefKind.ToDisplayString()); } } return; } // See the comments in IsAnonymousFunctionCompatibleWithDelegate for an explanation of this one. if (reason == LambdaConversionResult.StaticTypeInImplicitlyTypedLambda) { for (int i = 0; i < anonymousFunction.ParameterCount; ++i) { if (delegateParameters[i].Type.IsStatic) { // {0}: Static types cannot be used as parameter Error(diagnostics, ErrorCode.ERR_ParameterIsStaticClass, anonymousFunction.ParameterLocation(i), delegateParameters[i].Type); } } return; } // Otherwise, there might be a more complex reason why the parameter types are mismatched. if (reason == LambdaConversionResult.MismatchedParameterType) { // Cannot convert {0} to delegate type '{1}' because the parameter types do not match the delegate parameter types Error(diagnostics, ErrorCode.ERR_CantConvAnonMethParams, syntax, id, targetType); Debug.Assert(anonymousFunction.ParameterCount == delegateParameters.Length); for (int i = 0; i < anonymousFunction.ParameterCount; ++i) { var lambdaParameterType = anonymousFunction.ParameterType(i); if (lambdaParameterType.IsErrorType()) { continue; } var lambdaParameterLocation = anonymousFunction.ParameterLocation(i); var lambdaRefKind = anonymousFunction.RefKind(i); var delegateParameterType = delegateParameters[i].Type; var delegateRefKind = delegateParameters[i].RefKind; if (!lambdaParameterType.Equals(delegateParameterType, ignoreCustomModifiers: true, ignoreDynamic: true)) { SymbolDistinguisher distinguisher = new SymbolDistinguisher(this.Compilation, lambdaParameterType, delegateParameterType); // Parameter {0} is declared as type '{1}{2}' but should be '{3}{4}' Error(diagnostics, ErrorCode.ERR_BadParamType, lambdaParameterLocation, i + 1, lambdaRefKind.ToPrefix(), distinguisher.First, delegateRefKind.ToPrefix(), distinguisher.Second); } else if (lambdaRefKind != delegateRefKind) { if (delegateRefKind == RefKind.None) { // Parameter {0} should not be declared with the '{1}' keyword Error(diagnostics, ErrorCode.ERR_BadParamExtraRef, lambdaParameterLocation, i + 1, lambdaRefKind.ToDisplayString()); } else { // Parameter {0} must be declared with the '{1}' keyword Error(diagnostics, ErrorCode.ERR_BadParamRef, lambdaParameterLocation, i + 1, delegateRefKind.ToDisplayString()); } } } return; } if (reason == LambdaConversionResult.BindingFailed) { var bindingResult = anonymousFunction.Bind(delegateType); Debug.Assert(ErrorFacts.PreventsSuccessfulDelegateConversion(bindingResult.Diagnostics)); diagnostics.AddRange(bindingResult.Diagnostics); return; } // UNDONE: LambdaConversionResult.VoidExpressionLambdaMustBeStatementExpression: Debug.Assert(false, "Missing case in lambda conversion error reporting"); }
private UnboundLambda BindAnonymousFunction(CSharpSyntaxNode syntax, DiagnosticBag diagnostics) { Debug.Assert(syntax != null); Debug.Assert(syntax.IsAnonymousFunction()); var results = AnalyzeAnonymousFunction(syntax, diagnostics); var refKinds = results.Item1; var types = results.Item2; var names = results.Item3; var isAsync = results.Item4; if (!types.IsDefault) { foreach (var type in types) { // UNDONE: Where do we report improper use of pointer types? if ((object)type != null && type.IsStatic) { Error(diagnostics, ErrorCode.ERR_ParameterIsStaticClass, syntax, type); } } } var lambda = new UnboundLambda(syntax, this, refKinds, types, names, isAsync); if (!names.IsDefault) { var binder = new LocalScopeBinder(this.ContainingMemberOrLambda as MethodSymbol, this); for (int n = 0; n < names.Length; ++n) { string name = lambda.ParameterName(n); binder.ValidateLambdaParameterNameConflictsInScope(lambda.ParameterLocation(n), name, diagnostics); } } return lambda; }
private UnboundLambda BindAnonymousFunction(CSharpSyntaxNode syntax, DiagnosticBag diagnostics) { Debug.Assert(syntax != null); Debug.Assert(syntax.IsAnonymousFunction()); var results = AnalyzeAnonymousFunction(syntax, diagnostics); var refKinds = results.Item1; var types = results.Item2; var names = results.Item3; var isAsync = results.Item4; if (!types.IsDefault) { foreach (var type in types) { // UNDONE: Where do we report improper use of pointer types? if ((object)type != null && type.IsStatic) { Error(diagnostics, ErrorCode.ERR_ParameterIsStaticClass, syntax, type); } } } var lambda = new UnboundLambda(syntax, this, refKinds, types, names, isAsync); if (!names.IsDefault) { var binder = new LocalScopeBinder(this); var pNames = PooledHashSet<string>.GetInstance(); for (int i = 0; i < lambda.ParameterCount; i ++) { var name = lambda.ParameterName(i); if (string.IsNullOrEmpty(name)) { continue; } if (pNames.Contains(name)) { // The parameter name '{0}' is a duplicate diagnostics.Add(ErrorCode.ERR_DuplicateParamName, lambda.ParameterLocation(i), name); } else { pNames.Add(name); binder.ValidateLambdaParameterNameConflictsInScope(lambda.ParameterLocation(i), name, diagnostics); } } pNames.Free(); } return lambda; }