/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Binding/Binder_Lambda.vb
1 133 строки
60 KB
Cyrus Najmabadi
Update code to use GetFirstLocation() instead of Locations[0] or Locations.First() (#80709)
21 окт 2025, 00:00
Не верифицирован
21 окт 2025, 00:00
3a723bb
Код
Авторство
О чём код?
' Licensed to the .NET Foundation under one or more agreements. ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. Imports System.Collections.Immutable Imports System.Runtime.InteropServices Imports System.Threading Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic Partial Friend Class Binder Private Function BindLambdaExpression( node As LambdaExpressionSyntax, diagnostics As BindingDiagnosticBag ) As BoundExpression Const asyncIterator As SourceMemberFlags = SourceMemberFlags.Async Or SourceMemberFlags.Iterator ' Decode the modifiers. Dim modifiers As SourceMemberFlags = DecodeModifiers(node.SubOrFunctionHeader.Modifiers, asyncIterator, ERRID.ERR_InvalidLambdaModifier, Accessibility.Public, If(diagnostics.DiagnosticBag, New DiagnosticBag())).FoundFlags And asyncIterator If (modifiers And asyncIterator) = asyncIterator AndAlso diagnostics.AccumulatesDiagnostics Then ReportModifierError(node.SubOrFunctionHeader.Modifiers, ERRID.ERR_InvalidAsyncIteratorModifiers, diagnostics.DiagnosticBag, InvalidAsyncIterator) End If Dim parameters As ImmutableArray(Of ParameterSymbol) parameters = DecodeParameterList(Me.ContainingMember, True, modifiers, node.SubOrFunctionHeader.ParameterList, diagnostics) For Each param In parameters ' Look up in container binders for name clashes with other locals and parameters. Dim identifierSyntax As SyntaxNodeOrToken = DirectCast(param, UnboundLambdaParameterSymbol).IdentifierSyntax Me.VerifyNameShadowingInMethodBody(param, identifierSyntax, identifierSyntax, diagnostics) Next Dim returnType As TypeSymbol = Nothing Dim hasErrors As Boolean = False If node.Kind = SyntaxKind.MultiLineFunctionLambdaExpression AndAlso node.SubOrFunctionHeader.AsClause IsNot Nothing Then returnType = BindTypeSyntax(node.SubOrFunctionHeader.AsClause.Type, diagnostics) If returnType.IsRestrictedType() Then ReportDiagnostic(diagnostics, node.SubOrFunctionHeader.AsClause.Type, ERRID.ERR_RestrictedType1, returnType) hasErrors = True ElseIf Not returnType.IsErrorType() Then If Not (modifiers And asyncIterator) = asyncIterator Then If modifiers = SourceMemberFlags.Async AndAlso Not returnType.OriginalDefinition.Equals(Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T)) AndAlso Not returnType.Equals(Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task)) Then ReportDiagnostic(diagnostics, node.SubOrFunctionHeader.AsClause.Type, ERRID.ERR_BadAsyncReturn) End If If modifiers = SourceMemberFlags.Iterator Then Dim originalRetTypeDef = returnType.OriginalDefinition If originalRetTypeDef.SpecialType <> SpecialType.System_Collections_Generic_IEnumerable_T AndAlso originalRetTypeDef.SpecialType <> SpecialType.System_Collections_Generic_IEnumerator_T AndAlso returnType.SpecialType <> SpecialType.System_Collections_IEnumerable AndAlso returnType.SpecialType <> SpecialType.System_Collections_IEnumerator Then ReportDiagnostic(diagnostics, node.SubOrFunctionHeader.AsClause.Type, ERRID.ERR_BadIteratorReturn) End If End If End If End If ElseIf node.Kind = SyntaxKind.MultiLineSubLambdaExpression OrElse node.Kind = SyntaxKind.SingleLineSubLambdaExpression Then returnType = GetSpecialType(SpecialType.System_Void, node.SubOrFunctionHeader, diagnostics) If modifiers = SourceMemberFlags.Iterator Then ReportDiagnostic(diagnostics, node.SubOrFunctionHeader.DeclarationKeyword, ERRID.ERR_BadIteratorReturn) End If End If Return New UnboundLambda(node, Me, modifiers, parameters, returnType, New UnboundLambda.UnboundLambdaBindingCache(diagnostics.AccumulatesDependencies), hasErrors) End Function Friend Function BuildBoundLambdaParameters( source As UnboundLambda, targetSignature As UnboundLambda.TargetSignature, diagnostics As BindingDiagnosticBag ) As ImmutableArray(Of BoundLambdaParameterSymbol) If source.Parameters.Length = 0 Then Return ImmutableArray(Of BoundLambdaParameterSymbol).Empty End If Dim unboundParams As ImmutableArray(Of ParameterSymbol) = source.Parameters Dim parameters(unboundParams.Length - 1) As BoundLambdaParameterSymbol Dim minCount As Integer = Math.Min(parameters.Length, targetSignature.ParameterTypes.Length) For i As Integer = 0 To minCount - 1 Step 1 Dim unboundParam = DirectCast(unboundParams(i), UnboundLambdaParameterSymbol) Dim unboundType As TypeSymbol = unboundParam.Type Dim delegateType As TypeSymbol = targetSignature.ParameterTypes(i) If unboundType Is Nothing Then ' Get the type from the target. unboundType = delegateType If Not unboundParam.IsByRef AndAlso source.Flags <> 0 AndAlso unboundType.IsRestrictedType Then ReportDiagnostic(diagnostics, unboundParam.IdentifierSyntax, ERRID.ERR_RestrictedResumableType1, unboundType) Else ' Other cases with restricted types are not interesting because either the target delegate type is "bad" ' due to the way restricted type is used in its signature, or there is a ByRef/ByVal mismatch for the parameter. End If End If parameters(i) = New BoundLambdaParameterSymbol(unboundParam.Name, unboundParam.Ordinal, unboundType, unboundParam.IsByRef, unboundParam.Syntax, unboundParam.GetFirstLocation()) Next If parameters.Length <> targetSignature.ParameterTypes.Length Then ' Create the rest of the parameters Dim objectType As TypeSymbol = Nothing For i As Integer = minCount To parameters.Length - 1 Step 1 Dim unboundParam = DirectCast(unboundParams(i), UnboundLambdaParameterSymbol) Dim unboundType As TypeSymbol = unboundParam.Type If unboundType Is Nothing Then If objectType Is Nothing Then objectType = GetSpecialType(SpecialType.System_Object, unboundParam.IdentifierSyntax, diagnostics) End If unboundType = objectType ReportLambdaParameterInferredToBeObject(unboundParam, diagnostics) End If parameters(i) = New BoundLambdaParameterSymbol(unboundParam.Name, unboundParam.Ordinal, unboundType, unboundParam.IsByRef, unboundParam.Syntax, unboundParam.GetFirstLocation()) Next End If Return parameters.AsImmutableOrNull() End Function Friend Function BindUnboundLambda(source As UnboundLambda, target As UnboundLambda.TargetSignature) As BoundLambda Debug.Assert(Me Is source.Binder) Dim maxRelaxationLevel As ConversionKind = ConversionKind.DelegateRelaxationLevelNone Dim diagnostics = BindingDiagnosticBag.GetInstance(withDiagnostics:=True, source.WithDependencies) Dim targetReturnType As TypeSymbol If source.ReturnType IsNot Nothing Then targetReturnType = source.ReturnType If source.IsFunctionLambda Then If targetReturnType.IsVoidType() Then targetReturnType = Microsoft.CodeAnalysis.VisualBasic.Symbols.LambdaSymbol.ReturnTypeVoidReplacement End If End If Else Debug.Assert(source.IsFunctionLambda) ' For Async | Iterator lambdas with nongeneric target delegate return type, we still want to do return type inference ' in order to infer more specific return type Task(Of T) | IEnumerable(of T), if possible. If target.ReturnType.SpecialType <> SpecialType.System_Void AndAlso Not ((source.Flags And SourceMemberFlags.Async) <> 0 AndAlso target.ReturnType Is Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task)) AndAlso Not ((source.Flags And SourceMemberFlags.Iterator) <> 0 AndAlso (target.ReturnType.SpecialType = SpecialType.System_Collections_IEnumerable OrElse target.ReturnType.SpecialType = SpecialType.System_Collections_IEnumerator)) Then targetReturnType = target.ReturnType If Not targetReturnType.IsErrorType() Then If source.Flags = SourceMemberFlags.Async Then If Not TypeSymbol.Equals(targetReturnType.OriginalDefinition, Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T), TypeCompareKind.ConsiderEverything) Then ReportDiagnostic(diagnostics, LambdaHeaderErrorNode(source), ERRID.ERR_BadAsyncReturn) End If End If If source.Flags = SourceMemberFlags.Iterator Then Dim origTargetReturnType = targetReturnType.OriginalDefinition If origTargetReturnType.SpecialType <> SpecialType.System_Collections_Generic_IEnumerable_T AndAlso origTargetReturnType.SpecialType <> SpecialType.System_Collections_Generic_IEnumerator_T Then ReportDiagnostic(diagnostics, LambdaHeaderErrorNode(source), ERRID.ERR_BadIteratorReturn) End If End If End If Else ' Target signature is a Sub, but lambda is a function; or target return type is Task and lambda is Async. ' Have to infer the type Debug.Assert(target.ReturnType.IsVoidType() OrElse ((source.Flags And SourceMemberFlags.Async) <> 0 AndAlso target.ReturnType.Equals(Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task)))) Dim targetForInference As UnboundLambda.TargetSignature = target If Not targetForInference.ReturnType.IsVoidType() Then targetForInference = New UnboundLambda.TargetSignature(targetForInference.ParameterTypes, targetForInference.ParameterIsByRef, Compilation.GetSpecialType(SpecialType.System_Void), ' No need to report use-site error. returnsByRef:=False) End If Dim typeInfo As KeyValuePair(Of TypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol)) = source.InferReturnType(targetForInference) targetReturnType = typeInfo.Key diagnostics.AddRange(typeInfo.Value) End If End If ' Create parameters Dim parameters As ImmutableArray(Of BoundLambdaParameterSymbol) = BuildBoundLambdaParameters(source, target, diagnostics) Dim lambdaSymbol As New SourceLambdaSymbol(source.Syntax, source, parameters, targetReturnType, Me) Dim delegateRelaxation As ConversionKind = Nothing Dim lambdaBinder As LambdaBodyBinder = Nothing Dim block As BoundBlock = BindLambdaBody(lambdaSymbol, diagnostics, lambdaBinder) If block.HasErrors OrElse diagnostics.HasAnyErrors() Then delegateRelaxation = ConversionKind.DelegateRelaxationLevelInvalid 'No conversion Else ' Add information about delegate relaxation level across all Return statements within the lambda body. If lambdaSymbol.IsSub Then delegateRelaxation = ConversionKind.DelegateRelaxationLevelNone Else Dim seenReturnWithAValue As Boolean = False Dim useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics) delegateRelaxation = LambdaRelaxationVisitor.DetermineDelegateRelaxationLevel(lambdaSymbol, source.Flags = SourceMemberFlags.Iterator, block, seenReturnWithAValue, useSiteInfo) diagnostics.Add(LambdaHeaderErrorNode(source), useSiteInfo) ' Dev11#94373: we also need to track whether there were any returns with operands, since ' turning "Async Function() : End Function" into a Func(Of Task(Of Integer)) is a delegate ' relaxation. If Not seenReturnWithAValue AndAlso lambdaSymbol.IsAsync AndAlso delegateRelaxation < ConversionKind.DelegateRelaxationLevelWideningDropReturnOrArgs AndAlso lambdaSymbol.ReturnType.OriginalDefinition.Equals(Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T)) Then delegateRelaxation = ConversionKind.DelegateRelaxationLevelWideningDropReturnOrArgs End If End If End If ' See if we need to relax the lambda Dim methodConversions As MethodConversionKind = MethodConversionKind.Error_Unspecified If delegateRelaxation <> ConversionKind.DelegateRelaxationLevelInvalid Then ' Figure out conversion kind. Dim useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics) methodConversions = Conversions.ClassifyMethodConversionForLambdaOrAnonymousDelegate(target, lambdaSymbol, useSiteInfo) If diagnostics.Add(LambdaHeaderErrorNode(source), useSiteInfo) Then ' Suppress additional diagnostics diagnostics = BindingDiagnosticBag.Discarded End If If Conversions.IsDelegateRelaxationSupportedFor(methodConversions) Then If Conversions.IsStubRequiredForMethodConversion(methodConversions) Then ' We will need a stub for this lambda, which means that we will need to instantiate ' an Anonymous Delegate matching the signature of the lambdaSymbol. ' Anonymous Delegate has some limitations on parameter and return types. For Each param In lambdaSymbol.Parameters ' Verify for restricted types. Dim restrictedType As TypeSymbol = Nothing If param.Type.IsRestrictedTypeOrArrayType(restrictedType) Then ReportDiagnostic(diagnostics, DirectCast(source.Parameters(param.Ordinal), UnboundLambdaParameterSymbol).TypeSyntax, ERRID.ERR_RestrictedType1, restrictedType) delegateRelaxation = ConversionKind.DelegateRelaxationLevelInvalid 'No conversion methodConversions = methodConversions Or MethodConversionKind.Error_RestrictedType Exit For End If Next If delegateRelaxation <> ConversionKind.DelegateRelaxationLevelInvalid Then Debug.Assert(targetReturnType Is lambdaSymbol.ReturnType) ' Check return type as well, but complain only if we "inherited" it from the target signature. If we got ' it from the lambda's signature or inferred it, we already complained about it. Dim restrictedType As TypeSymbol = Nothing If targetReturnType.IsRestrictedTypeOrArrayType(restrictedType) Then delegateRelaxation = ConversionKind.DelegateRelaxationLevelInvalid 'No conversion methodConversions = methodConversions Or MethodConversionKind.Error_RestrictedType If source.ReturnType Is Nothing AndAlso target.ReturnType.SpecialType <> SpecialType.System_Void Then ReportDiagnostic(diagnostics, LambdaHeaderErrorNode(source), ERRID.ERR_RestrictedType1, restrictedType) End If End If End If End If End If delegateRelaxation = CType(Math.Max(delegateRelaxation, Conversions.DetermineDelegateRelaxationLevel(methodConversions)), ConversionKind) End If ' the control flow of lambda expression bodies have not yet been analyzed. This will report unreachable code, ... ControlFlowPass.Analyze(New FlowAnalysisInfo(Compilation, lambdaSymbol, block), diagnostics.DiagnosticBag, True) Dim hasAnyErrors = diagnostics.HasAnyErrors() ' handle cases where control flow reports errors (such as illegal goto out of Finally) ' this will not change the outcome of overload resolution since control flow errors will happen ' regardless of substitutions. If hasAnyErrors Then delegateRelaxation = ConversionKind.DelegateRelaxationLevelInvalid 'No conversion End If Dim sealedDiagnostics = diagnostics.ToReadOnlyAndFree() Return New BoundLambda(source.Syntax, lambdaSymbol, block, sealedDiagnostics, lambdaBinder, delegateRelaxation, methodConversions, hasAnyErrors) End Function Private Class LambdaRelaxationVisitor Inherits StatementWalker Private ReadOnly _lambdaSymbol As LambdaSymbol Private ReadOnly _isIterator As Boolean Private _delegateRelaxationLevel As ConversionKind = ConversionKind.DelegateRelaxationLevelNone Private _seenReturnWithAValue As Boolean Private _useSiteDiagnostics As CompoundUseSiteInfo(Of AssemblySymbol) Private Sub New(lambdaSymbol As LambdaSymbol, isIterator As Boolean) _lambdaSymbol = lambdaSymbol _isIterator = isIterator End Sub Public Shared Function DetermineDelegateRelaxationLevel( lambdaSymbol As LambdaSymbol, isIterator As Boolean, lambdaBlock As BoundBlock, <Out()> ByRef seenReturnWithAValue As Boolean, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) As ConversionKind Dim visitor As New LambdaRelaxationVisitor(lambdaSymbol, isIterator) visitor._useSiteDiagnostics = useSiteInfo visitor.VisitBlock(lambdaBlock) seenReturnWithAValue = visitor._seenReturnWithAValue useSiteInfo = visitor._useSiteDiagnostics Return visitor._delegateRelaxationLevel End Function Public Overrides Function Visit(node As BoundNode) As BoundNode 'Do not visit expressions If node Is Nothing OrElse TypeOf node Is BoundExpression Then Return Nothing End If Return MyBase.Visit(node) End Function Public Overrides Function VisitLambda(node As BoundLambda) As BoundNode Throw ExceptionUtilities.Unreachable End Function Public Overrides Function VisitReturnStatement(node As BoundReturnStatement) As BoundNode ' not interested in Returns in an iterator. If _isIterator Then Return Nothing End If ' Ignore implicit return at the end of the body. If node.ExpressionOpt IsNot Nothing Then If node.ExpressionOpt.Kind = BoundKind.Local Then Dim local As LocalSymbol = DirectCast(node.ExpressionOpt, BoundLocal).LocalSymbol If local.IsFunctionValue AndAlso local.ContainingSymbol Is _lambdaSymbol Then Return Nothing End If End If _seenReturnWithAValue = True End If Dim returnRelaxation As ConversionKind = Conversions.DetermineDelegateRelaxationLevelForLambdaReturn(node.ExpressionOpt, _useSiteDiagnostics) If returnRelaxation > _delegateRelaxationLevel Then _delegateRelaxationLevel = returnRelaxation End If Return Nothing End Function Public Overrides Function VisitYieldStatement(node As BoundYieldStatement) As BoundNode If _isIterator Then Dim returnRelaxation As ConversionKind = Conversions.DetermineDelegateRelaxationLevelForLambdaReturn(node.Expression, _useSiteDiagnostics) If returnRelaxation > _delegateRelaxationLevel Then _delegateRelaxationLevel = returnRelaxation End If End If Return Nothing End Function End Class Private Function BindLambdaBody( lambdaSymbol As LambdaSymbol, diagnostics As BindingDiagnosticBag, ByRef lambdaBinder As LambdaBodyBinder ) As BoundBlock Dim implicitVariablesBinder As Binder = Nothing If ContainingBinder.OptionExplicit = False AndAlso Not ContainingBinder.ImplicitVariableDeclarationAllowed Then ' Option Explicit is Off, but we're not in a location than allows implicit variable declaration (i.e., a field initializer). ' Install an implicit variables binder to capture implicit variables in this lambda. implicitVariablesBinder = New ImplicitVariableBinder(Me, lambdaSymbol) lambdaBinder = New LambdaBodyBinder(lambdaSymbol, implicitVariablesBinder) Else lambdaBinder = New LambdaBodyBinder(lambdaSymbol, Me) End If #If DEBUG Then lambdaBinder.EnableSimpleNameBindingOrderChecks(True) #End If Dim lambdaSyntax = lambdaSymbol.Syntax Dim bodyBinder = lambdaBinder.GetBinder(lambdaSyntax) Dim endSyntax As SyntaxNode = lambdaSyntax Dim block As BoundBlock Select Case lambdaSyntax.Kind Case SyntaxKind.SingleLineFunctionLambdaExpression Debug.Assert(lambdaSymbol.ReturnType Is Nothing OrElse Not lambdaSymbol.ReturnType.IsVoidType()) Dim expression As BoundExpression = bodyBinder.BindValue( DirectCast( DirectCast(lambdaSyntax, SingleLineLambdaExpressionSyntax).Body, ExpressionSyntax), diagnostics) If lambdaSymbol.ReturnType IsNot LambdaSymbol.ReturnTypeIsBeingInferred Then If lambdaSymbol.ReturnType IsNot LambdaSymbol.ReturnTypeIsUnknown Then Dim retType As TypeSymbol = lambdaSymbol.ReturnType If lambdaSymbol.IsAsync Then If retType.OriginalDefinition.Equals(Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T)) Then retType = DirectCast(retType, NamedTypeSymbol).TypeArgumentsNoUseSiteDiagnostics(0) Else ' We should have forced Task(Of T) inference. Debug.Assert(Not retType.Equals(Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task))) End If End If expression = bodyBinder.ApplyImplicitConversion(expression.Syntax, retType, expression, diagnostics, False) Else expression = bodyBinder.MakeRValueAndIgnoreDiagnostics(expression) End If End If Dim boundReturn = New BoundReturnStatement(expression.Syntax, expression, bodyBinder.GetLocalForFunctionValue(), bodyBinder.GetReturnLabel(), expression.HasErrors) boundReturn.SetWasCompilerGenerated() block = New BoundBlock(lambdaSyntax, Nothing, ImmutableArray(Of LocalSymbol).Empty, ImmutableArray.Create(Of BoundStatement)(boundReturn), expression.HasErrors).MakeCompilerGenerated() Case SyntaxKind.SingleLineSubLambdaExpression Debug.Assert(lambdaSymbol.ReturnType IsNot Nothing AndAlso lambdaSymbol.ReturnType.IsVoidType()) Dim singleLineLambdaSyntax = DirectCast(lambdaSyntax, SingleLineLambdaExpressionSyntax) Dim statement = DirectCast(singleLineLambdaSyntax.Body, StatementSyntax) If statement.Kind = SyntaxKind.LocalDeclarationStatement Then ' A local declaration is not allowed in a single line lambda as the top level statement. Report the error here because it is legal ' to have a single line if which contains a local declaration. If the error reporting is done in BindStatement then all local ' declarations are prohibited. ' Bind local declaration, discard diagnostics block = bodyBinder.BindBlock(lambdaSyntax, singleLineLambdaSyntax.Statements, BindingDiagnosticBag.Discarded).MakeCompilerGenerated() ' Generate a diagnostic and a bad statement node ReportDiagnostic(diagnostics, statement, ERRID.ERR_SubDisallowsStatement) Else block = bodyBinder.BindBlock(lambdaSyntax, singleLineLambdaSyntax.Statements, diagnostics).MakeCompilerGenerated() End If Case SyntaxKind.MultiLineFunctionLambdaExpression, SyntaxKind.MultiLineSubLambdaExpression Dim blockSyntax = DirectCast(lambdaSyntax, MultiLineLambdaExpressionSyntax) endSyntax = blockSyntax.EndSubOrFunctionStatement block = bodyBinder.BindBlock(lambdaSyntax, blockSyntax.Statements, diagnostics).MakeCompilerGenerated() Case Else Throw ExceptionUtilities.UnexpectedValue(lambdaSyntax.Kind) End Select Dim localBuilder = ArrayBuilder(Of LocalSymbol).GetInstance() ' TODO: this is adapted from BindMethodBody. It handles adding a return value local if needed and ' a function epilogue for the exit label ' for single line lambdas it may make sense to do in-place ' ' add indirect return sequence ' and maybe an indirect result local (if this is a function) Dim statements = ArrayBuilder(Of BoundStatement).GetInstance statements.AddRange(block.Statements) Select Case lambdaSyntax.Kind Case SyntaxKind.SingleLineFunctionLambdaExpression, SyntaxKind.MultiLineFunctionLambdaExpression Dim localForFunctionValue = bodyBinder.GetLocalForFunctionValue localBuilder.Add(localForFunctionValue) Dim returnLabel = New BoundLabelStatement(endSyntax, bodyBinder.GetReturnLabel()) Dim boundLocal = New BoundLocal(endSyntax, localForFunctionValue, isLValue:=False, type:=localForFunctionValue.Type).MakeCompilerGenerated() Dim returnStmt = New BoundReturnStatement(endSyntax, boundLocal, Nothing, Nothing) If lambdaSyntax.Kind = SyntaxKind.SingleLineFunctionLambdaExpression OrElse endSyntax Is lambdaSyntax Then returnLabel.SetWasCompilerGenerated() returnStmt.SetWasCompilerGenerated() End If statements.Add(returnLabel) statements.Add(returnStmt) Case SyntaxKind.SingleLineSubLambdaExpression, SyntaxKind.MultiLineSubLambdaExpression Dim returnLabel = New BoundLabelStatement(endSyntax, bodyBinder.GetReturnLabel()) Dim returnStmt = New BoundReturnStatement(endSyntax, Nothing, Nothing, Nothing) If lambdaSyntax.Kind = SyntaxKind.SingleLineSubLambdaExpression OrElse endSyntax Is lambdaSyntax Then returnLabel.SetWasCompilerGenerated() returnStmt.SetWasCompilerGenerated() End If statements.Add(returnLabel) statements.Add(returnStmt) End Select #If DEBUG Then lambdaBinder.EnableSimpleNameBindingOrderChecks(False) #End If If implicitVariablesBinder IsNot Nothing Then ' Add any implicitly declared variables to the block. implicitVariablesBinder.DisallowFurtherImplicitVariableDeclaration(diagnostics) localBuilder.AddRange(implicitVariablesBinder.ImplicitlyDeclaredVariables) End If If Not block.Locals.IsEmpty Then localBuilder.AddRange(block.Locals) End If block = block.Update(block.StatementListSyntax, localBuilder.ToImmutableAndFree(), statements.ToImmutableAndFree) block.SetWasCompilerGenerated() If lambdaSymbol.IsAsync AndAlso Not CheckAwaitWalker.VisitBlock(bodyBinder, block, diagnostics) AndAlso Not block.HasErrors AndAlso Not lambdaSymbol.IsIterator Then ReportDiagnostic(diagnostics, DirectCast(lambdaSyntax, LambdaExpressionSyntax).SubOrFunctionHeader.DeclarationKeyword, ERRID.WRN_AsyncLacksAwaits) End If Return block End Function Private Class CheckAwaitWalker Inherits BoundTreeWalkerWithStackGuardWithoutRecursionOnTheLeftOfBinaryOperator Private ReadOnly _binder As Binder Private ReadOnly _diagnostics As BindingDiagnosticBag Private _isInCatchFinallyOrSyncLock As Boolean Private _containsAwait As Boolean Private Sub New(binder As Binder, diagnostics As BindingDiagnosticBag) _diagnostics = diagnostics _binder = binder End Sub Public Shared Shadows Function VisitBlock( binder As Binder, block As BoundBlock, diagnostics As BindingDiagnosticBag ) As Boolean Debug.Assert(binder.IsInAsyncContext()) Try Dim walker As New CheckAwaitWalker(binder, diagnostics) walker.Visit(block) Debug.Assert(Not walker._isInCatchFinallyOrSyncLock) Return walker._containsAwait Catch ex As CancelledByStackGuardException ex.AddAnError(diagnostics) Return True End Try End Function Public Overrides Function VisitTryStatement(node As BoundTryStatement) As BoundNode Debug.Assert(Not node.WasCompilerGenerated) Visit(node.TryBlock) Dim save_m_isInCatchFinallyOrSyncLock As Boolean = _isInCatchFinallyOrSyncLock _isInCatchFinallyOrSyncLock = True VisitList(node.CatchBlocks) Visit(node.FinallyBlockOpt) _isInCatchFinallyOrSyncLock = save_m_isInCatchFinallyOrSyncLock Return Nothing End Function Public Overrides Function VisitSyncLockStatement(node As BoundSyncLockStatement) As BoundNode Debug.Assert(Not node.WasCompilerGenerated) Dim save_m_isInCatchFinallyOrSyncLock As Boolean = _isInCatchFinallyOrSyncLock _isInCatchFinallyOrSyncLock = True MyBase.VisitSyncLockStatement(node) _isInCatchFinallyOrSyncLock = save_m_isInCatchFinallyOrSyncLock Return Nothing End Function Public Overrides Function VisitAwaitOperator(node As BoundAwaitOperator) As BoundNode Debug.Assert(_binder.IsInAsyncContext()) _containsAwait = True If _isInCatchFinallyOrSyncLock Then ReportDiagnostic(_diagnostics, node.Syntax, ERRID.ERR_BadAwaitInTryHandler) End If Return MyBase.VisitAwaitOperator(node) End Function Public Overrides Function VisitLambda(node As BoundLambda) As BoundNode ' Do not dive into the lambdas. Return Nothing End Function End Class Public Sub ReportLambdaParameterInferredToBeObject(unboundParam As UnboundLambdaParameterSymbol, diagnostics As BindingDiagnosticBag) If OptionStrict = OptionStrict.On Then ReportDiagnostic(diagnostics, unboundParam.IdentifierSyntax, ERRID.ERR_StrictDisallowImplicitObjectLambda) ElseIf OptionStrict = OptionStrict.Custom Then ReportDiagnostic(diagnostics, unboundParam.IdentifierSyntax, ERRID.WRN_ObjectAssumedVar1, ErrorFactory.ErrorInfo(ERRID.WRN_MissingAsClauseinVarDecl)) End If End Sub ''' <summary> ''' If we are inside a lambda in a constructor and are passing ByRef a non-LValue field, which ''' would be an LValue field, if it were referred to in the constructor outside of a lambda, ''' we need to report an error because the operation will result in a simulated pass by ''' ref (through a temp, without a copy back), which might be not the intent. ''' </summary> Public Function Report_ERRID_ReadOnlyInClosure(argument As BoundExpression) As Boolean Debug.Assert(Not argument.IsLValue()) If argument.HasErrors Then Return False End If Dim containingMember As Symbol = Me.ContainingMember If containingMember Is Nothing Then Return False End If Dim receiverOpt As BoundExpression Dim field As FieldSymbol If argument.Kind = BoundKind.PropertyAccess Then Dim propAccess = DirectCast(argument, BoundPropertyAccess) Dim propSym = TryCast(propAccess.PropertySymbol, SourcePropertySymbol) If propSym Is Nothing OrElse Not propSym.IsReadOnly Then Return False End If field = propSym.AssociatedField receiverOpt = propAccess.ReceiverOpt If field Is Nothing Then Return False End If ElseIf argument.Kind = BoundKind.FieldAccess Then Dim fieldAccess = DirectCast(argument, BoundFieldAccess) receiverOpt = fieldAccess.ReceiverOpt field = fieldAccess.FieldSymbol receiverOpt = fieldAccess.ReceiverOpt Else Return False End If ' The business of figuring out whether a field access should be considered an LValue is rather complicated, ' it is easy to get wrong and Dev10 gets it wrong for this check in many scenarios. What we will do instead, ' we will recalculate LValue status for the field access in context of the binder for the constructor or ' binder for a field or property initializer. ' We will construct some throw-away nodes in the process, but I believe it is a good tradeoff. Dim nonLambdaBinder As Binder = Nothing If containingMember.IsLambdaMethod Then Dim binderForExpressionContainingLambda As Binder = Nothing ' Ok, we are inside a lambda. ' Bubble up to the containing method or initializer. Do binderForExpressionContainingLambda = DirectCast(containingMember, LambdaSymbol).ContainingBinder containingMember = containingMember.ContainingSymbol Debug.Assert(binderForExpressionContainingLambda.ContainingMember Is containingMember) Loop While containingMember IsNot Nothing AndAlso containingMember.IsLambdaMethod Dim containingMethodKind As MethodKind = binderForExpressionContainingLambda.KindOfContainingMethodAtRunTime() Select Case containingMethodKind Case MethodKind.SharedConstructor, MethodKind.Constructor nonLambdaBinder = binderForExpressionContainingLambda End Select End If If nonLambdaBinder Is Nothing Then ' Either we are not in a lambda or not in a constructor. Return False End If If receiverOpt Is Nothing OrElse receiverOpt.Kind <> BoundKind.FieldAccess Then ' Simple case only one field access in the chain. Return nonLambdaBinder.IsLValueFieldAccess(field, receiverOpt) Else Dim fields = ArrayBuilder(Of FieldSymbol).GetInstance() fields.Add(field) Do Dim fieldAccess = DirectCast(receiverOpt, BoundFieldAccess) fields.Add(fieldAccess.FieldSymbol) receiverOpt = fieldAccess.ReceiverOpt Loop While receiverOpt IsNot Nothing AndAlso receiverOpt.Kind = BoundKind.FieldAccess For i As Integer = fields.Count - 1 To 0 Step -1 Dim fieldSymbol As FieldSymbol = fields(i) receiverOpt = New BoundFieldAccess(argument.Syntax, receiverOpt, fieldSymbol, nonLambdaBinder.IsLValueFieldAccess(fieldSymbol, receiverOpt), type:=fieldSymbol.Type) Next fields.Free() Return receiverOpt.IsLValue() End If End Function Friend Function InferAnonymousDelegateForLambda(source As UnboundLambda) As KeyValuePair(Of NamedTypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol)) Debug.Assert(Me Is source.Binder) Dim diagnostics = BindingDiagnosticBag.GetInstance(withDiagnostics:=True, source.WithDependencies) ' Using Void as return type, because BuildBoundLambdaParameters doesn't use it and it is as good as any other value. Dim targetSignature As New UnboundLambda.TargetSignature(ImmutableArray(Of ParameterSymbol).Empty, Compilation.GetSpecialType(SpecialType.System_Void), returnsByRef:=False) Dim parameters As ImmutableArray(Of BoundLambdaParameterSymbol) = BuildBoundLambdaParameters(source, targetSignature, diagnostics) Dim returnTypeInfo As KeyValuePair(Of TypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol)) returnTypeInfo = source.InferReturnType(New UnboundLambda.TargetSignature(StaticCast(Of ParameterSymbol).From(parameters), targetSignature.ReturnType, targetSignature.ReturnsByRef)) Dim returnType As TypeSymbol = returnTypeInfo.Key diagnostics.AddRange(returnTypeInfo.Value) Dim delegateType As NamedTypeSymbol = ConstructAnonymousDelegateSymbol(source, parameters, returnType, diagnostics) Return New KeyValuePair(Of NamedTypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol))(delegateType, diagnostics.ToReadOnlyAndFree()) End Function Private Function ConstructAnonymousDelegateSymbol( source As UnboundLambda, parameters As ImmutableArray(Of BoundLambdaParameterSymbol), returnType As TypeSymbol, diagnostics As BindingDiagnosticBag ) As NamedTypeSymbol Debug.Assert(source.IsFunctionLambda = Not returnType.IsVoidType()) Dim parameterDescriptors(parameters.Length) As AnonymousTypeField Dim i As Integer For i = 0 To parameters.Length - 1 Dim sourceParameter = DirectCast(source.Parameters(i), UnboundLambdaParameterSymbol) parameterDescriptors(i) = New AnonymousTypeField( parameters(i).Name, parameters(i).Type, sourceParameter.Syntax.GetLocation(), parameters(i).IsByRef) ' Verify for restricted types. If parameters(i).Type.IsRestrictedType() Then ReportDiagnostic(diagnostics, sourceParameter.TypeSyntax, ERRID.ERR_RestrictedType1, parameters(i).Type) End If Next Dim returnParamName = AnonymousTypeDescriptor.GetReturnParameterName(source.IsFunctionLambda) parameterDescriptors(i) = New AnonymousTypeField(returnParamName, returnType, source.Syntax.GetLocation(), False) Dim typeDescriptor As New AnonymousTypeDescriptor(parameterDescriptors.AsImmutableOrNull(), source.Syntax.GetLocation(), True) Return Me.Compilation.AnonymousTypeManager.ConstructAnonymousDelegateSymbol(typeDescriptor) End Function Friend Function BindLambdaForErrorRecovery(source As UnboundLambda) As BoundLambda If source.BindingCache.ErrorRecoverySignature Is Nothing Then ' Let's examine what target signatures did we try to apply to this lambda and let's ' get common types from them. Dim commonReturnType As TypeSymbol = Nothing Dim commonParameterTypes(source.Parameters.Length - 1) As TypeSymbol For Each pair In source.BindingCache.InferredReturnType Dim target As UnboundLambda.TargetSignature = pair.Key For i As Integer = 0 To Math.Min(target.ParameterTypes.Length, commonParameterTypes.Length) - 1 BindLambdaForErrorRecoveryInferCommonType(commonParameterTypes(i), target.ParameterTypes(i)) Next BindLambdaForErrorRecoveryInferCommonType(commonReturnType, pair.Value.Key) Next For Each pair In source.BindingCache.BoundLambdas Dim target As UnboundLambda.TargetSignature = pair.Key For i As Integer = 0 To Math.Min(target.ParameterTypes.Length, commonParameterTypes.Length) - 1 BindLambdaForErrorRecoveryInferCommonType(commonParameterTypes(i), target.ParameterTypes(i)) Next BindLambdaForErrorRecoveryInferCommonType(commonReturnType, target.ReturnType) Next Dim isByRef = BitVector.Empty For i As Integer = 0 To commonParameterTypes.Length - 1 If source.Parameters(i).Type IsNot Nothing Then commonParameterTypes(i) = source.Parameters(i).Type ElseIf commonParameterTypes(i) Is Nothing OrElse commonParameterTypes(i) Is LambdaSymbol.ErrorRecoveryInferenceError Then ' Use Object for types we couldn't infer commonParameterTypes(i) = Compilation.GetSpecialType(SpecialType.System_Object) End If If source.Parameters(i).IsByRef Then isByRef(i) = True End If Next If source.ReturnType IsNot Nothing Then commonReturnType = If(source.IsFunctionLambda AndAlso source.ReturnType.IsVoidType(), LambdaSymbol.ReturnTypeVoidReplacement, source.ReturnType) ElseIf commonReturnType Is Nothing OrElse commonReturnType Is LambdaSymbol.ErrorRecoveryInferenceError Then commonReturnType = source.InferReturnType(New UnboundLambda.TargetSignature(commonParameterTypes.AsImmutableOrNull(), isByRef, Compilation.GetSpecialType(SpecialType.System_Void), returnsByRef:=False)).Key End If Interlocked.CompareExchange(source.BindingCache.ErrorRecoverySignature, New UnboundLambda.TargetSignature(commonParameterTypes.AsImmutableOrNull(), isByRef, commonReturnType, returnsByRef:=False), Nothing) End If Return source.Bind(source.BindingCache.ErrorRecoverySignature) End Function Private Shared Sub BindLambdaForErrorRecoveryInferCommonType(ByRef result As TypeSymbol, candidate As TypeSymbol) If result Is Nothing Then result = candidate ElseIf result IsNot LambdaSymbol.ErrorRecoveryInferenceError Then If Not result.IsSameTypeIgnoringAll(candidate) Then result = LambdaSymbol.ErrorRecoveryInferenceError End If End If End Sub Friend Function InferFunctionLambdaReturnType( source As UnboundLambda, targetParameters As UnboundLambda.TargetSignature ) As KeyValuePair(Of TypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol)) Debug.Assert(Me Is source.Binder AndAlso source.IsFunctionLambda AndAlso source.ReturnType Is Nothing AndAlso targetParameters.ReturnType.IsVoidType()) ' If both Async and Iterator are specified, we cannot really infer return type. If source.Flags = (SourceMemberFlags.Async Or SourceMemberFlags.Iterator) Then ' No need to report any error because we complained about conflicting modifiers. Return New KeyValuePair(Of TypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol))(LambdaSymbol.ReturnTypeIsUnknown, ReadOnlyBindingDiagnostic(Of AssemblySymbol).Empty) End If Dim diagnostics = BindingDiagnosticBag.GetInstance(withDiagnostics:=True, source.WithDependencies) ' Clone parameters. Dim parameters As ImmutableArray(Of BoundLambdaParameterSymbol) = BuildBoundLambdaParameters(source, targetParameters, diagnostics) Dim symbol = New SourceLambdaSymbol(source.Syntax, source, parameters, LambdaSymbol.ReturnTypeIsBeingInferred, Me) Dim block As BoundBlock = BindLambdaBody(symbol, diagnostics, lambdaBinder:=Nothing) If block.HasErrors OrElse diagnostics.HasAnyErrors() Then Return New KeyValuePair(Of TypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol))(LambdaSymbol.ReturnTypeIsUnknown, diagnostics.ToReadOnlyAndFree()) End If diagnostics.Clear() Dim lambdaReturnType As TypeSymbol Dim returnExpressions = ArrayBuilder(Of BoundExpression).GetInstance() LambdaReturnStatementsVisitor.CollectReturnExpressions(block, returnExpressions, source.Flags = SourceMemberFlags.Iterator) If returnExpressions.Count = 0 AndAlso source.Flags = SourceMemberFlags.Async Then ' It's fine if there were no return statements in an Async Function. ' It simply returns "Task". lambdaReturnType = GetWellKnownType(WellKnownType.System_Threading_Tasks_Task, source.Syntax, diagnostics) ElseIf returnExpressions.Count = 0 AndAlso source.Flags = SourceMemberFlags.Iterator Then ' It's fine if there were no yield statements in an Iterator Function. ' It simply returns IEnumerable(of Object). lambdaReturnType = GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T, source.Syntax, diagnostics). Construct(GetSpecialType(SpecialType.System_Object, source.Syntax, diagnostics)) Else ' Inference is different for Expression and Statement lambdas If source.IsSingleLine Then Debug.Assert(returnExpressions.Count < 2) Dim returnExpression As BoundExpression = Nothing If returnExpressions.Count > 0 Then returnExpression = MakeRValue(returnExpressions(0), diagnostics) End If If returnExpression IsNot Nothing AndAlso Not returnExpression.HasErrors AndAlso Not diagnostics.HasAnyErrors() Then lambdaReturnType = returnExpression.Type Else lambdaReturnType = GetSpecialType(SpecialType.System_Object, source.Syntax, diagnostics) End If diagnostics.Clear() Dim restrictedType As TypeSymbol = Nothing If lambdaReturnType.IsRestrictedTypeOrArrayType(restrictedType) Then ReportDiagnostic(diagnostics, LambdaHeaderErrorNode(source), ERRID.ERR_RestrictedType1, restrictedType) End If Else Dim numCandidates As Integer = 0 lambdaReturnType = InferDominantTypeOfExpressions(source.Syntax, returnExpressions, diagnostics, numCandidates) Debug.Assert(lambdaReturnType IsNot Nothing OrElse numCandidates = 0) Dim restrictedType As TypeSymbol = Nothing If lambdaReturnType Is Nothing Then ' "Cannot infer a return type. Specifying the return type might correct this error." ReportDiagnostic(diagnostics, LambdaHeaderErrorNode(source), ERRID.ERR_LambdaNoType) lambdaReturnType = LambdaSymbol.ReturnTypeIsUnknown ElseIf lambdaReturnType.IsRestrictedTypeOrArrayType(restrictedType) Then ReportDiagnostic(diagnostics, LambdaHeaderErrorNode(source), ERRID.ERR_RestrictedType1, restrictedType) ElseIf numCandidates <> 1 Then If OptionStrict = OptionStrict.On Then If numCandidates = 0 Then ' "Cannot infer a return type, and Option Strict On does not allow 'Object' to be assumed. Specifying the return type might correct this error." ReportDiagnostic(diagnostics, LambdaHeaderErrorNode(source), ERRID.ERR_LambdaNoTypeObjectDisallowed) Debug.Assert(lambdaReturnType.IsObjectType()) Else ' "Cannot infer a return type because more than one type is possible. Specifying the return type might correct this error." ReportDiagnostic(diagnostics, LambdaHeaderErrorNode(source), ERRID.ERR_LambdaTooManyTypesObjectDisallowed) Debug.Assert(lambdaReturnType.IsObjectType()) End If ElseIf OptionStrict = OptionStrict.Custom Then If numCandidates = 0 Then ' "Cannot infer a return type; 'Object' assumed." ReportDiagnostic(diagnostics, LambdaHeaderErrorNode(source), ERRID.WRN_ObjectAssumed1, ErrorFactory.ErrorInfo(ERRID.WRN_LambdaNoTypeObjectAssumed)) Debug.Assert(lambdaReturnType.IsObjectType()) Else ' "Cannot infer a return type because more than one type is possible; 'Object' assumed." ReportDiagnostic(diagnostics, LambdaHeaderErrorNode(source), ERRID.WRN_ObjectAssumed1, ErrorFactory.ErrorInfo(ERRID.WRN_LambdaTooManyTypesObjectAssumed)) Debug.Assert(lambdaReturnType.IsObjectType()) End If End If End If End If If source.Flags = SourceMemberFlags.Async Then ' There were some returns with values from Async lambda, infer Task(Of T) as return type of the lambda. lambdaReturnType = GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T, source.Syntax, diagnostics).Construct(lambdaReturnType) ElseIf source.Flags = SourceMemberFlags.Iterator Then ' There were some returns with values from Iterator lambda, infer IEnumerable(Of T) as return type of the lambda. lambdaReturnType = GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T, source.Syntax, diagnostics).Construct(lambdaReturnType) End If End If returnExpressions.Free() Return New KeyValuePair(Of TypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol))(lambdaReturnType, diagnostics.ToReadOnlyAndFree()) End Function Private Shared Function LambdaHeaderErrorNode(source As UnboundLambda) As SyntaxNode Dim lambdaSyntax = TryCast(source.Syntax, LambdaExpressionSyntax) If lambdaSyntax IsNot Nothing Then Return lambdaSyntax.SubOrFunctionHeader End If Return source.Syntax End Function Private Class LambdaReturnStatementsVisitor Inherits StatementWalker Private ReadOnly _builder As ArrayBuilder(Of BoundExpression) Private ReadOnly _isIterator As Boolean Private Sub New(builder As ArrayBuilder(Of BoundExpression), isIterator As Boolean) Me._builder = builder Me._isIterator = isIterator End Sub ''' <summary> ''' Collects expressions that are effective return values of the lambda body. ''' In iterators those would be arguments of Yield statements. ''' </summary> Public Shared Sub CollectReturnExpressions(lambdaBlock As BoundBlock, arrayToFill As ArrayBuilder(Of BoundExpression), isIterator As Boolean) Dim visitor = New LambdaReturnStatementsVisitor(arrayToFill, isIterator) visitor.VisitBlock(lambdaBlock) End Sub Public Overrides Function Visit(node As BoundNode) As BoundNode 'Do not visit expressions If node Is Nothing OrElse TypeOf node Is BoundExpression Then Return Nothing End If Return MyBase.Visit(node) End Function Public Overrides Function VisitLambda(node As BoundLambda) As BoundNode Throw ExceptionUtilities.Unreachable End Function Public Overrides Function VisitReturnStatement(node As BoundReturnStatement) As BoundNode ' not interested in Returns in an iterator. If _isIterator Then Return Nothing End If Dim expr As BoundExpression = node.ExpressionOpt ' Skip synthetic return for the function variable. If expr Is Nothing OrElse expr.Type Is LambdaSymbol.ReturnTypeIsBeingInferred Then Return Nothing End If _builder.Add(expr) Return Nothing End Function Public Overrides Function VisitYieldStatement(node As BoundYieldStatement) As BoundNode If _isIterator Then _builder.Add(node.Expression) End If Return Nothing End Function End Class End Class ''' <summary> ''' Provides context for binding body of a Lambda. ''' </summary> Friend NotInheritable Class LambdaBodyBinder Inherits SubOrFunctionBodyBinder Private ReadOnly _functionValue As LocalSymbol Public Sub New(lambdaSymbol As LambdaSymbol, containingBinder As Binder) MyBase.New(lambdaSymbol, lambdaSymbol.Syntax, containingBinder) _functionValue = CreateFunctionValueLocal(lambdaSymbol) End Sub Private Shared Function CreateFunctionValueLocal(lambdaSymbol As LambdaSymbol) As LocalSymbol ' synthesized lambdas may not result from a LambdaExpressionSyntax (e.g. an AddressOf expression that ' needs relaxation). In this case there will be no need to create a local here, this is done when generating the ' lambda body. If lambdaSymbol.IsImplicitlyDeclared OrElse lambdaSymbol.IsSub Then Return Nothing End If Dim header As LambdaHeaderSyntax = DirectCast(lambdaSymbol.Syntax, LambdaExpressionSyntax).SubOrFunctionHeader Return New SynthesizedLocal(lambdaSymbol, lambdaSymbol.ReturnType, SynthesizedLocalKind.FunctionReturnValue, header) End Function Public Overrides Function GetLocalForFunctionValue() As LocalSymbol Return _functionValue End Function Public Overrides Function GetContinueLabel(continueSyntaxKind As SyntaxKind) As LabelSymbol Return Nothing End Function Public Overrides Function GetExitLabel(exitSyntaxKind As SyntaxKind) As LabelSymbol Return Nothing End Function Public Overrides Function GetReturnLabel() As LabelSymbol Return Nothing End Function Friend Overrides Sub LookupInSingleBinder(lookupResult As LookupResult, name As String, arity As Integer, options As LookupOptions, originalBinder As Binder, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) MyBase.LookupInSingleBinder(lookupResult, name, arity, options, originalBinder, useSiteInfo) If (options And LookupOptions.LabelsOnly) = LookupOptions.LabelsOnly Then If lookupResult.Kind = LookupResultKind.Empty Then lookupResult.SetFrom(SingleLookupResult.EmptyAndStopLookup) End If End If End Sub End Class End Namespace