public WithQueryLambdaParametersBinder(LambdaSymbol lambdaSymbol, RangeVariableMap rangeVariableMap, Binder next) : base(lambdaSymbol, next) { _rangeVariableMap = rangeVariableMap; _parameterMap = new MultiDictionary<string, RangeVariableSymbol>(); foreach (var qv in rangeVariableMap.Keys) { _parameterMap.Add(qv.Name, qv); } }
public WithLambdaParametersBinder(LambdaSymbol lambdaSymbol, Binder enclosing) : base(lambdaSymbol, enclosing) { ForceSingleDefinitions(lambdaSymbol.Parameters); this.lambdaSymbol = lambdaSymbol; this.parameterMap = new MultiDictionary<string, ParameterSymbol>(); foreach (var parameter in lambdaSymbol.Parameters) { this.parameterMap.Add(parameter.Name, parameter); } }
public WithLambdaParametersBinder(LambdaSymbol lambdaSymbol, Binder enclosing) : base(enclosing) { this.lambdaSymbol = lambdaSymbol; this.parameterMap = new MultiDictionary<string, ParameterSymbol>(); var parameters = lambdaSymbol.Parameters; if (!parameters.IsDefaultOrEmpty) { RecordDefinitions(parameters); foreach (var parameter in lambdaSymbol.Parameters) { this.parameterMap.Add(parameter.Name, parameter); } } }
protected override BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics) { if (this.IsExpressionLambda) { var body = (ExpressionSyntax)this.Body; return lambdaBodyBinder.BindLambdaExpressionAsBlock(body, diagnostics); } else { return lambdaBodyBinder.BindBlock((BlockSyntax)this.Body, diagnostics); } }
private static string GetLambdaSortString(LambdaSymbol lambda) { var builder = PooledStringBuilder.GetInstance(); foreach (var parameter in lambda.Parameters) { builder.Builder.Append(parameter.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat)); } if ((object)lambda.ReturnType != null) { builder.Builder.Append(lambda.ReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)); } var result = builder.ToStringAndFree(); return result; }
public virtual Binder ParameterBinder(LambdaSymbol lambdaSymbol, Binder binder) { return new WithLambdaParametersBinder(lambdaSymbol, binder); }
private BoundLambda ReallyInferReturnType(NamedTypeSymbol delegateType) { var diagnostics = DiagnosticBag.GetInstance(); var parameters = DelegateParameters(delegateType); var lambdaSymbol = new LambdaSymbol(binder.Compilation, binder.ContainingMemberOrLambda, _unboundLambda, parameters, returnType: null); Binder lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder)); var block = BindLambdaBody(lambdaSymbol, ref lambdaBodyBinder, diagnostics); var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: true) { WasCompilerGenerated = _unboundLambda.WasCompilerGenerated }; HashSet<DiagnosticInfo> useSiteDiagnostics = null; // TODO: figure out if this should be somehow merged into BoundLambda.Diagnostics. lambdaSymbol.SetInferredReturnType(result.InferredReturnType(ref useSiteDiagnostics) ?? new ExtendedErrorTypeSymbol(binder.Compilation, string.Empty, 0, null)); return result; }
private BoundLambda ReallyBind(NamedTypeSymbol delegateType) { var returnType = DelegateReturnType(delegateType); LambdaSymbol lambdaSymbol; Binder lambdaBodyBinder; BoundBlock block; var diagnostics = DiagnosticBag.GetInstance(); // when binding for real (not for return inference), there is still // a good chance that we could reuse a body of a lambda previously bound for // return type inference. MethodSymbol cacheKey = GetCacheKey(delegateType); BoundLambda returnInferenceLambda; if (_returnInferenceCache.TryGetValue(cacheKey, out returnInferenceLambda) && returnInferenceLambda.InferredFromSingleType) { var lambdaSym = returnInferenceLambda.Symbol; var lambdaRetType = lambdaSym.ReturnType; if (lambdaRetType == returnType) { lambdaSymbol = lambdaSym; lambdaBodyBinder = returnInferenceLambda.Binder; block = returnInferenceLambda.Body; diagnostics.AddRange(returnInferenceLambda.Diagnostics); goto haveLambdaBodyAndBinders; } } var parameters = DelegateParameters(delegateType); lambdaSymbol = new LambdaSymbol(binder.Compilation, binder.ContainingMemberOrLambda, _unboundLambda, parameters, returnType); lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder)); block = BindLambdaBody(lambdaSymbol, ref lambdaBodyBinder, diagnostics); ValidateUnsafeParameters(diagnostics, parameters); haveLambdaBodyAndBinders: bool reachableEndpoint = ControlFlowPass.Analyze(binder.Compilation, lambdaSymbol, block, diagnostics); if (reachableEndpoint) { if (DelegateNeedsReturn(delegateType)) { // Not all code paths return a value in {0} of type '{1}' diagnostics.Add(ErrorCode.ERR_AnonymousReturnExpected, lambdaSymbol.Locations[0], this.MessageID.Localize(), delegateType); } else { block = FlowAnalysisPass.AppendImplicitReturn(block, lambdaSymbol, _unboundLambda.Syntax); } } if (IsAsync && !ErrorFacts.PreventsSuccessfulDelegateConversion(diagnostics)) { if ((object)returnType != null && // Can be null if "delegateType" is not actually a delegate type. returnType.SpecialType != SpecialType.System_Void && returnType != binder.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task) && returnType.OriginalDefinition != binder.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T)) { // Cannot convert async {0} to delegate type '{1}'. An async {0} may return void, Task or Task<T>, none of which are convertible to '{1}'. diagnostics.Add(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, lambdaSymbol.Locations[0], lambdaSymbol.MessageID.Localize(), delegateType); } } if (IsAsync) { Debug.Assert(lambdaSymbol.IsAsync); SourceMemberMethodSymbol.ReportAsyncParameterErrors(lambdaSymbol, diagnostics, lambdaSymbol.Locations[0]); } var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: false) { WasCompilerGenerated = _unboundLambda.WasCompilerGenerated }; return result; }
protected abstract BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics);
protected override BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics) { return _bodyFactory(lambdaSymbol, ref lambdaBodyBinder, diagnostics); }
public override Binder ParameterBinder(LambdaSymbol lambdaSymbol, Binder binder) { return new WithQueryLambdaParametersBinder(lambdaSymbol, _rangeVariableMap, binder); }
protected override BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ExecutableCodeBinder lambdaBodyBinder, DiagnosticBag diagnostics) { return bodyResolver(lambdaSymbol, lambdaBodyBinder, diagnostics); }
protected override BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ExecutableCodeBinder lambdaBodyBinder, DiagnosticBag diagnostics) { return this.IsExpressionLambda ? lambdaBodyBinder.BindExpressionLambdaBody((ExpressionSyntax)this.Body, diagnostics) : lambdaBodyBinder.BindBlock((BlockSyntax)this.Body, diagnostics); }
protected abstract BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ExecutableCodeBinder binder, DiagnosticBag diagnostics);
private BoundLambda ReallyBind(NamedTypeSymbol delegateType) { var invokeMethod = DelegateInvokeMethod(delegateType); RefKind refKind; var returnType = DelegateReturnType(invokeMethod, out refKind); LambdaSymbol lambdaSymbol; Binder lambdaBodyBinder; BoundBlock block; var diagnostics = DiagnosticBag.GetInstance(); // when binding for real (not for return inference), there is still // a good chance that we could reuse a body of a lambda previously bound for // return type inference. MethodSymbol cacheKey = GetCacheKey(delegateType); BoundLambda returnInferenceLambda; if (_returnInferenceCache.TryGetValue(cacheKey, out returnInferenceLambda) && returnInferenceLambda.InferredFromSingleType && returnInferenceLambda.Symbol.ReturnType == returnType) { lambdaSymbol = returnInferenceLambda.Symbol; Debug.Assert(lambdaSymbol.RefKind == refKind); lambdaBodyBinder = returnInferenceLambda.Binder; block = returnInferenceLambda.Body; diagnostics.AddRange(returnInferenceLambda.Diagnostics); goto haveLambdaBodyAndBinders; } var parameters = DelegateParameters(invokeMethod); lambdaSymbol = new LambdaSymbol( binder.Compilation, binder.ContainingMemberOrLambda, _unboundLambda, parameters, refKind, returnType); lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder)); block = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics); ((ExecutableCodeBinder)lambdaBodyBinder).ValidateIteratorMethods(diagnostics); ValidateUnsafeParameters(diagnostics, parameters); haveLambdaBodyAndBinders: bool reachableEndpoint = ControlFlowPass.Analyze(binder.Compilation, lambdaSymbol, block, diagnostics); if (reachableEndpoint) { if (DelegateNeedsReturn(invokeMethod)) { // Not all code paths return a value in {0} of type '{1}' diagnostics.Add(ErrorCode.ERR_AnonymousReturnExpected, lambdaSymbol.Locations[0], this.MessageID.Localize(), delegateType); } else { block = FlowAnalysisPass.AppendImplicitReturn(block, lambdaSymbol); } } if (IsAsync && !ErrorFacts.PreventsSuccessfulDelegateConversion(diagnostics)) { if ((object)returnType != null && // Can be null if "delegateType" is not actually a delegate type. returnType.SpecialType != SpecialType.System_Void && !returnType.IsNonGenericTaskType(binder.Compilation) && !returnType.IsGenericTaskType(binder.Compilation)) { // Cannot convert async {0} to delegate type '{1}'. An async {0} may return void, Task or Task<T>, none of which are convertible to '{1}'. diagnostics.Add(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, lambdaSymbol.Locations[0], lambdaSymbol.MessageID.Localize(), delegateType); } } if (IsAsync) { Debug.Assert(lambdaSymbol.IsAsync); SourceMemberMethodSymbol.ReportAsyncParameterErrors(lambdaSymbol.Parameters, diagnostics, lambdaSymbol.Locations[0]); } // This is an attempt to get a repro for https://devdiv.visualstudio.com/DevDiv/_workitems?id=278481 if ((object)returnType != null && returnType.SpecialType != SpecialType.System_Void && !block.HasErrors && !diagnostics.HasAnyResolvedErrors() && block.Statements.Length > 0) { BoundStatement first = block.Statements[0]; if (first.Kind == BoundKind.ReturnStatement) { var returnStmt = (BoundReturnStatement)first; if (returnStmt.ExpressionOpt != null && (object)returnStmt.ExpressionOpt.Type == null) { throw ExceptionUtilities.Unreachable; } } } var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: false) { WasCompilerGenerated = _unboundLambda.WasCompilerGenerated }; return result; }