public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray<RangeVariableSymbol> parameters, LambdaBodyResolver bodyResolver) : base(unbound, binder) { this.parameters = parameters; this.bodyResolver = bodyResolver; this.rangeVariableMap = rangeVariableMap; }
public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray<RangeVariableSymbol> parameters, ExpressionSyntax body) : this(unbound, binder, rangeVariableMap, parameters, (LambdaSymbol lambdaSymbol, ExecutableCodeBinder lambdaBodyBinder, DiagnosticBag diagnostics) => { BoundExpression expression = lambdaBodyBinder.BindValue(body, diagnostics, BindValueKind.RValue); return lambdaBodyBinder.WrapExpressionLambdaBody(expression, body, diagnostics); }) { }
public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray <RangeVariableSymbol> parameters, LambdaBodyResolver bodyResolver) : base(unbound, binder) { this.parameters = parameters; this.bodyResolver = bodyResolver; this.rangeVariableMap = rangeVariableMap; }
public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray <RangeVariableSymbol> parameters, ExpressionSyntax body) : this(unbound, binder, rangeVariableMap, parameters, (LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics) => { lambdaBodyBinder = new ScopedExpressionBinder(lambdaBodyBinder, body); return(lambdaBodyBinder.BindLambdaExpressionAsBlock(body, diagnostics)); }) { }
public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray <RangeVariableSymbol> parameters, ExpressionSyntax body) : this(unbound, binder, rangeVariableMap, parameters, (LambdaSymbol lambdaSymbol, ExecutableCodeBinder lambdaBodyBinder, DiagnosticBag diagnostics) => { BoundExpression expression = lambdaBodyBinder.BindValue(body, diagnostics, BindValueKind.RValue); return(lambdaBodyBinder.WrapExpressionLambdaBody(expression, body, diagnostics)); }) { }
public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray<RangeVariableSymbol> parameters, ExpressionSyntax body) : this(unbound, binder, rangeVariableMap, parameters, (LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics) => { lambdaBodyBinder = new ScopedExpressionBinder(lambdaBodyBinder, body); return lambdaBodyBinder.BindLambdaExpressionAsBlock(body, diagnostics); }) { }
public UnboundLambdaState(Binder binder, UnboundLambda unboundLambdaOpt) { Debug.Assert(binder != null); // might be initialized later (for query lambdas) _unboundLambda = unboundLambdaOpt; this.binder = binder; }
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); }
public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray<RangeVariableSymbol> parameters, ExpressionSyntax body, TypeSyntax castTypeSyntax, TypeSymbol castType) : this(unbound, binder, rangeVariableMap, parameters, (LambdaSymbol lambdaSymbol, ExecutableCodeBinder lambdaBodyBinder, DiagnosticBag diagnostics) => { BoundExpression expression = lambdaBodyBinder.BindValue(body, diagnostics, BindValueKind.RValue); Debug.Assert((object)castType != null); Debug.Assert(castTypeSyntax != null); // We transform the expression from "expr" to "expr.Cast<castTypeOpt>()". expression = lambdaBodyBinder.MakeQueryInvocation(body, expression, "Cast", castTypeSyntax, castType, diagnostics); return lambdaBodyBinder.WrapExpressionLambdaBody(expression, body, diagnostics); }) { }
private UnboundLambda MakeQueryUnboundLambda(CSharpSyntaxNode node, QueryUnboundLambdaState state) { Debug.Assert(node is ExpressionSyntax || LambdaUtilities.IsQueryPairLambda(node)); var lambda = new UnboundLambda(node, state, hasErrors: false) { WasCompilerGenerated = true }; state.SetUnboundLambda(lambda); return(lambda); }
UnboundLambda MakeQueryUnboundLambda(RangeVariableMap qvm, ImmutableArray <RangeVariableSymbol> parameters, CSharpSyntaxNode node, LambdaBodyResolver resolver) { var state = new QueryUnboundLambdaState(null, this, qvm, parameters, resolver); var lambda = new UnboundLambda(node, state, false) { WasCompilerGenerated = true }; state.SetUnboundLambda(lambda); return(lambda); }
public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray <RangeVariableSymbol> parameters, ExpressionSyntax body, TypeSyntax castTypeSyntax, TypeSymbol castType) : this(unbound, binder, rangeVariableMap, parameters, (LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics) => { BoundExpression expression = lambdaBodyBinder.BindValue(body, diagnostics, BindValueKind.RValue); Debug.Assert((object)castType != null); Debug.Assert(castTypeSyntax != null); // We transform the expression from "expr" to "expr.Cast<castTypeOpt>()". expression = lambdaBodyBinder.MakeQueryInvocation(body, expression, "Cast", castTypeSyntax, castType, diagnostics); return(lambdaBodyBinder.CreateBlockFromExpression(lambdaBodyBinder.Locals, expression, body, diagnostics)); }) { }
UnboundLambda MakeQueryUnboundLambda(RangeVariableMap qvm, ImmutableArray <RangeVariableSymbol> parameters, ExpressionSyntax expression, TypeSyntax castTypeSyntaxOpt, TypeSymbol castTypeOpt) { var state = ((object)castTypeOpt == null) ? new QueryUnboundLambdaState(null, this, qvm, parameters, expression) : new QueryUnboundLambdaState(null, this, qvm, parameters, expression, castTypeSyntaxOpt, castTypeOpt); var lambda = new UnboundLambda(expression, state, false) { WasCompilerGenerated = true }; state.SetUnboundLambda(lambda); return(lambda); }
internal PlainUnboundLambdaState( UnboundLambda unboundLambda, Binder binder, ImmutableArray <string> parameterNames, ImmutableArray <TypeSymbol> parameterTypes, ImmutableArray <RefKind> parameterRefKinds, bool isAsync) : base(unboundLambda, binder) { this.parameterNames = parameterNames; this.parameterTypes = parameterTypes; this.parameterRefKinds = parameterRefKinds; this.isAsync = isAsync; }
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); }
public static LambdaConversionResult IsAnonymousFunctionCompatibleWithType(UnboundLambda anonymousFunction, TypeSymbol type) { Debug.Assert((object)anonymousFunction != null); Debug.Assert((object)type != null); if (type.IsDelegateType()) { return(IsAnonymousFunctionCompatibleWithDelegate(anonymousFunction, type)); } else if (type.IsExpressionTree()) { return(IsAnonymousFunctionCompatibleWithExpressionTree(anonymousFunction, (NamedTypeSymbol)type)); } return(LambdaConversionResult.BadTargetType); }
public override LambdaConversionResult IsAnonymousFunctionCompatibleWithType(UnboundLambda anonymousFunction, TypeSymbol type) { var res = base.IsAnonymousFunctionCompatibleWithType(anonymousFunction, type); if (res == LambdaConversionResult.BadTargetType && _binder.Compilation.Options.HasRuntime) { if (type == Compilation.CodeBlockType() || type == Compilation.UsualType() || type.IsObjectType()) { return(LambdaConversionResult.Success); } var conv = Compilation.ClassifyConversion(Compilation.CodeBlockType(), type); if (conv.Exists) { return(LambdaConversionResult.Success); } } return(res); }
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 static LambdaConversionResult IsAnonymousFunctionCompatibleWithDelegate(UnboundLambda anonymousFunction, TypeSymbol type) { Debug.Assert((object)anonymousFunction != null); Debug.Assert((object)type != null); // SPEC: An anonymous-method-expression or lambda-expression is classified as an anonymous function. // SPEC: The expression does not have a type but can be implicitly converted to a compatible delegate // SPEC: type or expression tree type. Specifically, a delegate type D is compatible with an // SPEC: anonymous function F provided: var delegateType = (NamedTypeSymbol)type; var invokeMethod = delegateType.DelegateInvokeMethod; if ((object)invokeMethod == null || invokeMethod.HasUseSiteError) { return(LambdaConversionResult.BadTargetType); } var delegateParameters = invokeMethod.Parameters; // SPEC: If F contains an anonymous-function-signature, then D and F have the same number of parameters. // SPEC: If F does not contain an anonymous-function-signature, then D may have zero or more parameters // SPEC: of any type, as long as no parameter of D has the out parameter modifier. if (anonymousFunction.HasSignature) { if (anonymousFunction.ParameterCount != invokeMethod.ParameterCount) { return(LambdaConversionResult.BadParameterCount); } // SPEC: If F has an explicitly typed parameter list, each parameter in D has the same type // SPEC: and modifiers as the corresponding parameter in F. // SPEC: If F has an implicitly typed parameter list, D has no ref or out parameters. if (anonymousFunction.HasExplicitlyTypedParameterList) { for (int p = 0; p < delegateParameters.Length; ++p) { if (delegateParameters[p].RefKind != anonymousFunction.RefKind(p) || !delegateParameters[p].Type.Equals(anonymousFunction.ParameterType(p), ignoreCustomModifiersAndArraySizesAndLowerBounds: true, ignoreDynamic: true)) { return(LambdaConversionResult.MismatchedParameterType); } } } else { for (int p = 0; p < delegateParameters.Length; ++p) { if (delegateParameters[p].RefKind != RefKind.None) { return(LambdaConversionResult.RefInImplicitlyTypedLambda); } } // In C# it is not possible to make a delegate type // such that one of its parameter types is a static type. But static types are // in metadata just sealed abstract types; there is nothing stopping someone in // another language from creating a delegate with a static type for a parameter, // though the only argument you could pass for that parameter is null. // // In the native compiler we forbid conversion of an anonymous function that has // an implicitly-typed parameter list to a delegate type that has a static type // for a formal parameter type. However, we do *not* forbid it for an explicitly- // typed lambda (because we already require that the explicitly typed parameter not // be static) and we do not forbid it for an anonymous method with the entire // parameter list missing (because the body cannot possibly have a parameter that // is of static type, even though this means that we will be generating a hidden // method with a parameter of static type.) // // We also allow more exotic situations to work in the native compiler. For example, // though it is not possible to convert x=>{} to Action<GC>, it is possible to convert // it to Action<List<GC>> should there be a language that allows you to construct // a variable of that type. // // We might consider beefing up this rule to disallow a conversion of *any* anonymous // function to *any* delegate that has a static type *anywhere* in the parameter list. for (int p = 0; p < delegateParameters.Length; ++p) { if (delegateParameters[p].Type.IsStatic) { return(LambdaConversionResult.StaticTypeInImplicitlyTypedLambda); } } } } else { for (int p = 0; p < delegateParameters.Length; ++p) { if (delegateParameters[p].RefKind == RefKind.Out) { return(LambdaConversionResult.MissingSignatureWithOutParameter); } } } // Ensure the body can be converted to that delegate type var bound = anonymousFunction.Bind(delegateType); if (ErrorFacts.PreventsSuccessfulDelegateConversion(bound.Diagnostics)) { return(LambdaConversionResult.BindingFailed); } return(LambdaConversionResult.Success); }
internal void SetUnboundLambda(UnboundLambda unbound) { Debug.Assert(base.unboundLambda == null); base.unboundLambda = unbound; }
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 MakeQueryUnboundLambda(CSharpSyntaxNode node, QueryUnboundLambdaState state) { Debug.Assert(node is ExpressionSyntax || LambdaUtilities.IsQueryPairLambda(node)); var lambda = new UnboundLambda(node, state, hasErrors: false) { WasCompilerGenerated = true }; state.SetUnboundLambda(lambda); 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"); }
public void SetUnboundLambda(UnboundLambda unbound) { Debug.Assert(unbound != null); Debug.Assert(_unboundLambda == null); _unboundLambda = unbound; }
public UnboundLambdaState(UnboundLambda unboundLambda, Binder binder) { this.unboundLambda = unboundLambda; this.binder = binder; }
public static LambdaConversionResult IsAnonymousFunctionCompatibleWithType(UnboundLambda anonymousFunction, TypeSymbol type) { Debug.Assert((object)anonymousFunction != null); Debug.Assert((object)type != null); if (type.IsDelegateType()) { return IsAnonymousFunctionCompatibleWithDelegate(anonymousFunction, type); } else if (type.IsExpressionTree()) { return IsAnonymousFunctionCompatibleWithExpressionTree(anonymousFunction, (NamedTypeSymbol)type); } return LambdaConversionResult.BadTargetType; }
private static LambdaConversionResult IsAnonymousFunctionCompatibleWithDelegate(UnboundLambda anonymousFunction, TypeSymbol type) { Debug.Assert((object)anonymousFunction != null); Debug.Assert((object)type != null); // SPEC: An anonymous-method-expression or lambda-expression is classified as an anonymous function. // SPEC: The expression does not have a type but can be implicitly converted to a compatible delegate // SPEC: type or expression tree type. Specifically, a delegate type D is compatible with an // SPEC: anonymous function F provided: var delegateType = (NamedTypeSymbol)type; var invokeMethod = delegateType.DelegateInvokeMethod; if ((object)invokeMethod == null || invokeMethod.HasUseSiteError) { return LambdaConversionResult.BadTargetType; } var delegateParameters = invokeMethod.Parameters; // SPEC: If F contains an anonymous-function-signature, then D and F have the same number of parameters. // SPEC: If F does not contain an anonymous-function-signature, then D may have zero or more parameters // SPEC: of any type, as long as no parameter of D has the out parameter modifier. if (anonymousFunction.HasSignature) { if (anonymousFunction.ParameterCount != invokeMethod.ParameterCount) { return LambdaConversionResult.BadParameterCount; } // SPEC: If F has an explicitly typed parameter list, each parameter in D has the same type // SPEC: and modifiers as the corresponding parameter in F. // SPEC: If F has an implicitly typed parameter list, D has no ref or out parameters. if (anonymousFunction.HasExplicitlyTypedParameterList) { for (int p = 0; p < delegateParameters.Length; ++p) { if (delegateParameters[p].RefKind != anonymousFunction.RefKind(p) || !delegateParameters[p].Type.Equals(anonymousFunction.ParameterType(p), ignoreCustomModifiers: true, ignoreDynamic: true)) { return LambdaConversionResult.MismatchedParameterType; } } } else { for (int p = 0; p < delegateParameters.Length; ++p) { if (delegateParameters[p].RefKind != RefKind.None) { return LambdaConversionResult.RefInImplicitlyTypedLambda; } } // In C# it is not possible to make a delegate type // such that one of its parameter types is a static type. But static types are // in metadata just sealed abstract types; there is nothing stopping someone in // another language from creating a delegate with a static type for a parameter, // though the only argument you could pass for that parameter is null. // // In the native compiler we forbid conversion of an anonymous function that has // an implicitly-typed parameter list to a delegate type that has a static type // for a formal parameter type. However, we do *not* forbid it for an explicitly- // typed lambda (because we already require that the explicitly typed parameter not // be static) and we do not forbid it for an anonymous method with the entire // parameter list missing (because the body cannot possibly have a parameter that // is of static type, even though this means that we will be generating a hidden // method with a parameter of static type.) // // We also allow more exotic situations to work in the native compiler. For example, // though it is not possible to convert x=>{} to Action<GC>, it is possible to convert // it to Action<List<GC>> should there be a language that allows you to construct // a variable of that type. // // We might consider beefing up this rule to disallow a conversion of *any* anonymous // function to *any* delegate that has a static type *anywhere* in the parameter list. for (int p = 0; p < delegateParameters.Length; ++p) { if (delegateParameters[p].Type.IsStatic) { return LambdaConversionResult.StaticTypeInImplicitlyTypedLambda; } } } } else { for (int p = 0; p < delegateParameters.Length; ++p) { if (delegateParameters[p].RefKind == RefKind.Out) { return LambdaConversionResult.MissingSignatureWithOutParameter; } } } // Ensure the body can be converted to that delegate type var bound = anonymousFunction.Bind(delegateType); if (ErrorFacts.PreventsSuccessfulDelegateConversion(bound.Diagnostics)) { return LambdaConversionResult.BindingFailed; } return LambdaConversionResult.Success; }
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 BoundExpression BindCodeblock(SyntaxNode syntax, UnboundLambda unboundLambda, Conversion conversion, bool isCast, TypeSymbol destination, DiagnosticBag diagnostics) { if (!Compilation.Options.HasRuntime) { return(null); } var isCodeblock = syntax.XIsCodeBlock; if (!isCodeblock) { isCodeblock = !destination.IsDelegateType() && !destination.IsExpressionTree(); } if (!isCodeblock) { return(null); } Conversion conv = Conversion.ImplicitReference; if (destination != Compilation.CodeBlockType() && !destination.IsObjectType()) { HashSet <DiagnosticInfo> useSiteDiagnostics = null; conv = Conversions.ClassifyConversionFromType(Compilation.CodeBlockType(), destination, ref useSiteDiagnostics); diagnostics.Add(syntax, useSiteDiagnostics); } if (Compilation.Options.HasRuntime) { Debug.Assert(destination == Compilation.CodeBlockType() || conv.Exists); } if (!syntax.XIsCodeBlock && !Compilation.Options.MacroScript && !syntax.XNode.IsAliasExpression()) { Error(diagnostics, ErrorCode.ERR_CodeblockWithLambdaSyntax, syntax); } AnonymousTypeManager manager = this.Compilation.AnonymousTypeManager; var delegateSignature = new TypeSymbol[unboundLambda.ParameterCount + 1]; var usualType = this.Compilation.UsualType(); for (int i = 0; i < delegateSignature.Length; i++) { delegateSignature[i] = usualType; } NamedTypeSymbol cbType = manager.ConstructCodeblockTypeSymbol(delegateSignature, syntax.Location); var delType = manager.GetCodeblockDelegateType(cbType); var _boundLambda = unboundLambda.Bind(delType); diagnostics.AddRange(_boundLambda.Diagnostics); var cbDel = new BoundConversion( syntax, _boundLambda, conversion, @checked: false, explicitCastInCode: false, constantValueOpt: ConstantValue.NotAvailable, type: delType) { WasCompilerGenerated = unboundLambda.WasCompilerGenerated }; var cbSrc = new BoundLiteral(syntax, ConstantValue.Create(syntax.XCodeBlockSource), Compilation.GetSpecialType(SpecialType.System_String)); BoundExpression cbInst = new BoundAnonymousObjectCreationExpression(syntax, cbType.InstanceConstructors[0], new BoundExpression[] { cbDel, cbSrc }.ToImmutableArrayOrEmpty(), System.Collections.Immutable.ImmutableArray <BoundAnonymousPropertyDeclaration> .Empty, cbType) { WasCompilerGenerated = unboundLambda.WasCompilerGenerated };; if (conv != Conversion.ImplicitReference) { cbInst = new BoundConversion(syntax, cbInst, Conversion.ImplicitReference, false, false, ConstantValue.NotAvailable, Compilation.CodeBlockType()) { WasCompilerGenerated = unboundLambda.WasCompilerGenerated };; } if (!conv.IsValid || (!isCast && conv.IsExplicit)) { GenerateImplicitConversionError(diagnostics, syntax, conv, cbInst, destination); return(new BoundConversion( syntax, cbInst, conv, false, explicitCastInCode: isCast, constantValueOpt: ConstantValue.NotAvailable, type: destination, hasErrors: true) { WasCompilerGenerated = unboundLambda.WasCompilerGenerated }); } return(new BoundConversion( syntax, cbInst, conv, false, explicitCastInCode: isCast, constantValueOpt: ConstantValue.NotAvailable, type: destination) { WasCompilerGenerated = unboundLambda.WasCompilerGenerated }); }
private static LambdaConversionResult IsAnonymousFunctionCompatibleWithExpressionTree(UnboundLambda anonymousFunction, NamedTypeSymbol type) { Debug.Assert((object)anonymousFunction != null); Debug.Assert((object)type != null); Debug.Assert(type.IsExpressionTree()); // SPEC OMISSION: // // The C# 3 spec said that anonymous methods and statement lambdas are *convertible* to expression tree // types if the anonymous method/statement lambda is convertible to its delegate type; however, actually // *using* such a conversion is an error. However, that is not what we implemented. In C# 3 we implemented // that an anonymous method is *not convertible* to an expression tree type, period. (Statement lambdas // used the rule described in the spec.) // // This appears to be a spec omission; the intention is to make old-style anonymous methods not // convertible to expression trees. var delegateType = type.TypeArgumentsNoUseSiteDiagnostics[0]; if (!delegateType.IsDelegateType()) { return(LambdaConversionResult.ExpressionTreeMustHaveDelegateTypeArgument); } if (anonymousFunction.Syntax.Kind() == SyntaxKind.AnonymousMethodExpression) { return(LambdaConversionResult.ExpressionTreeFromAnonymousMethod); } return(IsAnonymousFunctionCompatibleWithDelegate(anonymousFunction, delegateType)); }
internal PlainUnboundLambdaState( UnboundLambda unboundLambda, Binder binder, ImmutableArray<string> parameterNames, ImmutableArray<TypeSymbol> parameterTypes, ImmutableArray<RefKind> parameterRefKinds, bool isAsync) : base(binder, unboundLambda) { _parameterNames = parameterNames; _parameterTypes = parameterTypes; _parameterRefKinds = parameterRefKinds; _isAsync = isAsync; }
private static LambdaConversionResult IsAnonymousFunctionCompatibleWithExpressionTree(UnboundLambda anonymousFunction, NamedTypeSymbol type) { Debug.Assert((object)anonymousFunction != null); Debug.Assert((object)type != null); Debug.Assert(type.IsExpressionTree()); // SPEC OMISSION: // // The C# 3 spec said that anonymous methods and statement lambdas are *convertible* to expression tree // types if the anonymous method/statement lambda is convertible to its delegate type; however, actually // *using* such a conversion is an error. However, that is not what we implemented. In C# 3 we implemented // that an anonymous method is *not convertible* to an expression tree type, period. (Statement lambdas // used the rule described in the spec.) // // This appears to be a spec omission; the intention is to make old-style anonymous methods not // convertible to expression trees. var delegateType = type.TypeArgumentsNoUseSiteDiagnostics[0]; if (!delegateType.IsDelegateType()) { return LambdaConversionResult.ExpressionTreeMustHaveDelegateTypeArgument; } if (anonymousFunction.Syntax.Kind == SyntaxKind.AnonymousMethodExpression) { return LambdaConversionResult.ExpressionTreeFromAnonymousMethod; } return IsAnonymousFunctionCompatibleWithDelegate(anonymousFunction, delegateType); }
public override BoundNode VisitUnboundLambda(UnboundLambda node) { return VisitLambda(node.BindForErrorRecovery()); }
public override BoundNode VisitUnboundLambda(UnboundLambda node) { return(VisitLambda(node.BindForErrorRecovery())); }