internal SynthesizedLambdaMethod(NamedTypeSymbol containingType, MethodSymbol topLevelMethod, BoundLambda node, bool isStatic, TypeCompilationState compilationState) : base(containingType, node.Symbol, null, node.SyntaxTree.GetReference(node.Body.Syntax), node.Syntax.GetLocation(), GeneratedNames.MakeLambdaMethodName(topLevelMethod.Name, compilationState.GenerateTempNumber()), (containingType is LambdaFrame ? DeclarationModifiers.Internal : DeclarationModifiers.Private) | (isStatic ? DeclarationModifiers.Static : 0) | (node.Symbol.IsAsync ? DeclarationModifiers.Async : 0)) { TypeMap typeMap; ImmutableArray<TypeParameterSymbol> typeParameters; LambdaFrame lambdaFrame; if (!topLevelMethod.IsGenericMethod) { typeMap = TypeMap.Empty; typeParameters = ImmutableArray<TypeParameterSymbol>.Empty; } else if ((object)(lambdaFrame = this.ContainingType as LambdaFrame) != null) { typeMap = lambdaFrame.TypeMap; typeParameters = ImmutableArray<TypeParameterSymbol>.Empty; } else { typeMap = TypeMap.Empty.WithAlphaRename(topLevelMethod, this, out typeParameters); } AssignTypeMapAndTypeParameters(typeMap, typeParameters); }
public override BoundNode VisitLambda(BoundLambda node) { if (IsInside && !node.WasCompilerGenerated) { foreach (var parameter in node.Symbol.Parameters) { _variablesDeclared.Add(parameter); } } return base.VisitLambda(node); }
public override BoundNode VisitLambda(BoundLambda node) { var origLabels = this.currentLabels; var origSeenAwait = _seenAwait; this.currentLabels = null; _seenAwait = false; base.VisitLambda(node); this.currentLabels = origLabels; _seenAwait = origSeenAwait; return(null); }
public override BoundNode VisitLambda(BoundLambda node) { var oldContainingSymbol = _F.CurrentFunction; var oldAwaitFinallyFrame = _currentAwaitFinallyFrame; _F.CurrentFunction = node.Symbol; _currentAwaitFinallyFrame = new AwaitFinallyFrame(); var result = base.VisitLambda(node); _F.CurrentFunction = oldContainingSymbol; _currentAwaitFinallyFrame = oldAwaitFinallyFrame; return(result); }
public override BoundNode VisitLambda(BoundLambda node) { _sawLambdas = true; var oldContainingSymbol = _factory.CurrentMethod; try { _factory.CurrentMethod = node.Symbol; return(base.VisitLambda(node)); } finally { _factory.CurrentMethod = oldContainingSymbol; } }
public override BoundNode VisitLambda(BoundLambda node) { var oldContainingSymbol = this.F.CurrentMethod; var oldAwaitFinallyFrame = this.currentAwaitFinallyFrame; this.F.CurrentMethod = node.Symbol; this.currentAwaitFinallyFrame = new AwaitFinallyFrame(null, null); var result = base.VisitLambda(node); this.F.CurrentMethod = oldContainingSymbol; this.currentAwaitFinallyFrame = oldAwaitFinallyFrame; return(result); }
public override BoundNode VisitLambda(BoundLambda node) { _sawLambdas = true; CheckRefReadOnlySymbols(node.Symbol); var oldContainingSymbol = _factory.CurrentFunction; try { _factory.CurrentFunction = node.Symbol; return(base.VisitLambda(node)); } finally { _factory.CurrentFunction = oldContainingSymbol; } }
internal static BoundNode RewriteLambda(BoundLambda node, TypeCompilationState compilationState, TypeMap typeMap, int recursionDepth, BindingDiagnosticBag diagnostics) { try { var r = new ExpressionLambdaRewriter(compilationState, typeMap, node.Syntax, recursionDepth, diagnostics); var result = r.VisitLambdaInternal(node); if (!node.Type.Equals(result.Type, TypeCompareKind.IgnoreNullableModifiersForReferenceTypes)) { diagnostics.Add(ErrorCode.ERR_MissingPredefinedMember, node.Syntax.Location, r.ExpressionType, "Lambda"); } return(result); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) { diagnostics.Add(ex.Diagnostic); return(node); } }
internal static BoundNode RewriteLambda(BoundLambda node, TypeCompilationState compilationState, TypeMap typeMap, int recursionDepth, DiagnosticBag diagnostics) { try { var r = new ExpressionLambdaRewriter(compilationState, typeMap, node.Syntax, recursionDepth, diagnostics); var result = r.VisitLambdaInternal(node); if (node.Type != result.Type) { diagnostics.Add(ErrorCode.ERR_MissingPredefinedMember, node.Syntax.Location, r.ExpressionType, "Lambda"); } return(result); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) { diagnostics.Add(ex.Diagnostic); return(node); } }
public override BoundNode VisitLambda(BoundLambda node) { Debug.Assert((object)node.Symbol != null); SeenLambda = true; var oldParent = currentParent; var oldBlock = currentBlock; currentParent = node.Symbol; currentBlock = node.Body; blockParent[currentBlock] = oldBlock; var wasInExpressionLambda = inExpressionLambda; inExpressionLambda = inExpressionLambda || node.Type.IsExpressionTree(); // for the purpose of constructing frames parameters are scoped as if they are inside the lambda block foreach (var parameter in node.Symbol.Parameters) { variableBlock[parameter] = currentBlock; if (inExpressionLambda) { declaredInsideExpressionLambda.Add(parameter); } } if (!node.Body.LocalsOpt.IsDefaultOrEmpty) { foreach (var local in node.Body.LocalsOpt) { variableBlock[local] = currentBlock; if (inExpressionLambda) { declaredInsideExpressionLambda.Add(local); } } } var result = base.VisitBlock(node.Body); inExpressionLambda = wasInExpressionLambda; currentParent = oldParent; currentBlock = oldBlock; return(result); }
private BoundLambda ReallyInferReturnType(NamedTypeSymbol delegateType, ImmutableArray <TypeSymbol> parameterTypes, ImmutableArray <RefKind> parameterRefKinds) { var diagnostics = DiagnosticBag.GetInstance(); var lambdaSymbol = new LambdaSymbol(binder.Compilation, binder.ContainingMemberOrLambda, _unboundLambda, parameterTypes, parameterRefKinds, refKind: Microsoft.CodeAnalysis.RefKind.None, returnType: null); Binder lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder)); var block = BindLambdaBody(lambdaSymbol, 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. TypeSymbol returnType = result.InferredReturnType(ref useSiteDiagnostics) ?? LambdaSymbol.InferenceFailureReturnType; lambdaSymbol.SetInferredReturnType(result.RefKind, returnType); return(result); }
private BoundLambda ReallyInferReturnType(NamedTypeSymbol delegateType) { var diagnostics = DiagnosticBag.GetInstance(); var parameters = DelegateParameters(delegateType); var lambdaSymbol = new LambdaSymbol(binder.Compilation, binder.ContainingMemberOrLambda, this.unboundLambda, parameters, returnType: null); Binder lambdaBodyBinder = new ExecutableCodeBinder(this.unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder)); var block = BindLambdaBody(lambdaSymbol, ref lambdaBodyBinder, diagnostics); var result = new BoundLambda(this.unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType) { WasCompilerGenerated = this.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); }
// Control flow analysis does not normally scan the body of a lambda, but region analysis does. public override BoundNode VisitLambda(BoundLambda node) { var oldPending = SavePending(); // We do not support branches *into* a lambda. LocalState finalState = this.State; this.State = ReachableState(); var oldPending2 = SavePending(); VisitAlways(node.Body); RestorePending(oldPending2); // process any forward branches within the lambda body ImmutableArray<PendingBranch> pendingReturns = RemoveReturns(); RestorePending(oldPending); IntersectWith(ref finalState, ref this.State); foreach (PendingBranch returnBranch in pendingReturns) { this.State = returnBranch.State; IntersectWith(ref finalState, ref this.State); } this.State = finalState; return null; }
internal SynthesizedLambdaMethod( VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, NamedTypeSymbol containingType, ClosureKind closureKind, MethodSymbol topLevelMethod, int topLevelMethodOrdinal, BoundLambda lambdaNode, int lambdaOrdinal) : base(containingType, lambdaNode.Symbol, null, lambdaNode.SyntaxTree.GetReference(lambdaNode.Body.Syntax), lambdaNode.Syntax.GetLocation(), MakeName(slotAllocatorOpt, compilationState, closureKind, topLevelMethod, topLevelMethodOrdinal, lambdaOrdinal), (closureKind == ClosureKind.ThisOnly ? DeclarationModifiers.Private : DeclarationModifiers.Internal) | (lambdaNode.Symbol.IsAsync ? DeclarationModifiers.Async : 0)) { this.topLevelMethod = topLevelMethod; TypeMap typeMap; ImmutableArray <TypeParameterSymbol> typeParameters; LambdaFrame lambdaFrame; if (!topLevelMethod.IsGenericMethod) { typeMap = TypeMap.Empty; typeParameters = ImmutableArray <TypeParameterSymbol> .Empty; } else if ((object)(lambdaFrame = this.ContainingType as LambdaFrame) != null) { typeMap = lambdaFrame.TypeMap; typeParameters = ImmutableArray <TypeParameterSymbol> .Empty; } else { typeMap = TypeMap.Empty.WithAlphaRename(topLevelMethod, this, out typeParameters); } AssignTypeMapAndTypeParameters(typeMap, typeParameters); }
internal SynthesizedLambdaMethod( NamedTypeSymbol containingType, ClosureKind closureKind, MethodSymbol topLevelMethod, DebugId topLevelMethodId, BoundLambda lambdaNode, DebugId lambdaId) : base(containingType, lambdaNode.Symbol, null, lambdaNode.SyntaxTree.GetReference(lambdaNode.Body.Syntax), lambdaNode.Syntax.GetLocation(), MakeName(topLevelMethod.Name, topLevelMethodId, closureKind, lambdaId), (closureKind == ClosureKind.ThisOnly ? DeclarationModifiers.Private : DeclarationModifiers.Internal) | (lambdaNode.Symbol.IsAsync ? DeclarationModifiers.Async : 0)) { _topLevelMethod = topLevelMethod; TypeMap typeMap; ImmutableArray<TypeParameterSymbol> typeParameters; LambdaFrame lambdaFrame; if (!topLevelMethod.IsGenericMethod) { typeMap = TypeMap.Empty; typeParameters = ImmutableArray<TypeParameterSymbol>.Empty; } else if ((object)(lambdaFrame = this.ContainingType as LambdaFrame) != null) { typeMap = lambdaFrame.TypeMap; typeParameters = ImmutableArray<TypeParameterSymbol>.Empty; } else { typeMap = TypeMap.Empty.WithAlphaRename(topLevelMethod, this, out typeParameters); } AssignTypeMapAndTypeParameters(typeMap, typeParameters); }
// Control flow analysis does not normally scan the body of a lambda, but region analysis does. public override BoundNode VisitLambda(BoundLambda node) { var oldPending = SavePending(); // We do not support branches *into* a lambda. LocalState finalState = this.State; this.State = ReachableState(); var oldPending2 = SavePending(); VisitAlways(node.Body); RestorePending(oldPending2); // process any forward branches within the lambda body ImmutableArray <PendingBranch> pendingReturns = RemoveReturns(); RestorePending(oldPending); IntersectWith(ref finalState, ref this.State); foreach (PendingBranch returnBranch in pendingReturns) { this.State = returnBranch.State; IntersectWith(ref finalState, ref this.State); } this.State = finalState; return(null); }
private BoundExpression VisitLambdaInternal(BoundLambda node) { // prepare parameters so that they can be seen later var locals = ArrayBuilder <LocalSymbol> .GetInstance(); var initializers = ArrayBuilder <BoundExpression> .GetInstance(); var parameters = ArrayBuilder <BoundExpression> .GetInstance(); foreach (var p in node.Symbol.Parameters) { var param = _bound.SynthesizedLocal(ParameterExpressionType); locals.Add(param); var parameterReference = _bound.Local(param); parameters.Add(parameterReference); var parameter = ExprFactory( "Parameter", _bound.Typeof(_typeMap.SubstituteType(p.Type.TypeSymbol).TypeSymbol), _bound.Literal(p.Name)); initializers.Add(_bound.AssignmentExpression(parameterReference, parameter)); _parameterMap[p] = parameterReference; } var underlyingDelegateType = node.Type.GetDelegateType(); var result = _bound.Sequence(locals.ToImmutableAndFree(), initializers.ToImmutableAndFree(), ExprFactory( "Lambda", ImmutableArray.Create <TypeSymbol>(underlyingDelegateType), TranslateLambdaBody(node.Body), _bound.ArrayOrEmpty(ParameterExpressionType, parameters.ToImmutableAndFree()))); foreach (var p in node.Symbol.Parameters) { _parameterMap.Remove(p); } return(result); }
public override BoundNode VisitLambda(BoundLambda node) { var origLabels = this.currentLabels; var origSeenAwait = _seenAwait; this.currentLabels = null; _seenAwait = false; base.VisitLambda(node); this.currentLabels = origLabels; _seenAwait = origSeenAwait; return null; }
public override BoundNode VisitLambda(BoundLambda node) { var oldContainingSymbol = _F.CurrentMethod; var oldAwaitFinallyFrame = _currentAwaitFinallyFrame; _F.CurrentMethod = node.Symbol; _currentAwaitFinallyFrame = new AwaitFinallyFrame(); var result = base.VisitLambda(node); _F.CurrentMethod = oldContainingSymbol; _currentAwaitFinallyFrame = oldAwaitFinallyFrame; return result; }
public override BoundNode VisitLambda(BoundLambda node) { Debug.Assert((object)node.Symbol != null); seenLambda = true; var oldParent = currentParent; var oldBlock = currentBlock; currentParent = node.Symbol; currentBlock = node.Body; blockParent[currentBlock] = oldBlock; var wasInExpressionLambda = inExpressionLambda; inExpressionLambda = inExpressionLambda || node.Type.IsExpressionTree(); // for the purpose of constructing frames parameters are scoped as if they are inside the lambda block foreach (var parameter in node.Symbol.Parameters) { variableBlock[parameter] = currentBlock; if (inExpressionLambda) declaredInsideExpressionLambda.Add(parameter); } if (!node.Body.LocalsOpt.IsDefaultOrEmpty) { foreach (var local in node.Body.LocalsOpt) { variableBlock[local] = currentBlock; if (inExpressionLambda) declaredInsideExpressionLambda.Add(local); } } var result = base.VisitBlock(node.Body); inExpressionLambda = wasInExpressionLambda; currentParent = oldParent; currentBlock = oldBlock; return result; }
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); }
public override BoundNode VisitLambda(BoundLambda node) { // Do not recurse into nested lambdas; we don't want their returns. return(null); }
private BoundExpression VisitLambda(BoundLambda node) { var result = VisitLambdaInternal(node); return(node.Type.IsExpressionTree() ? ExprFactory("Quote", result) : result); }
public override BoundNode VisitLambda(BoundLambda node) { Debug.Assert((object)node.Symbol != null); SeenLambda = true; var oldParent = _currentParent; var oldBlock = _currentScope; _currentParent = node.Symbol; _currentScope = node.Body; scopeParent[_currentScope] = oldBlock; var wasInExpressionLambda = _inExpressionLambda; _inExpressionLambda = _inExpressionLambda || node.Type.IsExpressionTree(); if (!_inExpressionLambda) { // for the purpose of constructing frames parameters are scoped as if they are inside the lambda block foreach (var parameter in node.Symbol.Parameters) { variableScope[parameter] = _currentScope; } foreach (var local in node.Body.Locals) { variableScope[local] = _currentScope; } } var result = base.VisitBlock(node.Body); _inExpressionLambda = wasInExpressionLambda; _currentParent = oldParent; _currentScope = oldBlock; 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; }
private BoundNode RewriteLambdaConversion(BoundLambda node) { var wasInExpressionLambda = inExpressionLambda; inExpressionLambda = inExpressionLambda || node.Type.IsExpressionTree(); if (inExpressionLambda) { var newType = VisitType(node.Type); var newBody = (BoundBlock)Visit(node.Body); node = node.Update(node.Symbol, newBody, node.Diagnostics, node.Binder, newType); var result0 = wasInExpressionLambda ? node : ExpressionLambdaRewriter.RewriteLambda(node, CompilationState, Diagnostics); inExpressionLambda = wasInExpressionLambda; return(result0); } NamedTypeSymbol translatedLambdaContainer; BoundNode lambdaScope = null; if (analysis.lambdaScopes.TryGetValue(node.Symbol, out lambdaScope)) { translatedLambdaContainer = frames[lambdaScope]; } else { translatedLambdaContainer = topLevelMethod.ContainingType; } // Move the body of the lambda to a freshly generated synthetic method on its frame. bool lambdaIsStatic = analysis.captures[node.Symbol].IsEmpty(); var synthesizedMethod = new SynthesizedLambdaMethod(translatedLambdaContainer, topLevelMethod, node, lambdaIsStatic, CompilationState); if (CompilationState.Emitting) { CompilationState.ModuleBuilderOpt.AddSynthesizedDefinition(translatedLambdaContainer, synthesizedMethod); } for (int i = 0; i < node.Symbol.ParameterCount; i++) { parameterMap.Add(node.Symbol.Parameters[i], synthesizedMethod.Parameters[i]); } // rewrite the lambda body as the generated method's body var oldMethod = currentMethod; var oldFrameThis = currentFrameThis; var oldTypeParameters = currentTypeParameters; var oldInnermostFramePointer = innermostFramePointer; var oldTypeMap = currentLambdaBodyTypeMap; var oldAddedStatements = addedStatements; var oldAddedLocals = addedLocals; addedStatements = null; addedLocals = null; // switch to the generated method currentMethod = synthesizedMethod; if (lambdaIsStatic) { // no link from a static lambda to its container innermostFramePointer = currentFrameThis = null; } else { currentFrameThis = synthesizedMethod.ThisParameter; innermostFramePointer = null; framePointers.TryGetValue(translatedLambdaContainer, out innermostFramePointer); } if (translatedLambdaContainer.OriginalDefinition is LambdaFrame) { currentTypeParameters = translatedLambdaContainer.TypeParameters; currentLambdaBodyTypeMap = ((LambdaFrame)translatedLambdaContainer).TypeMap; } else { currentTypeParameters = synthesizedMethod.TypeParameters; currentLambdaBodyTypeMap = new TypeMap(topLevelMethod.TypeParameters, currentTypeParameters); } var body = AddStatementsIfNeeded((BoundStatement)VisitBlock(node.Body)); CheckLocalsDefined(body); CompilationState.AddSynthesizedMethod(synthesizedMethod, body); // return to the old method currentMethod = oldMethod; currentFrameThis = oldFrameThis; currentTypeParameters = oldTypeParameters; innermostFramePointer = oldInnermostFramePointer; currentLambdaBodyTypeMap = oldTypeMap; addedLocals = oldAddedLocals; addedStatements = oldAddedStatements; // Rewrite the lambda expression (and the enclosing anonymous method conversion) as a delegate creation expression NamedTypeSymbol constructedFrame = (translatedLambdaContainer is LambdaFrame) ? translatedLambdaContainer.ConstructIfGeneric(StaticCast <TypeSymbol> .From(currentTypeParameters)) : translatedLambdaContainer; BoundExpression receiver = lambdaIsStatic ? new BoundTypeExpression(node.Syntax, null, constructedFrame) : FrameOfType(node.Syntax, constructedFrame); MethodSymbol referencedMethod = synthesizedMethod.AsMember(constructedFrame); if (referencedMethod.IsGenericMethod) { referencedMethod = referencedMethod.Construct(StaticCast <TypeSymbol> .From(currentTypeParameters)); } TypeSymbol type = this.VisitType(node.Type); BoundExpression result = new BoundDelegateCreationExpression( node.Syntax, receiver, referencedMethod, isExtensionMethod: false, type: type); // if the block containing the lambda is not the innermost block, // or the lambda is static, then the lambda object should be cached in its frame. // NOTE: we are not caching static lambdas in static ctors - cannot reuse such cache. var shouldCacheForStaticMethod = lambdaIsStatic && currentMethod.MethodKind != MethodKind.StaticConstructor && !referencedMethod.IsGenericMethod; // NOTE: We require "lambdaScope != null". // We do not want to introduce a field into an actual user's class (not a synthetic frame). var shouldCacheInLoop = lambdaScope != null && lambdaScope != analysis.blockParent[node.Body] && InLoopOrLambda(node.Syntax, lambdaScope.Syntax); if (shouldCacheForStaticMethod || shouldCacheInLoop) { // replace the expression "new Delegate(frame.M)" with "(frame.cache == null) ? (frame.cache = new Delegate(frame.M)) : frame.cache" var F = new SyntheticBoundNodeFactory(currentMethod, node.Syntax, CompilationState, Diagnostics); try { var cacheVariableName = GeneratedNames.MakeLambdaCacheName(CompilationState.GenerateTempNumber()); BoundExpression cacheVariable; if (shouldCacheForStaticMethod || shouldCacheInLoop && translatedLambdaContainer is LambdaFrame) { var cacheVariableType = lambdaIsStatic ? type : (translatedLambdaContainer as LambdaFrame).TypeMap.SubstituteType(type); var cacheField = new SynthesizedFieldSymbol(translatedLambdaContainer, cacheVariableType, cacheVariableName, isPublic: !lambdaIsStatic, isStatic: lambdaIsStatic); CompilationState.ModuleBuilderOpt.AddSynthesizedDefinition(translatedLambdaContainer, cacheField); cacheVariable = F.Field(receiver, cacheField.AsMember(constructedFrame)); //NOTE: the field was added to the unconstructed frame type. } else { // the lambda captures at most the "this" of the enclosing method. We cache its delegate in a local variable. var cacheLocal = F.SynthesizedLocal(type, cacheVariableName); if (addedLocals == null) { addedLocals = ArrayBuilder <LocalSymbol> .GetInstance(); } addedLocals.Add(cacheLocal); if (addedStatements == null) { addedStatements = ArrayBuilder <BoundStatement> .GetInstance(); } cacheVariable = F.Local(cacheLocal); addedStatements.Add(F.Assignment(cacheVariable, F.Null(type))); } result = F.Coalesce(cacheVariable, F.AssignmentExpression(cacheVariable, result)); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) { Diagnostics.Add(ex.Diagnostic); return(new BoundBadExpression(F.Syntax, LookupResultKind.Empty, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundNode>(node), node.Type)); } } return(result); }
private BoundExpression VisitLambda(BoundLambda node) { var result = VisitLambdaInternal(node); return node.Type.IsExpressionTree() ? ExprFactory("Quote", result) : result; }
public override BoundNode VisitLambda(BoundLambda node) { MakeSlots(node.Symbol.Parameters); return(base.VisitLambda(node)); }
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. var cacheKey = ReturnInferenceCacheKey.Create(delegateType, IsAsync); BoundLambda returnInferenceLambda; if (_returnInferenceCache.TryGetValue(cacheKey, out returnInferenceLambda) && returnInferenceLambda.InferredFromSingleType) { lambdaSymbol = returnInferenceLambda.Symbol; if ((object)LambdaSymbol.InferenceFailureReturnType != lambdaSymbol.ReturnType && lambdaSymbol.ReturnType == returnType && lambdaSymbol.RefKind == refKind) { lambdaBodyBinder = returnInferenceLambda.Binder; block = returnInferenceLambda.Body; diagnostics.AddRange(returnInferenceLambda.Diagnostics); goto haveLambdaBodyAndBinders; } } lambdaSymbol = new LambdaSymbol( binder.Compilation, binder.ContainingMemberOrLambda, _unboundLambda, cacheKey.ParameterTypes, cacheKey.ParameterRefKinds, refKind, returnType); lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder)); block = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics); ((ExecutableCodeBinder)lambdaBodyBinder).ValidateIteratorMethods(diagnostics); ValidateUnsafeParameters(diagnostics, cacheKey.ParameterTypes); 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.DiagnosticLocation, 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.DiagnosticLocation, lambdaSymbol.MessageID.Localize(), delegateType); } } if (IsAsync) { Debug.Assert(lambdaSymbol.IsAsync); SourceMemberMethodSymbol.ReportAsyncParameterErrors(lambdaSymbol.Parameters, diagnostics, lambdaSymbol.DiagnosticLocation); } var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: false) { WasCompilerGenerated = _unboundLambda.WasCompilerGenerated }; return(result); }
// Control flow analysis does not normally scan the body of a lambda, but region analysis does. public override BoundNode VisitLambda(BoundLambda node) { return(VisitLocalFunctionOrLambda(node.Body)); }
public override BoundNode VisitLambda(BoundLambda node) { MethodsConvertedToDelegates.Add(node.Symbol.OriginalDefinition); return VisitLambdaOrFunction(node); }
// Control flow analysis does not normally scan the body of a lambda, but region analysis does. public override BoundNode VisitLambda(BoundLambda node) { return VisitLocalFunctionOrLambda(node.Body); }
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; }
public override BoundNode VisitLambda(BoundLambda node) { MakeSlots(node.Symbol.Parameters); return base.VisitLambda(node); }
public override BoundNode VisitLambda(BoundLambda node) { MethodsConvertedToDelegates.Add(node.Symbol.OriginalDefinition); return(VisitLambdaOrFunction(node)); }
public override BoundNode VisitLambda(BoundLambda node) { if (_inExpressionLambda) { switch (node.Syntax.Kind()) { case SyntaxKind.ParenthesizedLambdaExpression: { var lambdaSyntax = (ParenthesizedLambdaExpressionSyntax)node.Syntax; if (lambdaSyntax.AsyncKeyword.Kind() == SyntaxKind.AsyncKeyword) { Error(ErrorCode.ERR_BadAsyncExpressionTree, node); } else if (lambdaSyntax.Body.Kind() == SyntaxKind.Block) { Error(ErrorCode.ERR_StatementLambdaToExpressionTree, node); } else if (lambdaSyntax.Body.Kind() == SyntaxKind.RefExpression) { Error(ErrorCode.ERR_BadRefReturnExpressionTree, node); } var lambda = node.ExpressionSymbol as MethodSymbol; if ((object)lambda != null) { foreach (var p in lambda.Parameters) { if (p.RefKind != RefKind.None && p.Locations.Length != 0) { _diagnostics.Add(ErrorCode.ERR_ByRefParameterInExpressionTree, p.Locations[0]); } } } } break; case SyntaxKind.SimpleLambdaExpression: { var lambdaSyntax = (SimpleLambdaExpressionSyntax)node.Syntax; if (lambdaSyntax.AsyncKeyword.Kind() == SyntaxKind.AsyncKeyword) { Error(ErrorCode.ERR_BadAsyncExpressionTree, node); } else if (lambdaSyntax.Body.Kind() == SyntaxKind.Block) { Error(ErrorCode.ERR_StatementLambdaToExpressionTree, node); } else if (lambdaSyntax.Body.Kind() == SyntaxKind.RefExpression) { Error(ErrorCode.ERR_BadRefReturnExpressionTree, node); } } break; case SyntaxKind.AnonymousMethodExpression: Error(ErrorCode.ERR_ExpressionTreeContainsAnonymousMethod, node); break; default: // other syntax forms arise from query expressions, and always result from implied expression-lambda-like forms break; } } return base.VisitLambda(node); }
public override BoundNode VisitLambda(BoundLambda node) { // these nodes have been handled in the context of the enclosing anonymous method conversion. throw ExceptionUtilities.Unreachable; }
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, this.unboundLambda, parameters, returnType); lambdaBodyBinder = new ExecutableCodeBinder(this.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, this.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(this.unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType) { WasCompilerGenerated = this.unboundLambda.WasCompilerGenerated }; return(result); }
public override BoundNode VisitLambda(BoundLambda node) { lambdaLevel++; base.VisitLambda(node); lambdaLevel--; return null; }
public override BoundNode VisitLambda(BoundLambda node) { if (_inExpressionLambda) { var lambda = node.Symbol; foreach (var p in lambda.Parameters) { if (p.RefKind != RefKind.None && p.Locations.Length != 0) { _diagnostics.Add(ErrorCode.ERR_ByRefParameterInExpressionTree, p.Locations[0]); } if (p.Type.IsRestrictedType()) { _diagnostics.Add(ErrorCode.ERR_ExpressionTreeCantContainRefStruct, p.Locations[0], p.Type.Name); } } switch (node.Syntax.Kind()) { case SyntaxKind.ParenthesizedLambdaExpression: { var lambdaSyntax = (ParenthesizedLambdaExpressionSyntax)node.Syntax; if (lambdaSyntax.AsyncKeyword.Kind() == SyntaxKind.AsyncKeyword) { Error(ErrorCode.ERR_BadAsyncExpressionTree, node); } else if (lambdaSyntax.Body.Kind() == SyntaxKind.Block) { Error(ErrorCode.ERR_StatementLambdaToExpressionTree, node); } else if (lambdaSyntax.Body.Kind() == SyntaxKind.RefExpression) { Error(ErrorCode.ERR_BadRefReturnExpressionTree, node); } } break; case SyntaxKind.SimpleLambdaExpression: { var lambdaSyntax = (SimpleLambdaExpressionSyntax)node.Syntax; if (lambdaSyntax.AsyncKeyword.Kind() == SyntaxKind.AsyncKeyword) { Error(ErrorCode.ERR_BadAsyncExpressionTree, node); } else if (lambdaSyntax.Body.Kind() == SyntaxKind.Block) { Error(ErrorCode.ERR_StatementLambdaToExpressionTree, node); } else if (lambdaSyntax.Body.Kind() == SyntaxKind.RefExpression) { Error(ErrorCode.ERR_BadRefReturnExpressionTree, node); } } break; case SyntaxKind.AnonymousMethodExpression: Error(ErrorCode.ERR_ExpressionTreeContainsAnonymousMethod, node); break; default: // other syntax forms arise from query expressions, and always result from implied expression-lambda-like forms break; } } return(base.VisitLambda(node)); }
internal SynthesizedLambdaMethod(NamedTypeSymbol containingType, MethodSymbol topLevelMethod, BoundLambda node, bool isStatic, TypeCompilationState compilationState) : base(containingType, node.Symbol, null, node.SyntaxTree.GetReference(node.Body.Syntax), node.Syntax.GetLocation(), GeneratedNames.MakeLambdaMethodName(topLevelMethod.Name, compilationState.GenerateTempNumber()), (containingType is LambdaFrame ? DeclarationModifiers.Internal : DeclarationModifiers.Private) | (isStatic ? DeclarationModifiers.Static : 0) | (node.Symbol.IsAsync ? DeclarationModifiers.Async : 0)) { TypeMap typeMap; ImmutableArray <TypeParameterSymbol> typeParameters; LambdaFrame lambdaFrame; if (!topLevelMethod.IsGenericMethod) { typeMap = TypeMap.Empty; typeParameters = ImmutableArray <TypeParameterSymbol> .Empty; } else if ((object)(lambdaFrame = this.ContainingType as LambdaFrame) != null) { typeMap = lambdaFrame.TypeMap; typeParameters = ImmutableArray <TypeParameterSymbol> .Empty; } else { typeMap = TypeMap.Empty.WithAlphaRename(topLevelMethod, this, out typeParameters); } AssignTypeMapAndTypeParameters(typeMap, typeParameters); }
internal static BoundNode RewriteLambda(BoundLambda node, TypeCompilationState compilationState, TypeMap typeMap, DiagnosticBag diagnostics) { try { var r = new ExpressionLambdaRewriter(compilationState, typeMap, node.Syntax, diagnostics); var result = r.VisitLambdaInternal(node); if (node.Type != result.Type) { diagnostics.Add(ErrorCode.ERR_MissingPredefinedMember, node.Syntax.Location, r.ExpressionType, "Lambda"); } return result; } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) { diagnostics.Add(ex.Diagnostic); return node; } }
public override BoundNode VisitLambda(BoundLambda node) { // Do not recurse into nested lambdas; we don't want their returns. return null; }
private BoundExpression VisitLambdaInternal(BoundLambda node) { // prepare parameters so that they can be seen later var locals = ArrayBuilder<LocalSymbol>.GetInstance(); var initializers = ArrayBuilder<BoundExpression>.GetInstance(); var parameters = ArrayBuilder<BoundExpression>.GetInstance(); foreach (var p in node.Symbol.Parameters) { var param = _bound.SynthesizedLocal(ParameterExpressionType); locals.Add(param); var parameterReference = _bound.Local(param); parameters.Add(parameterReference); var parameter = ExprFactory( "Parameter", _bound.Typeof(_typeMap.SubstituteType(p.Type).Type), _bound.Literal(p.Name)); initializers.Add(_bound.AssignmentExpression(parameterReference, parameter)); _parameterMap[p] = parameterReference; } var underlyingDelegateType = node.Type.GetDelegateType(); var result = _bound.Sequence(locals.ToImmutableAndFree(), initializers.ToImmutableAndFree(), ExprFactory( "Lambda", ImmutableArray.Create<TypeSymbol>(underlyingDelegateType), TranslateLambdaBody(node.Body), _bound.Array(ParameterExpressionType, parameters.ToImmutableAndFree()))); foreach (var p in node.Symbol.Parameters) { _parameterMap.Remove(p); } return result; }
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; }