Ejemplo n.º 1
0
        internal sealed override TypeSymbolWithAnnotations GetFieldType(ConsList <FieldSymbol> fieldsBeingBound)
        {
            Debug.Assert(fieldsBeingBound != null);

            if (!_lazyType.IsNull)
            {
                return(_lazyType.ToType());
            }

            var declarator  = VariableDeclarationNode;
            var fieldSyntax = GetFieldDeclaration(declarator);
            var typeSyntax  = fieldSyntax.Declaration.Type;

            var compilation = this.DeclaringCompilation;

            var diagnostics = DiagnosticBag.GetInstance();
            TypeSymbolWithAnnotations type = default;

            // When we have multiple declarators, we report the type diagnostics on only the first.
            DiagnosticBag diagnosticsForFirstDeclarator = DiagnosticBag.GetInstance();

            Symbol associatedPropertyOrEvent = this.AssociatedSymbol;

            if ((object)associatedPropertyOrEvent != null && associatedPropertyOrEvent.Kind == SymbolKind.Event)
            {
                EventSymbol @event = (EventSymbol)associatedPropertyOrEvent;
                if (@event.IsWindowsRuntimeEvent)
                {
                    NamedTypeSymbol tokenTableType = this.DeclaringCompilation.GetWellKnownType(WellKnownType.core_runtime_WindowsRuntime_EventRegistrationTokenTable_T);
                    Binder.ReportUseSiteDiagnostics(tokenTableType, diagnosticsForFirstDeclarator, this.ErrorLocation);

                    // CONSIDER: Do we want to guard against the possibility that someone has created their own EventRegistrationTokenTable<T>
                    // type that has additional generic constraints?
                    type = TypeSymbolWithAnnotations.Create(tokenTableType.Construct(ImmutableArray.Create(@event.Type)));
                }
                else
                {
                    type = @event.Type;
                }
            }
            else
            {
                var binderFactory = compilation.GetBinderFactory(SyntaxTree);

                var binder = binderFactory.GetBinder(declarator);

                binder = binder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this);

                if (!ContainingType.IsScriptClass)
                {
                    type = binder.BindType(typeSyntax, diagnosticsForFirstDeclarator);
                }
                else if (typeSyntax == null)
                {
                    if (this.IsConst)
                    {
                        diagnosticsForFirstDeclarator.Add(ErrorCode.ERR_ImplicitlyTypedVariableCannotBeConst, typeSyntax.Location);
                    }

                    if (fieldsBeingBound.ContainsReference(this))
                    {
                        diagnostics.Add(ErrorCode.ERR_RecursivelyTypedVariable, this.ErrorLocation, this);
                        type = default;
                    }
                    else if (this.IsConst && this.ContainingType.IsScriptClass)
                    {
                        // For const var in script, we won't try to bind the initializer (case below), as it can lead to an unbound recursion
                        type = default;
                    }
                    else
                    {
                        fieldsBeingBound = new ConsList <FieldSymbol>(this, fieldsBeingBound);

                        var initializerBinder = new ImplicitlyTypedFieldBinder(binder, fieldsBeingBound);
                        var initializerOpt    = initializerBinder.BindInferredVariableInitializer(diagnostics, RefKind.None, (EqualsValueClauseSyntax)declarator.Initializer, declarator);

                        if (initializerOpt != null)
                        {
                            if ((object)initializerOpt.Type != null && !initializerOpt.Type.IsErrorType())
                            {
                                type = TypeSymbolWithAnnotations.Create(initializerOpt.Type);
                            }

                            _lazyFieldTypeInferred = 1;
                        }
                    }

                    if (type.IsNull)
                    {
                        type = TypeSymbolWithAnnotations.Create(binder.CreateErrorType("var"));
                    }
                }
                else
                {
                    type = binder.BindType(typeSyntax, diagnostics);
                }

                if (IsFixedSizeBuffer)
                {
                    type = TypeSymbolWithAnnotations.Create(new PointerTypeSymbol(type));

                    if (ContainingType.TypeKind != TypeKind.Struct)
                    {
                        diagnostics.Add(ErrorCode.ERR_FixedNotInStruct, ErrorLocation);
                    }

                    var elementType = ((PointerTypeSymbol)type.TypeSymbol).PointedAtType.TypeSymbol;
                    int elementSize = elementType.FixedBufferElementSizeInBytes();
                    if (elementSize == 0)
                    {
                        var loc = typeSyntax.Location;
                        diagnostics.Add(ErrorCode.ERR_IllegalFixedType, loc);
                    }

                    if (!binder.InUnsafeRegion)
                    {
                        diagnosticsForFirstDeclarator.Add(ErrorCode.ERR_UnsafeNeeded, declarator.Location);
                    }
                }
            }

            // update the lazyType only if it contains value last seen by the current thread:
            if (_lazyType.InterlockedInitialize(type.WithModifiers(this.RequiredCustomModifiers)))
            {
                TypeChecks(type.TypeSymbol, diagnostics);

                // CONSIDER: SourceEventFieldSymbol would like to suppress these diagnostics.
                compilation.DeclarationDiagnostics.AddRange(diagnostics);
                compilation.DeclarationDiagnostics.AddRange(diagnosticsForFirstDeclarator);

                state.NotePartComplete(CompletionPart.Type);
            }

            diagnostics.Free();
            diagnosticsForFirstDeclarator.Free();
            return(_lazyType.ToType());
        }