Пример #1
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: CodeAnalysis.RefKind.None,
                returnType: null,
                diagnostics: diagnostics);
            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);
        }
Пример #2
0
        // Tests just the errors found while binding method M in class C.
        public void TestErrors(string code, params string[] errors)
        {
            var compilation            = CreateCompilationWithMscorlib(code);
            var method                 = (SourceMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("M").Single();
            var factory                = compilation.GetBinderFactory(method.SyntaxTree);
            var parameterBinderContext = factory.GetBinder(method.BlockSyntax);
            var binder                 = new ExecutableCodeBinder(method.BlockSyntax.Parent, method, parameterBinderContext);
            var diagnostics            = new DiagnosticBag();
            var block = (BoundBlock)binder.BindStatement(method.BlockSyntax, diagnostics);

            AssertEx.SetEqual(errors, diagnostics.AsEnumerable().Select(DumpDiagnostic));
        }
Пример #3
0
 public void TestErrors(string code, params string[] errors)
 {
     var compilation = CreateCompilationWithMscorlib(code);
     var method = (SourceMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("M").Single();
     var factory = compilation.GetBinderFactory(method.SyntaxTree);
     var bodyBlock = (BlockSyntax)method.BodySyntax;
     var parameterBinderContext = factory.GetBinder(bodyBlock);
     var binder = new ExecutableCodeBinder(bodyBlock.Parent, method, parameterBinderContext);
     var diagnostics = new DiagnosticBag();
     var block = binder.BindEmbeddedBlock(bodyBlock, diagnostics);
     AssertEx.SetEqual(errors, diagnostics.AsEnumerable().Select(DumpDiagnostic));
 }
Пример #4
0
        public void TestErrors(string code, params string[] errors)
        {
            var compilation            = CreateStandardCompilation(code);
            var method                 = (SourceMemberMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("M").Single();
            var factory                = compilation.GetBinderFactory(method.SyntaxTree);
            var bodyBlock              = (BlockSyntax)method.BodySyntax;
            var parameterBinderContext = factory.GetBinder(bodyBlock);
            var binder                 = new ExecutableCodeBinder(bodyBlock.Parent, method, parameterBinderContext);
            var diagnostics            = new DiagnosticBag();
            var block = binder.BindEmbeddedBlock(bodyBlock, diagnostics);

            AssertEx.SetEqual(errors, diagnostics.AsEnumerable().Select(DumpDiagnostic));
        }
Пример #5
0
        public void TestWarnings(string code, params string[] expectedWarnings)
        {
            var compilation            = CreateCompilationWithMscorlib(code);
            var method                 = (SourceMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("M").Single();
            var factory                = compilation.GetBinderFactory(method.SyntaxTree);
            var bodyBlock              = (BlockSyntax)method.BodySyntax;
            var parameterBinderContext = factory.GetBinder(bodyBlock);
            var binder                 = new ExecutableCodeBinder(bodyBlock.Parent, method, parameterBinderContext);
            var block          = (BoundBlock)binder.BindStatement(bodyBlock, new DiagnosticBag());
            var actualWarnings = new DiagnosticBag();

            DiagnosticsPass.IssueDiagnostics(compilation, block, actualWarnings, method);
            AssertEx.SetEqual(expectedWarnings, actualWarnings.AsEnumerable().Select(DumpDiagnostic));
        }
Пример #6
0
        private static BoundExpression BindFieldOrEnumInitializer(
            Binder binder,
            FieldSymbol fieldSymbol,
            EqualsValueClauseSyntax initializer,
            DiagnosticBag diagnostics)
        {
            var enumConstant = fieldSymbol as SourceEnumConstantSymbol;
            Binder collisionDetector = new LocalScopeBinder(binder);
            collisionDetector = new ExecutableCodeBinder(initializer, fieldSymbol, collisionDetector);
            BoundExpression result;

            if ((object)enumConstant != null)
            {
                result = collisionDetector.BindEnumConstantInitializer(enumConstant, initializer, diagnostics);
            }
            else
            {
                result = collisionDetector.BindVariableOrAutoPropInitializer(initializer, RefKind.None, fieldSymbol.Type, diagnostics);
            }

            return result;
        }
Пример #7
0
        private static BoundFieldEqualsValue BindFieldOrEnumInitializer(
            Binder binder,
            FieldSymbol fieldSymbol,
            EqualsValueClauseSyntax initializer,
            BindingDiagnosticBag diagnostics)
        {
            var    enumConstant      = fieldSymbol as SourceEnumConstantSymbol;
            Binder collisionDetector = new LocalScopeBinder(binder);

            collisionDetector = new ExecutableCodeBinder(initializer, fieldSymbol, collisionDetector);
            BoundFieldEqualsValue result;

            if ((object)enumConstant != null)
            {
                result = collisionDetector.BindEnumConstantInitializer(enumConstant, initializer, diagnostics);
            }
            else
            {
                result = collisionDetector.BindFieldInitializer(fieldSymbol, initializer, diagnostics);
            }

            return(result);
        }
Пример #8
0
        private static BoundExpression BindFieldOrEnumInitializer(
            Binder binder,
            FieldSymbol fieldSymbol,
            EqualsValueClauseSyntax initializer,
            DiagnosticBag diagnostics)
        {
            var    enumConstant      = fieldSymbol as SourceEnumConstantSymbol;
            Binder collisionDetector = new LocalScopeBinder(binder);

            collisionDetector = new ExecutableCodeBinder(initializer, fieldSymbol, collisionDetector);
            BoundExpression result;

            if ((object)enumConstant != null)
            {
                result = collisionDetector.BindEnumConstantInitializer(enumConstant, initializer, diagnostics);
            }
            else
            {
                result = collisionDetector.BindVariableOrAutoPropInitializer(initializer, RefKind.None, fieldSymbol.Type, diagnostics);
            }

            return(result);
        }
Пример #9
0
 public void TestWarnings(string code, params string[] expectedWarnings)
 {
     var compilation = CreateCompilationWithMscorlib(code);
     var method = (SourceMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("M").Single();
     var factory = compilation.GetBinderFactory(method.SyntaxTree);
     var bodyBlock = (BlockSyntax)method.BodySyntax;
     var parameterBinderContext = factory.GetBinder(bodyBlock);
     var binder = new ExecutableCodeBinder(bodyBlock.Parent, method, parameterBinderContext);
     var block = (BoundBlock)binder.BindStatement(bodyBlock, new DiagnosticBag());
     var actualWarnings = new DiagnosticBag();
     DiagnosticsPass.IssueDiagnostics(compilation, block, actualWarnings, method);
     AssertEx.SetEqual(expectedWarnings, actualWarnings.AsEnumerable().Select(DumpDiagnostic));
 }
Пример #10
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,
                diagnostics);
            lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder));

            if (lambdaSymbol.RefKind == CodeAnalysis.RefKind.RefReadOnly)
            {
                binder.Compilation.EnsureIsReadOnlyAttributeExists(diagnostics, lambdaSymbol.DiagnosticLocation, modifyCompilationForRefReadOnly: false);
            }

            ParameterHelpers.EnsureIsReadOnlyAttributeExists(lambdaSymbol.Parameters, diagnostics, modifyCompilationForRefReadOnly: false);

            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);
                SourceOrdinaryMethodSymbol.ReportAsyncParameterErrors(lambdaSymbol.Parameters, diagnostics, lambdaSymbol.DiagnosticLocation);
            }

            var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: false)
            {
                WasCompilerGenerated = _unboundLambda.WasCompilerGenerated
            };

            return(result);
        }
        /// <summary>
        /// Performs the same function as GetEnclosingBinder, but is known to take place within a
        /// specified lambda.  Walks up the syntax hierarchy until a node with an associated binder
        /// is found.
        /// </summary>
        /// <remarks>
        /// CONSIDER: can this share code with MemberSemanticModel.GetEnclosingBinder?
        /// </remarks>
        private Binder GetLambdaEnclosingBinder(int position, SyntaxNode startingNode, SyntaxNode containingLambda, ExecutableCodeBinder lambdaBinder)
        {
            AssertPositionAdjusted(position);
            Debug.Assert(containingLambda.IsAnonymousFunction());
            Debug.Assert(LookupPosition.IsInAnonymousFunctionOrQuery(position, containingLambda));

            var current = startingNode;
            while (current != containingLambda)
            {
                Debug.Assert(current != null);

                StatementSyntax stmt = current as StatementSyntax;
                if (stmt != null)
                {
                    if (LookupPosition.IsInStatementScope(position, stmt))
                    {
                        Binder binder = lambdaBinder.GetBinder(current);
                        if (binder != null)
                        {
                            return binder;
                        }
                    }
                }
                else if (current.Kind == SyntaxKind.CatchClause)
                {
                    if (LookupPosition.IsInCatchClauseScope(position, (CatchClauseSyntax)current))
                    {
                        Binder binder = lambdaBinder.GetBinder(current);
                        if (binder != null)
                        {
                            return binder;
                        }
                    }
                }
                else if (current.IsAnonymousFunction())
                {
                    if (LookupPosition.IsInAnonymousFunctionOrQuery(position, current))
                    {
                        Binder binder = lambdaBinder.GetBinder(current);
                        if (binder != null)
                        {
                            return binder;
                        }
                    }
                }
                else
                {
                    // If this ever breaks, make sure that all callers of
                    // CanHaveAssociatedLocalBinder are in sync.
                    Debug.Assert(!current.CanHaveAssociatedLocalBinder());
                }

                current = current.Parent;
            }

            return lambdaBinder;
        }
Пример #12
0
        /// <summary>
        /// Performs the same function as GetEnclosingBinder, but is known to take place within a
        /// specified lambda.  Walks up the syntax hierarchy until a node with an associated binder
        /// is found.
        /// </summary>
        /// <remarks>
        /// CONSIDER: can this share code with MemberSemanticModel.GetEnclosingBinder?
        /// </remarks>
        private Binder GetLambdaEnclosingBinder(int position, SyntaxNode startingNode, SyntaxNode containingLambda, ExecutableCodeBinder lambdaBinder)
        {
            AssertPositionAdjusted(position);
            Debug.Assert(containingLambda.IsAnonymousFunction());
            Debug.Assert(LookupPosition.IsInAnonymousFunctionOrQuery(position, containingLambda));

            var current = startingNode;

            while (current != containingLambda)
            {
                Debug.Assert(current != null);

                StatementSyntax stmt = current as StatementSyntax;
                if (stmt != null)
                {
                    if (LookupPosition.IsInStatementScope(position, stmt))
                    {
                        Binder binder = lambdaBinder.GetBinder(current);
                        if (binder != null)
                        {
                            return(binder);
                        }
                    }
                }
                else if (current.Kind == SyntaxKind.CatchClause)
                {
                    if (LookupPosition.IsInCatchClauseScope(position, (CatchClauseSyntax)current))
                    {
                        Binder binder = lambdaBinder.GetBinder(current);
                        if (binder != null)
                        {
                            return(binder);
                        }
                    }
                }
                else if (current.IsAnonymousFunction())
                {
                    if (LookupPosition.IsInAnonymousFunctionOrQuery(position, current))
                    {
                        Binder binder = lambdaBinder.GetBinder(current);
                        if (binder != null)
                        {
                            return(binder);
                        }
                    }
                }
                else
                {
                    // If this ever breaks, make sure that all callers of
                    // CanHaveAssociatedLocalBinder are in sync.
                    Debug.Assert(!current.CanHaveAssociatedLocalBinder());
                }

                current = current.Parent;
            }

            return(lambdaBinder);
        }
Пример #13
0
        private static Binder ExtendBinderChain(
            CSharpSyntaxNode syntax,
            ImmutableArray<Alias> aliases,
            EEMethodSymbol method,
            Binder binder,
            bool hasDisplayClassThis,
            bool methodNotType)
        {
            var substitutedSourceMethod = GetSubstitutedSourceMethod(method.SubstitutedSourceMethod, hasDisplayClassThis);
            var substitutedSourceType = substitutedSourceMethod.ContainingType;

            var stack = ArrayBuilder<NamedTypeSymbol>.GetInstance();
            for (var type = substitutedSourceType; (object)type != null; type = type.ContainingType)
            {
                stack.Add(type);
            }

            while (stack.Count > 0)
            {
                substitutedSourceType = stack.Pop();

                binder = new InContainerBinder(substitutedSourceType, binder);
                if (substitutedSourceType.Arity > 0)
                {
                    binder = new WithTypeArgumentsBinder(substitutedSourceType.TypeArguments, binder);
                }
            }

            stack.Free();

            if (substitutedSourceMethod.Arity > 0)
            {
                binder = new WithTypeArgumentsBinder(substitutedSourceMethod.TypeArguments, binder);
            }

            if (methodNotType)
            {
                // Method locals and parameters shadow pseudo-variables.
                var typeNameDecoder = new EETypeNameDecoder(binder.Compilation, (PEModuleSymbol)substitutedSourceMethod.ContainingModule);
                binder = new PlaceholderLocalBinder(
                    syntax,
                    aliases,
                    method,
                    typeNameDecoder,
                    binder);
            }

            binder = new EEMethodBinder(method, substitutedSourceMethod, binder);

            if (methodNotType)
            {
                binder = new SimpleLocalScopeBinder(method.LocalsForBinding, binder);
            }

            binder = new ExecutableCodeBinder(syntax, binder.ContainingMemberOrLambda, binder);
            return binder;
        }
Пример #14
0
        private static Binder ExtendBinderChain(
            CSharpSyntaxNode syntax,
            ImmutableArray<Alias> aliases,
            EEMethodSymbol method,
            Binder binder,
            bool hasDisplayClassThis,
            bool methodNotType,
            out ImmutableArray<LocalSymbol> declaredLocals)
        {
            var substitutedSourceMethod = GetSubstitutedSourceMethod(method.SubstitutedSourceMethod, hasDisplayClassThis);
            var substitutedSourceType = substitutedSourceMethod.ContainingType;

            var stack = ArrayBuilder<NamedTypeSymbol>.GetInstance();
            for (var type = substitutedSourceType; (object)type != null; type = type.ContainingType)
            {
                stack.Add(type);
            }

            while (stack.Count > 0)
            {
                substitutedSourceType = stack.Pop();

                binder = new InContainerBinder(substitutedSourceType, binder);
                if (substitutedSourceType.Arity > 0)
                {
                    binder = new WithTypeArgumentsBinder(substitutedSourceType.TypeArguments, binder);
                }
            }

            stack.Free();

            if (substitutedSourceMethod.Arity > 0)
            {
                binder = new WithTypeArgumentsBinder(substitutedSourceMethod.TypeArguments, binder);
            }

            // Method locals and parameters shadow pseudo-variables.
            // That is why we place PlaceholderLocalBinder and ExecutableCodeBinder before EEMethodBinder.
            if (methodNotType)
            {
                var typeNameDecoder = new EETypeNameDecoder(binder.Compilation, (PEModuleSymbol)substitutedSourceMethod.ContainingModule);
                binder = new PlaceholderLocalBinder(
                    syntax,
                    aliases,
                    method,
                    typeNameDecoder,
                    binder);
            }

            Binder originalRootBinder = null;
            SyntaxNode declaredLocalsScopeDesignator = null;
            var executableBinder = new ExecutableCodeBinder(syntax, substitutedSourceMethod, binder,
                                              (rootBinder, declaredLocalsScopeDesignatorOpt) =>
                                              {
                                                  originalRootBinder = rootBinder;
                                                  declaredLocalsScopeDesignator = declaredLocalsScopeDesignatorOpt;
                                                  binder = new EEMethodBinder(method, substitutedSourceMethod, rootBinder);

                                                  if (methodNotType)
                                                  {
                                                      binder = new SimpleLocalScopeBinder(method.LocalsForBinding, binder);
                                                  }

                                                  return binder;
                                              });

            // We just need to trigger the process of building the binder map
            // so that the lambda above was executed.
            executableBinder.GetBinder(syntax);

            Debug.Assert(originalRootBinder != null);
            Debug.Assert(executableBinder.Next != binder);

            if (declaredLocalsScopeDesignator != null)
            {
                declaredLocals = originalRootBinder.GetDeclaredLocalsForScope(declaredLocalsScopeDesignator);
            }
            else
            {
                declaredLocals = ImmutableArray<LocalSymbol>.Empty;
            }

            return binder;
        }