/// <summary> /// In regular C#, all field initializers are assignments to fields and the assigned expressions /// may not reference instance members. /// </summary> internal static void BindRegularCSharpFieldInitializers( CSharpCompilation compilation, ImmutableArray <ImmutableArray <FieldOrPropertyInitializer> > initializers, ArrayBuilder <BoundInitializer> boundInitializers, BindingDiagnosticBag diagnostics, out ImportChain?firstDebugImports) { firstDebugImports = null; foreach (ImmutableArray <FieldOrPropertyInitializer> siblingInitializers in initializers) { // All sibling initializers share the same parent node and tree so we can reuse the binder // factory across siblings. Unfortunately, we cannot reuse the binder itself, because // individual fields might have their own binders (e.g. because of being declared unsafe). BinderFactory?binderFactory = null; foreach (FieldOrPropertyInitializer initializer in siblingInitializers) { FieldSymbol fieldSymbol = initializer.FieldOpt; Debug.Assert((object)fieldSymbol != null); // A constant field of type decimal needs a field initializer, so // check if it is a metadata constant, not just a constant to exclude // decimals. Other constants do not need field initializers. if (!fieldSymbol.IsMetadataConstant) { //Can't assert that this is a regular C# compilation, because we could be in a nested type of a script class. SyntaxReference syntaxRef = initializer.Syntax; switch (syntaxRef.GetSyntax()) { case EqualsValueClauseSyntax initializerNode: if (binderFactory == null) { binderFactory = compilation.GetBinderFactory(syntaxRef.SyntaxTree); } Binder parentBinder = binderFactory.GetBinder(initializerNode); if (firstDebugImports == null) { firstDebugImports = parentBinder.ImportChain; } parentBinder = parentBinder.GetFieldInitializerBinder(fieldSymbol); BoundFieldEqualsValue boundInitializer = BindFieldInitializer(parentBinder, fieldSymbol, initializerNode, diagnostics); if (!boundInitializer.Value.HasAnyErrors) { var field = boundInitializer.Field; if (field.Type.IsRefLikeType) { BoundExpression value = parentBinder.ValidateEscape(boundInitializer.Value, ExternalScope, isByRef: false, diagnostics); boundInitializer = boundInitializer.Update(field, boundInitializer.Locals, value); } } boundInitializers.Add(boundInitializer); break; case ParameterSyntax parameterSyntax: // Initializer for a generated property based on record parameters if (firstDebugImports == null) { if (binderFactory == null) { binderFactory = compilation.GetBinderFactory(syntaxRef.SyntaxTree); } firstDebugImports = binderFactory.GetBinder(parameterSyntax).ImportChain; } boundInitializers.Add(new BoundFieldEqualsValue(parameterSyntax, fieldSymbol, ImmutableArray <LocalSymbol> .Empty, new BoundParameter(parameterSyntax, ((SynthesizedRecordPropertySymbol)fieldSymbol.AssociatedSymbol).BackingParameter).MakeCompilerGenerated())); break; default: throw ExceptionUtilities.Unreachable; } } } } }