Пример #1
0
            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);
            }
Пример #2
0
        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);
        }
Пример #5
0
        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);
        }
Пример #7
0
        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;
            }
        }
Пример #8
0
 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);
     }
 }
Пример #9
0
 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);
     }
 }
Пример #10
0
            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);
            }
Пример #11
0
        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);
        }
Пример #12
0
        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;
        }
Пример #14
0
        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);
        }
Пример #17
0
        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;
        }
Пример #20
0
            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;
            }
Пример #21
0
        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&lt;T&gt;, 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);
        }
Пример #22
0
 public override BoundNode VisitLambda(BoundLambda node)
 {
     // Do not recurse into nested lambdas; we don't want their returns.
     return(null);
 }
Пример #23
0
        private BoundExpression VisitLambda(BoundLambda node)
        {
            var result = VisitLambdaInternal(node);

            return(node.Type.IsExpressionTree() ? ExprFactory("Quote", result) : result);
        }
Пример #24
0
            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;
            }
Пример #25
0
        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&lt;T&gt;, 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;
        }
Пример #26
0
        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;
 }
Пример #28
0
 public override BoundNode VisitLambda(BoundLambda node)
 {
     MakeSlots(node.Symbol.Parameters);
     return(base.VisitLambda(node));
 }
Пример #29
0
        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&lt;T&gt;, 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);
        }
Пример #30
0
 // 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));
 }
Пример #31
0
 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);
 }
Пример #33
0
        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;
        }
Пример #34
0
 public override BoundNode VisitLambda(BoundLambda node)
 {
     MakeSlots(node.Symbol.Parameters);
     return base.VisitLambda(node);
 }
Пример #35
0
 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);
        }
Пример #37
0
 public override BoundNode VisitLambda(BoundLambda node)
 {
     // these nodes have been handled in the context of the enclosing anonymous method conversion.
     throw ExceptionUtilities.Unreachable;
 }
Пример #38
0
        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&lt;T&gt;, 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;
 }
Пример #40
0
        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));
        }
Пример #41
0
        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;
     }
 }
Пример #43
0
 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;
        }
Пример #45
0
        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&lt;T&gt;, 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;
        }