예제 #1
0
 internal void MakeIterator()
 {
     if (_iteratorInfo == null)
     {
         _iteratorInfo = IteratorInfo.Empty;
     }
 }
예제 #2
0
 internal void MakeIterator()
 {
     if (this.iteratorInfo == null)
     {
         this.iteratorInfo = IteratorInfo.Empty;
     }
 }
예제 #3
0
        internal override TypeSymbol GetIteratorElementType(YieldStatementSyntax node, DiagnosticBag diagnostics)
        {
            RefKind    refKind    = _methodSymbol.RefKind;
            TypeSymbol returnType = _methodSymbol.ReturnType.TypeSymbol;

            if (!this.IsDirectlyInIterator)
            {
                // This should only happen when speculating, but we don't have a good way to assert that since the
                // original binder isn't available here.
                // If we're speculating about a yield statement inside a non-iterator method, we'll try to be nice
                // and deduce an iterator element type from the return type.  If we didn't do this, the
                // TypeInfo.ConvertedType of the yield statement would always be an error type.  However, we will
                // not mutate any state (i.e. we won't store the result).
                return(GetIteratorElementTypeFromReturnType(refKind, returnType, node, diagnostics).elementType ?? CreateErrorType());
            }

            if (_iteratorInfo == IteratorInfo.Empty)
            {
                DiagnosticBag elementTypeDiagnostics = DiagnosticBag.GetInstance();

                (TypeSymbol elementType, bool asyncInterface) = GetIteratorElementTypeFromReturnType(refKind, returnType, node, elementTypeDiagnostics);

                Location errorLocation = _methodSymbol.Locations[0];
                if ((object)elementType == null)
                {
                    if (refKind != RefKind.None)
                    {
                        Error(elementTypeDiagnostics, ErrorCode.ERR_BadIteratorReturnRef, errorLocation, _methodSymbol);
                    }
                    else if (!returnType.IsErrorType())
                    {
                        Error(elementTypeDiagnostics, ErrorCode.ERR_BadIteratorReturn, errorLocation, _methodSymbol, returnType);
                    }
                    elementType = CreateErrorType();
                }
                else if (asyncInterface && !_methodSymbol.IsAsync)
                {
                    Error(elementTypeDiagnostics, ErrorCode.ERR_IteratorMustBeAsync, errorLocation, _methodSymbol, returnType);
                }

                var info = new IteratorInfo(elementType, elementTypeDiagnostics.ToReadOnlyAndFree());

                Interlocked.CompareExchange(ref _iteratorInfo, info, IteratorInfo.Empty);
            }

            if (node == null)
            {
                // node==null indicates this we are being called from the top-level of processing of a method. We report
                // the diagnostic, if any, at that time to ensure it is reported exactly once.
                diagnostics.AddRange(_iteratorInfo.ElementTypeDiagnostics);
            }

            return(_iteratorInfo.ElementType);
        }
예제 #4
0
 internal void MakeIterator()
 {
     if (this.iteratorInfo == null)
     {
         this.iteratorInfo = IteratorInfo.Empty;
     }
 }
예제 #5
0
        internal override TypeSymbol GetIteratorElementType(YieldStatementSyntax node, DiagnosticBag diagnostics)
        {
            TypeSymbol returnType = this.Owner.ReturnType;

            if (!this.IsDirectlyInIterator)
            {
                // This should only happen when speculating, but we don't have a good way to assert that since the
                // original binder isn't available here.
                // If we're speculating about a yield statement inside a non-iterator method, we'll try to be nice
                // and deduce an iterator element type from the return type.  If we didn't do this, the 
                // TypeInfo.ConvertedType of the yield statement would always be an error type.  However, we will 
                // not mutate any state (i.e. we won't store the result).
                return GetIteratorElementTypeFromReturnType(returnType, node, diagnostics) ?? CreateErrorType();
            }

            if (this.iteratorInfo == IteratorInfo.Empty)
            {
                TypeSymbol elementType = null;
                DiagnosticBag elementTypeDiagnostics = DiagnosticBag.GetInstance();

                elementType = GetIteratorElementTypeFromReturnType(returnType, node, elementTypeDiagnostics);

                if ((object)elementType == null)
                {
                    Error(elementTypeDiagnostics, ErrorCode.ERR_BadIteratorReturn, this.Owner.Locations[0], this.Owner, returnType);
                    elementType = CreateErrorType();
                }

                var info = new IteratorInfo(elementType, elementTypeDiagnostics.ToReadOnlyAndFree());

                Interlocked.CompareExchange(ref this.iteratorInfo, info, IteratorInfo.Empty);
            }

            if (node == null)
            {
                // node==null indicates this we are being called from the top-level of processing of a method. We report
                // the diagnostic, if any, at that time to ensure it is reported exactly once.
                diagnostics.AddRange(this.iteratorInfo.ElementTypeDiagnostics);
            }

            return this.iteratorInfo.ElementType;
        }