[cfe] Unify getter/setter/field references

This unifies the handling of getter/setter/field references into one object. The references for internal parts of the late lowering are removed. These are not need because the member are never accessed from outside the library and all uses are therefore created together with the reference objects.

Change-Id: I9a18d9f18fa379ee73a74ebadebd473dcb1649aa
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/426800
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/lib/src/fragment/enum_element.dart b/pkg/front_end/lib/src/fragment/enum_element.dart
index ac36817..0b045d2 100644
--- a/pkg/front_end/lib/src/fragment/enum_element.dart
+++ b/pkg/front_end/lib/src/fragment/enum_element.dart
@@ -353,8 +353,11 @@
   }
 
   @override
-  void buildFieldOutlineNode(SourceLibraryBuilder libraryBuilder,
-      NameScheme nameScheme, BuildNodesCallback f, FieldReference references,
+  void buildFieldOutlineNode(
+      SourceLibraryBuilder libraryBuilder,
+      NameScheme nameScheme,
+      BuildNodesCallback f,
+      PropertyReferences references,
       {required List<TypeParameter>? classTypeParameters}) {
     _field = new Field.immutable(dummyName,
         type: _type,
@@ -363,7 +366,7 @@
         isStatic: true,
         fileUri: fileUri,
         fieldReference: references.fieldReference,
-        getterReference: references.fieldGetterReference,
+        getterReference: references.getterReference,
         isEnumElement: true)
       ..fileOffset = nameOffset
       ..fileEndOffset = nameOffset;
diff --git a/pkg/front_end/lib/src/fragment/field/declaration.dart b/pkg/front_end/lib/src/fragment/field/declaration.dart
index d630b33..4765bad 100644
--- a/pkg/front_end/lib/src/fragment/field/declaration.dart
+++ b/pkg/front_end/lib/src/fragment/field/declaration.dart
@@ -47,8 +47,11 @@
 
   /// Builds the core AST structures for this field declaration as needed for
   /// the outline.
-  void buildFieldOutlineNode(SourceLibraryBuilder libraryBuilder,
-      NameScheme nameScheme, BuildNodesCallback f, FieldReference references,
+  void buildFieldOutlineNode(
+      SourceLibraryBuilder libraryBuilder,
+      NameScheme nameScheme,
+      BuildNodesCallback f,
+      PropertyReferences references,
       {required List<TypeParameter>? classTypeParameters});
 
   void buildFieldOutlineExpressions(
@@ -352,8 +355,11 @@
   }
 
   @override
-  void buildFieldOutlineNode(SourceLibraryBuilder libraryBuilder,
-      NameScheme nameScheme, BuildNodesCallback f, FieldReference references,
+  void buildFieldOutlineNode(
+      SourceLibraryBuilder libraryBuilder,
+      NameScheme nameScheme,
+      BuildNodesCallback f,
+      PropertyReferences references,
       {required List<TypeParameter>? classTypeParameters}) {
     _encoding.buildOutlineNode(libraryBuilder, nameScheme, references,
         isAbstractOrExternal:
diff --git a/pkg/front_end/lib/src/fragment/field/encoding.dart b/pkg/front_end/lib/src/fragment/field/encoding.dart
index aa5545a..314b104 100644
--- a/pkg/front_end/lib/src/fragment/field/encoding.dart
+++ b/pkg/front_end/lib/src/fragment/field/encoding.dart
@@ -15,7 +15,7 @@
   /// members should be without body. The member bodies are created through
   /// [createBodies].
   void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
-      NameScheme nameScheme, FieldReference references,
+      NameScheme nameScheme, PropertyReferences references,
       {required bool isAbstractOrExternal,
       required List<TypeParameter>? classTypeParameters});
 
@@ -136,7 +136,7 @@
 
   @override
   void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
-      NameScheme nameScheme, FieldReference references,
+      NameScheme nameScheme, PropertyReferences references,
       {required bool isAbstractOrExternal,
       required List<TypeParameter>? classTypeParameters}) {
     bool isImmutable = _fragment.modifiers.isLate
@@ -150,7 +150,7 @@
             isLate: _fragment.modifiers.isLate,
             fileUri: _fragment.fileUri,
             fieldReference: references.fieldReference,
-            getterReference: references.fieldGetterReference,
+            getterReference: references.getterReference,
             isEnumElement: isEnumElement)
         : new Field.mutable(dummyName,
             type: _type,
@@ -158,8 +158,8 @@
             isLate: _fragment.modifiers.isLate,
             fileUri: _fragment.fileUri,
             fieldReference: references.fieldReference,
-            getterReference: references.fieldGetterReference,
-            setterReference: references.fieldSetterReference);
+            getterReference: references.getterReference,
+            setterReference: references.setterReference);
     nameScheme
         .getFieldMemberName(FieldNameType.Field, _fragment.name,
             isSynthesized: false)
@@ -517,14 +517,11 @@
 
   @override
   void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
-      NameScheme nameScheme, FieldReference references,
+      NameScheme nameScheme, PropertyReferences references,
       {required bool isAbstractOrExternal,
       required List<TypeParameter>? classTypeParameters}) {
     _field = new Field.mutable(dummyName,
-        fileUri: _fragment.fileUri,
-        fieldReference: references.fieldReference,
-        getterReference: references.fieldGetterReference,
-        setterReference: references.fieldSetterReference)
+        fileUri: _fragment.fileUri, fieldReference: references.fieldReference)
       ..fileOffset = _fragment.nameOffset
       ..fileEndOffset = _fragment.endOffset
       ..isInternalImplementation = true;
@@ -539,14 +536,11 @@
         break;
       case late_lowering.IsSetStrategy.forceUseIsSetField:
       case late_lowering.IsSetStrategy.useIsSetFieldOrNull:
-        _lateIsSetField = new Field.mutable(dummyName,
-            fileUri: _fragment.fileUri,
-            fieldReference: references.lateIsSetFieldReference,
-            getterReference: references.lateIsSetGetterReference,
-            setterReference: references.lateIsSetSetterReference)
-          ..fileOffset = _fragment.nameOffset
-          ..fileEndOffset = _fragment.endOffset
-          ..isInternalImplementation = true;
+        _lateIsSetField =
+            new Field.mutable(dummyName, fileUri: _fragment.fileUri)
+              ..fileOffset = _fragment.nameOffset
+              ..fileEndOffset = _fragment.endOffset
+              ..isInternalImplementation = true;
         nameScheme
             .getFieldMemberName(FieldNameType.IsSetField, _fragment.name,
                 isSynthesized: true)
@@ -560,7 +554,7 @@
           ..fileOffset = _fragment.nameOffset
           ..fileEndOffset = _fragment.endOffset,
         fileUri: _fragment.fileUri,
-        reference: references.lateGetterReference)
+        reference: references.getterReference)
       ..fileOffset = _fragment.nameOffset
       ..fileEndOffset = _fragment.endOffset;
     nameScheme
@@ -568,7 +562,7 @@
             isSynthesized: true)
         .attachMember(_lateGetter!);
     _lateSetter = _createSetter(
-        _fragment.fileUri, _fragment.nameOffset, references.lateSetterReference,
+        _fragment.fileUri, _fragment.nameOffset, references.setterReference,
         isCovariantByDeclaration: _fragment.modifiers.isCovariant);
     if (_lateSetter != null) {
       nameScheme
@@ -944,7 +938,7 @@
 
   @override
   void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
-      NameScheme nameScheme, FieldReference references,
+      NameScheme nameScheme, PropertyReferences references,
       {required bool isAbstractOrExternal,
       required List<TypeParameter>? classTypeParameters}) {
     if (_isExtensionInstanceMember || _isExtensionTypeInstanceMember) {
@@ -957,7 +951,7 @@
               ..isLowered = true
           ]),
           fileUri: _fragment.fileUri,
-          reference: references.fieldGetterReference)
+          reference: references.getterReference)
         ..fileOffset = _fragment.nameOffset
         ..fileEndOffset = _fragment.endOffset;
       nameScheme
@@ -982,7 +976,7 @@
               ..fileOffset = _fragment.nameOffset
               ..fileEndOffset = _fragment.endOffset,
             fileUri: _fragment.fileUri,
-            reference: references.fieldSetterReference)
+            reference: references.setterReference)
           ..fileOffset = _fragment.nameOffset
           ..fileEndOffset = _fragment.endOffset;
         nameScheme
@@ -992,8 +986,7 @@
     } else {
       _getter = new Procedure(
           dummyName, ProcedureKind.Getter, new FunctionNode(null),
-          fileUri: _fragment.fileUri,
-          reference: references.fieldGetterReference)
+          fileUri: _fragment.fileUri, reference: references.getterReference)
         ..fileOffset = _fragment.nameOffset
         ..fileEndOffset = _fragment.endOffset;
       nameScheme
@@ -1013,7 +1006,7 @@
               ..fileOffset = _fragment.nameOffset
               ..fileEndOffset = _fragment.endOffset,
             fileUri: _fragment.fileUri,
-            reference: references.fieldSetterReference)
+            reference: references.setterReference)
           ..fileOffset = _fragment.nameOffset
           ..fileEndOffset = _fragment.endOffset;
         nameScheme
@@ -1211,12 +1204,12 @@
 
   @override
   void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
-      NameScheme nameScheme, FieldReference references,
+      NameScheme nameScheme, PropertyReferences references,
       {required bool isAbstractOrExternal,
       required List<TypeParameter>? classTypeParameters}) {
     _getter = new Procedure(
         dummyName, ProcedureKind.Getter, new FunctionNode(null),
-        fileUri: _fragment.fileUri, reference: references.fieldGetterReference)
+        fileUri: _fragment.fileUri, reference: references.getterReference)
       ..stubKind = ProcedureStubKind.RepresentationField
       ..fileOffset = _fragment.nameOffset
       ..fileEndOffset = _fragment.nameOffset;
diff --git a/pkg/front_end/lib/src/fragment/primary_constructor_field.dart b/pkg/front_end/lib/src/fragment/primary_constructor_field.dart
index 5aa5b32..a4e7e20 100644
--- a/pkg/front_end/lib/src/fragment/primary_constructor_field.dart
+++ b/pkg/front_end/lib/src/fragment/primary_constructor_field.dart
@@ -46,6 +46,7 @@
     _builder = value;
   }
 
+  // Coverage-ignore(suite): Not run.
   PrimaryConstructorFieldDeclaration get declaration {
     assert(
         _declaration != null, "Declaration has not been computed for $this.");
@@ -107,9 +108,11 @@
   shared.Expression? get initializerExpression => null;
 
   @override
+  // Coverage-ignore(suite): Not run.
   bool get isConst => false;
 
   @override
+  // Coverage-ignore(suite): Not run.
   bool get isEnumElement => false;
 
   @override
@@ -122,6 +125,7 @@
   bool get isLate => false;
 
   @override
+  // Coverage-ignore(suite): Not run.
   bool get isStatic => false;
 
   @override
@@ -148,6 +152,7 @@
     _encoding.type = value;
   }
 
+  // Coverage-ignore(suite): Not run.
   /// Builds the body of this field using [initializer] as the initializer
   /// expression.
   void buildBody(CoreTypes coreTypes, Expression? initializer) {
@@ -164,6 +169,7 @@
   }
 
   @override
+  // Coverage-ignore(suite): Not run.
   void buildFieldInitializer(InferenceHelper helper, TypeInferrer typeInferrer,
       CoreTypes coreTypes, Expression? initializer) {
     if (initializer != null) {
@@ -179,6 +185,7 @@
   }
 
   @override
+  // Coverage-ignore(suite): Not run.
   void buildImplicitDefaultValue() {
     _encoding.buildImplicitDefaultValue();
   }
@@ -216,8 +223,11 @@
   }
 
   @override
-  void buildFieldOutlineNode(SourceLibraryBuilder libraryBuilder,
-      NameScheme nameScheme, BuildNodesCallback f, FieldReference references,
+  void buildFieldOutlineNode(
+      SourceLibraryBuilder libraryBuilder,
+      NameScheme nameScheme,
+      BuildNodesCallback f,
+      PropertyReferences references,
       {required List<TypeParameter>? classTypeParameters}) {
     _encoding.buildOutlineNode(libraryBuilder, nameScheme, references,
         isAbstractOrExternal: false, classTypeParameters: classTypeParameters);
@@ -243,6 +253,7 @@
   }
 
   @override
+  // Coverage-ignore(suite): Not run.
   void checkFieldVariance(
       SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
     sourceClassBuilder.checkVarianceInField(typeEnvironment,
@@ -287,6 +298,7 @@
 
     type.registerInferredTypeListener(this);
     if (type is InferableTypeBuilder) {
+      // Coverage-ignore-block(suite): Not run.
       // A field with no type and initializer or an instance field without
       // type and initializer need to have the type inferred.
       _encoding.type = new InferredType(
@@ -304,6 +316,7 @@
   }
 
   @override
+  // Coverage-ignore(suite): Not run.
   void ensureTypes(
       ClassMembersBuilder membersBuilder,
       Set<ClassMember>? getterOverrideDependencies,
@@ -320,17 +333,18 @@
           nameLength: _fragment.name.length,
           isAssignable: hasSetter);
     } else {
-      // Coverage-ignore-block(suite): Not run.
       type.build(builder.libraryBuilder, TypeUse.fieldType,
           hierarchy: membersBuilder.hierarchyBuilder);
     }
   }
 
   @override
+  // Coverage-ignore(suite): Not run.
   void registerSuperCall() {
     _encoding.registerSuperCall();
   }
 
+  // Coverage-ignore(suite): Not run.
   DartType _computeInferredType(
       ClassHierarchyBase classHierarchy, Token? token) {
     DartType? inferredType;
@@ -344,16 +358,9 @@
                   declarationBuilder.cls, libraryBuilder.library.nonNullable)
           : null;
       LookupScope scope = _fragment.enclosingScope;
-      TypeInferrer typeInferrer =
-          libraryBuilder.loader.typeInferenceEngine.createTopLevelTypeInferrer(
-              fileUri,
-              enclosingClassThisType,
-              libraryBuilder,
-              scope,
-              builder
-                  .dataForTesting
-                  // Coverage-ignore(suite): Not run.
-                  ?.inferenceData);
+      TypeInferrer typeInferrer = libraryBuilder.loader.typeInferenceEngine
+          .createTopLevelTypeInferrer(fileUri, enclosingClassThisType,
+              libraryBuilder, scope, builder.dataForTesting?.inferenceData);
       BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
       BodyBuilder bodyBuilder = libraryBuilder.loader.createBodyBuilderForField(
           libraryBuilder, bodyBuilderContext, scope, typeInferrer, fileUri);
@@ -371,6 +378,7 @@
   }
 
   @override
+  // Coverage-ignore(suite): Not run.
   void setCovariantByClassInternal() {
     _encoding.setCovariantByClass();
   }
@@ -398,6 +406,7 @@
       TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder) {}
 
   @override
+  // Coverage-ignore(suite): Not run.
   void checkGetterVariance(
       SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {}
 
@@ -414,6 +423,7 @@
       List<NominalParameterBuilder> unboundNominalParameters) {}
 
   @override
+  // Coverage-ignore(suite): Not run.
   void ensureGetterTypes(
       {required SourceLibraryBuilder libraryBuilder,
       required DeclarationBuilder? declarationBuilder,
@@ -421,6 +431,7 @@
       required Set<ClassMember>? getterOverrideDependencies}) {}
 
   @override
+  // Coverage-ignore(suite): Not run.
   Iterable<Reference> getExportedGetterReferences(
       PropertyReferences references) {
     return [references.getterReference!];
diff --git a/pkg/front_end/lib/src/source/source_enum_builder.dart b/pkg/front_end/lib/src/source/source_enum_builder.dart
index ecc0d1e9..94f71aa 100644
--- a/pkg/front_end/lib/src/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/source/source_enum_builder.dart
@@ -201,9 +201,9 @@
           new Name("_enumToString", coreLibrary.library));
     }
 
-    FieldReference valuesReferences = new FieldReference(
+    PropertyReferences valuesReferences = new PropertyReferences(
         "values", staticFieldNameScheme, indexedClass,
-        fieldIsLateWithLowering: false, isExternal: false);
+        fieldIsLateWithLowering: false);
 
     Builder? customValuesDeclaration =
         nameSpace.lookupLocalMember("values")?.getable;
@@ -251,7 +251,7 @@
     }
 
     _enumValuesFieldDeclaration =
-        new _EnumValuesFieldDeclaration(this, valuesReferences, listType);
+        new _EnumValuesFieldDeclaration(this, listType);
 
     SourcePropertyBuilder valuesBuilder = new SourcePropertyBuilder.forField(
         fileUri: fileUri,
@@ -599,7 +599,6 @@
   static const String name = "values";
 
   final SourceEnumBuilder _sourceEnumBuilder;
-  final FieldReference fieldReference;
 
   SourcePropertyBuilder? _builder;
 
@@ -609,8 +608,7 @@
 
   final TypeBuilder _typeBuilder;
 
-  _EnumValuesFieldDeclaration(
-      this._sourceEnumBuilder, this.fieldReference, this._typeBuilder);
+  _EnumValuesFieldDeclaration(this._sourceEnumBuilder, this._typeBuilder);
 
   SourcePropertyBuilder get builder {
     assert(_builder != null, "Builder has not been computed for $this.");
@@ -669,8 +667,11 @@
   }
 
   @override
-  void buildFieldOutlineNode(SourceLibraryBuilder libraryBuilder,
-      NameScheme nameScheme, BuildNodesCallback f, FieldReference references,
+  void buildFieldOutlineNode(
+      SourceLibraryBuilder libraryBuilder,
+      NameScheme nameScheme,
+      BuildNodesCallback f,
+      PropertyReferences references,
       {required List<TypeParameter>? classTypeParameters}) {
     fieldType = _typeBuilder.build(libraryBuilder, TypeUse.fieldType);
     _field = new Field.immutable(dummyName,
@@ -680,7 +681,7 @@
         isStatic: true,
         fileUri: builder.fileUri,
         fieldReference: references.fieldReference,
-        getterReference: references.fieldGetterReference,
+        getterReference: references.getterReference,
         isEnumElement: false)
       ..fileOffset = builder.fileOffset
       ..fileEndOffset = builder.fileOffset;
diff --git a/pkg/front_end/lib/src/source/source_property_builder.dart b/pkg/front_end/lib/src/source/source_property_builder.dart
index 10a53db..bb546dd 100644
--- a/pkg/front_end/lib/src/source/source_property_builder.dart
+++ b/pkg/front_end/lib/src/source/source_property_builder.dart
@@ -182,7 +182,7 @@
   @override
   void buildOutlineNodes(BuildNodesCallback f) {
     _introductoryField?.buildFieldOutlineNode(
-        libraryBuilder, _nameScheme, f, _references as FieldReference,
+        libraryBuilder, _nameScheme, f, _references,
         classTypeParameters: classBuilder?.cls.typeParameters);
 
     List<GetterDeclaration>? augmentedGetables = _augmentedGetables;
@@ -883,322 +883,79 @@
 }
 
 abstract class PropertyReferences {
+  Reference? get fieldReference;
   Reference? get getterReference;
   Reference? get setterReference;
+
+  void registerReference(SourceLoader loader, SourcePropertyBuilder builder);
+
+  factory PropertyReferences(
+      String name, NameScheme nameScheme, IndexedContainer? indexedContainer,
+      {required bool fieldIsLateWithLowering}) = _PropertyReferences;
 }
 
-class GetterReference extends PropertyReferences {
+class _PropertyReferences implements PropertyReferences {
+  Reference? _fieldReference;
   Reference? _getterReference;
-
-  GetterReference._(this._getterReference);
-
-  factory GetterReference(
-      String name, NameScheme nameScheme, IndexedContainer? indexedContainer) {
-    Reference? procedureReference;
-    ProcedureKind kind = ProcedureKind.Getter;
-    if (indexedContainer != null) {
-      Name nameToLookup = nameScheme.getProcedureMemberName(kind, name).name;
-      procedureReference = indexedContainer.lookupGetterReference(nameToLookup);
-    }
-    return new GetterReference._(procedureReference);
-  }
-
-  void registerReference(SourceLoader loader, Builder builder) {
-    if (_getterReference != null) {
-      loader.buildersCreatedWithReferences[_getterReference!] = builder;
-    }
-  }
-
-  @override
-  Reference get getterReference => _getterReference ??= new Reference();
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Reference? get setterReference => null;
-}
-
-class SetterReference extends PropertyReferences {
   Reference? _setterReference;
 
-  SetterReference._(this._setterReference);
+  _PropertyReferences._(
+      this._fieldReference, this._getterReference, this._setterReference);
 
-  factory SetterReference(
-      String name, NameScheme nameScheme, IndexedContainer? indexedContainer) {
-    Reference? procedureReference;
-    ProcedureKind kind = ProcedureKind.Setter;
+  factory _PropertyReferences(
+      String name, NameScheme nameScheme, IndexedContainer? indexedContainer,
+      {required bool fieldIsLateWithLowering}) {
+    Reference? getterReference;
+    Reference? setterReference;
+    Reference? fieldReference;
     if (indexedContainer != null) {
-      Name nameToLookup = nameScheme.getProcedureMemberName(kind, name).name;
+      Name getterNameToLookup =
+          nameScheme.getProcedureMemberName(ProcedureKind.Getter, name).name;
+      getterReference =
+          indexedContainer.lookupGetterReference(getterNameToLookup);
+
+      Name setterNameToLookup =
+          nameScheme.getProcedureMemberName(ProcedureKind.Setter, name).name;
       if ((nameScheme.isExtensionMember || nameScheme.isExtensionTypeMember) &&
           nameScheme.isInstanceMember) {
         // Extension (type) instance setters are encoded as methods.
-        procedureReference =
-            indexedContainer.lookupGetterReference(nameToLookup);
+        setterReference =
+            indexedContainer.lookupGetterReference(setterNameToLookup);
       } else {
-        procedureReference =
-            indexedContainer.lookupSetterReference(nameToLookup);
+        setterReference =
+            indexedContainer.lookupSetterReference(setterNameToLookup);
       }
+
+      Name fieldNameToLookup = nameScheme
+          .getFieldMemberName(FieldNameType.Field, name,
+              isSynthesized: fieldIsLateWithLowering)
+          .name;
+      fieldReference = indexedContainer.lookupFieldReference(fieldNameToLookup);
     }
-    return new SetterReference._(procedureReference);
+
+    return new _PropertyReferences._(
+        fieldReference, getterReference, setterReference);
   }
 
-  void registerReference(SourceLoader loader, Builder builder) {
+  @override
+  void registerReference(SourceLoader loader, SourcePropertyBuilder builder) {
+    if (_fieldReference != null) {
+      loader.buildersCreatedWithReferences[_fieldReference!] = builder;
+    }
+    if (_getterReference != null) {
+      loader.buildersCreatedWithReferences[_getterReference!] = builder;
+    }
     if (_setterReference != null) {
       loader.buildersCreatedWithReferences[_setterReference!] = builder;
     }
   }
 
   @override
-  // Coverage-ignore(suite): Not run.
-  Reference? get getterReference => null;
+  Reference get fieldReference => _fieldReference ??= new Reference();
+
+  @override
+  Reference get getterReference => _getterReference ??= new Reference();
 
   @override
   Reference get setterReference => _setterReference ??= new Reference();
 }
-
-abstract class FieldReference extends PropertyReferences {
-  factory FieldReference(
-      String name, NameScheme nameScheme, IndexedContainer? indexedContainer,
-      {required bool fieldIsLateWithLowering, required bool isExternal}) {
-    Reference? fieldReference;
-    Reference? fieldGetterReference;
-    Reference? fieldSetterReference;
-    Reference? lateIsSetFieldReference;
-    Reference? lateIsSetGetterReference;
-    Reference? lateIsSetSetterReference;
-    Reference? lateGetterReference;
-    Reference? lateSetterReference;
-    if (indexedContainer != null) {
-      if ((nameScheme.isExtensionMember || nameScheme.isExtensionTypeMember) &&
-          nameScheme.isInstanceMember &&
-          isExternal) {
-        /// An external extension (type) instance field is special. It is
-        /// treated as an external getter/setter pair and is therefore
-        /// encoded as a pair of top level methods using the extension
-        /// instance member naming convention.
-        fieldGetterReference = indexedContainer.lookupGetterReference(
-            nameScheme.getProcedureMemberName(ProcedureKind.Getter, name).name);
-        fieldSetterReference = indexedContainer.lookupGetterReference(
-            nameScheme.getProcedureMemberName(ProcedureKind.Setter, name).name);
-      } else if (nameScheme.isExtensionTypeMember &&
-          nameScheme.isInstanceMember) {
-        Name nameToLookup = nameScheme
-            .getFieldMemberName(FieldNameType.RepresentationField, name,
-                isSynthesized: true)
-            .name;
-        fieldGetterReference =
-            indexedContainer.lookupGetterReference(nameToLookup);
-      } else {
-        Name nameToLookup = nameScheme
-            .getFieldMemberName(FieldNameType.Field, name,
-                isSynthesized: fieldIsLateWithLowering)
-            .name;
-        fieldReference = indexedContainer.lookupFieldReference(nameToLookup);
-        fieldGetterReference =
-            indexedContainer.lookupGetterReference(nameToLookup);
-        fieldSetterReference =
-            indexedContainer.lookupSetterReference(nameToLookup);
-      }
-
-      if (fieldIsLateWithLowering) {
-        Name lateIsSetName = nameScheme
-            .getFieldMemberName(FieldNameType.IsSetField, name,
-                isSynthesized: fieldIsLateWithLowering)
-            .name;
-        lateIsSetFieldReference =
-            indexedContainer.lookupFieldReference(lateIsSetName);
-        lateIsSetGetterReference =
-            indexedContainer.lookupGetterReference(lateIsSetName);
-        lateIsSetSetterReference =
-            indexedContainer.lookupSetterReference(lateIsSetName);
-        lateGetterReference = indexedContainer.lookupGetterReference(nameScheme
-            .getFieldMemberName(FieldNameType.Getter, name,
-                isSynthesized: fieldIsLateWithLowering)
-            .name);
-        lateSetterReference = indexedContainer.lookupSetterReference(nameScheme
-            .getFieldMemberName(FieldNameType.Setter, name,
-                isSynthesized: fieldIsLateWithLowering)
-            .name);
-      }
-    }
-    if (fieldIsLateWithLowering) {
-      return new _LateFieldLoweringReference._(
-          fieldReference: fieldReference,
-          fieldGetterReference: fieldGetterReference,
-          fieldSetterReference: fieldSetterReference,
-          lateIsSetFieldReference: lateIsSetFieldReference,
-          lateIsSetGetterReference: lateIsSetGetterReference,
-          lateIsSetSetterReference: lateIsSetSetterReference,
-          lateGetterReference: lateGetterReference,
-          lateSetterReference: lateSetterReference);
-    } else {
-      return new _RegularFieldReference._(
-          fieldReference: fieldReference,
-          fieldGetterReference: fieldGetterReference,
-          fieldSetterReference: fieldSetterReference,
-          lateIsSetFieldReference: lateIsSetFieldReference,
-          lateIsSetGetterReference: lateIsSetGetterReference,
-          lateIsSetSetterReference: lateIsSetSetterReference,
-          lateGetterReference: lateGetterReference,
-          lateSetterReference: lateSetterReference);
-    }
-  }
-
-  void registerReference(SourceLoader loader, Builder builder);
-
-  Reference get fieldReference;
-  Reference get fieldGetterReference;
-  Reference get fieldSetterReference;
-  Reference get lateIsSetFieldReference;
-  Reference get lateIsSetGetterReference;
-  Reference get lateIsSetSetterReference;
-  Reference get lateGetterReference;
-  Reference get lateSetterReference;
-}
-
-class _RegularFieldReference implements FieldReference {
-  Reference? _fieldReference;
-  Reference? _fieldGetterReference;
-  Reference? _fieldSetterReference;
-  Reference? _lateIsSetFieldReference;
-  Reference? _lateIsSetGetterReference;
-  Reference? _lateIsSetSetterReference;
-  Reference? _lateGetterReference;
-  Reference? _lateSetterReference;
-
-  _RegularFieldReference._(
-      {required Reference? fieldReference,
-      required Reference? fieldGetterReference,
-      required Reference? fieldSetterReference,
-      required Reference? lateIsSetFieldReference,
-      required Reference? lateIsSetGetterReference,
-      required Reference? lateIsSetSetterReference,
-      required Reference? lateGetterReference,
-      required Reference? lateSetterReference})
-      : _fieldReference = fieldReference,
-        _fieldGetterReference = fieldGetterReference,
-        _fieldSetterReference = fieldSetterReference,
-        _lateIsSetFieldReference = lateIsSetFieldReference,
-        _lateIsSetGetterReference = lateIsSetGetterReference,
-        _lateIsSetSetterReference = lateIsSetSetterReference,
-        _lateGetterReference = lateGetterReference,
-        _lateSetterReference = lateSetterReference;
-
-  @override
-  void registerReference(SourceLoader loader, Builder builder) {
-    if (_fieldGetterReference != null) {
-      loader.buildersCreatedWithReferences[_fieldGetterReference!] = builder;
-    }
-    if (_fieldSetterReference != null) {
-      loader.buildersCreatedWithReferences[_fieldSetterReference!] = builder;
-    }
-  }
-
-  @override
-  Reference get fieldReference => _fieldReference ??= new Reference();
-
-  @override
-  Reference get fieldGetterReference =>
-      _fieldGetterReference ??= new Reference();
-
-  @override
-  Reference get fieldSetterReference =>
-      _fieldSetterReference ??= new Reference();
-
-  @override
-  Reference get lateIsSetFieldReference =>
-      _lateIsSetFieldReference ??= new Reference();
-
-  @override
-  Reference get lateIsSetGetterReference =>
-      _lateIsSetGetterReference ??= new Reference();
-
-  @override
-  Reference get lateIsSetSetterReference =>
-      _lateIsSetSetterReference ??= new Reference();
-
-  @override
-  Reference get lateGetterReference => _lateGetterReference ??= new Reference();
-
-  @override
-  Reference get lateSetterReference => _lateSetterReference ??= new Reference();
-
-  @override
-  Reference? get getterReference => fieldGetterReference;
-
-  @override
-  Reference? get setterReference => fieldSetterReference;
-}
-
-class _LateFieldLoweringReference implements FieldReference {
-  Reference? _fieldReference;
-  Reference? _fieldGetterReference;
-  Reference? _fieldSetterReference;
-  Reference? _lateIsSetFieldReference;
-  Reference? _lateIsSetGetterReference;
-  Reference? _lateIsSetSetterReference;
-  Reference? _lateGetterReference;
-  Reference? _lateSetterReference;
-
-  _LateFieldLoweringReference._(
-      {required Reference? fieldReference,
-      required Reference? fieldGetterReference,
-      required Reference? fieldSetterReference,
-      required Reference? lateIsSetFieldReference,
-      required Reference? lateIsSetGetterReference,
-      required Reference? lateIsSetSetterReference,
-      required Reference? lateGetterReference,
-      required Reference? lateSetterReference})
-      : _fieldReference = fieldReference,
-        _fieldGetterReference = fieldGetterReference,
-        _fieldSetterReference = fieldSetterReference,
-        _lateIsSetFieldReference = lateIsSetFieldReference,
-        _lateIsSetGetterReference = lateIsSetGetterReference,
-        _lateIsSetSetterReference = lateIsSetSetterReference,
-        _lateGetterReference = lateGetterReference,
-        _lateSetterReference = lateSetterReference;
-
-  @override
-  void registerReference(SourceLoader loader, Builder builder) {
-    if (_fieldGetterReference != null) {
-      loader.buildersCreatedWithReferences[_fieldGetterReference!] = builder;
-    }
-    if (_fieldSetterReference != null) {
-      loader.buildersCreatedWithReferences[_fieldSetterReference!] = builder;
-    }
-  }
-
-  @override
-  Reference get fieldReference => _fieldReference ??= new Reference();
-
-  @override
-  Reference get fieldGetterReference =>
-      _fieldGetterReference ??= new Reference();
-
-  @override
-  Reference get fieldSetterReference =>
-      _fieldSetterReference ??= new Reference();
-
-  @override
-  Reference get lateIsSetFieldReference =>
-      _lateIsSetFieldReference ??= new Reference();
-
-  @override
-  Reference get lateIsSetGetterReference =>
-      _lateIsSetGetterReference ??= new Reference();
-
-  @override
-  Reference get lateIsSetSetterReference =>
-      _lateIsSetSetterReference ??= new Reference();
-
-  @override
-  Reference get lateGetterReference => _lateGetterReference ??= new Reference();
-
-  @override
-  Reference get lateSetterReference => _lateSetterReference ??= new Reference();
-
-  @override
-  Reference? get getterReference => lateGetterReference;
-
-  @override
-  Reference? get setterReference => lateSetterReference;
-}
diff --git a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
index 3e4d856..87c3d10 100644
--- a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
+++ b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
@@ -2491,10 +2491,9 @@
           : enclosingLibraryBuilder.libraryName);
   indexedContainer ??= indexedLibrary;
 
-  FieldReference references = new FieldReference(
+  PropertyReferences references = new PropertyReferences(
       name, nameScheme, indexedContainer,
-      fieldIsLateWithLowering: fieldIsLateWithLowering,
-      isExternal: fragment.modifiers.isExternal);
+      fieldIsLateWithLowering: fieldIsLateWithLowering);
 
   RegularFieldDeclaration declaration = new RegularFieldDeclaration(fragment);
   SourcePropertyBuilder propertyBuilder = new SourcePropertyBuilder.forField(
@@ -2552,9 +2551,9 @@
           : enclosingLibraryBuilder.libraryName);
   indexedContainer ??= indexedLibrary;
 
-  FieldReference references = new FieldReference(
+  PropertyReferences references = new PropertyReferences(
       name, nameScheme, indexedContainer,
-      fieldIsLateWithLowering: false, isExternal: false);
+      fieldIsLateWithLowering: false);
 
   PrimaryConstructorFieldDeclaration declaration =
       new PrimaryConstructorFieldDeclaration(fragment);
@@ -2614,8 +2613,9 @@
 
   indexedContainer ??= indexedLibrary;
 
-  GetterReference references =
-      new GetterReference(name, nameScheme, indexedContainer);
+  PropertyReferences references = new PropertyReferences(
+      name, nameScheme, indexedContainer,
+      fieldIsLateWithLowering: false);
 
   GetterDeclaration declaration = new GetterDeclarationImpl(fragment);
   List<GetterDeclaration> augmentationDeclarations = [];
@@ -2706,8 +2706,9 @@
 
   indexedContainer ??= indexedLibrary;
 
-  SetterReference references =
-      new SetterReference(name, nameScheme, indexedContainer);
+  PropertyReferences references = new PropertyReferences(
+      name, nameScheme, indexedContainer,
+      fieldIsLateWithLowering: false);
 
   SetterDeclaration declaration = new SetterDeclarationImpl(fragment);
   List<SetterDeclaration> augmentationDeclarations = [];
@@ -3313,9 +3314,9 @@
       libraryName: indexedLibrary != null
           ? new LibraryName(indexedLibrary.library.reference)
           : enclosingLibraryBuilder.libraryName);
-  FieldReference references = new FieldReference(
+  PropertyReferences references = new PropertyReferences(
       fragment.name, nameScheme, indexedContainer,
-      fieldIsLateWithLowering: false, isExternal: false);
+      fieldIsLateWithLowering: false);
   EnumElementDeclaration enumElementDeclaration =
       new EnumElementDeclaration(fragment);
   SourcePropertyBuilder propertyBuilder = new SourcePropertyBuilder.forField(
diff --git a/pkg/front_end/test/coverage_suite_expected.dart b/pkg/front_end/test/coverage_suite_expected.dart
index 6764c11..bbf5047 100644
--- a/pkg/front_end/test/coverage_suite_expected.dart
+++ b/pkg/front_end/test/coverage_suite_expected.dart
@@ -560,7 +560,7 @@
   ),
   // 100.0%.
   "package:front_end/src/fragment/field/body_builder_context.dart": (
-    hitCount: 30,
+    hitCount: 18,
     missCount: 0,
   ),
   // 100.0%.
@@ -570,12 +570,12 @@
   ),
   // 100.0%.
   "package:front_end/src/fragment/field/declaration.dart": (
-    hitCount: 427,
+    hitCount: 431,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/fragment/field/encoding.dart": (
-    hitCount: 963,
+    hitCount: 955,
     missCount: 0,
   ),
   // 100.0%.
@@ -634,6 +634,11 @@
     missCount: 0,
   ),
   // 100.0%.
+  "package:front_end/src/fragment/primary_constructor_field.dart": (
+    hitCount: 120,
+    missCount: 0,
+  ),
+  // 100.0%.
   "package:front_end/src/fragment/setter.dart": (
     hitCount: 48,
     missCount: 0,
@@ -675,7 +680,7 @@
   ),
   // 100.0%.
   "package:front_end/src/kernel/body_builder.dart": (
-    hitCount: 7215,
+    hitCount: 7220,
     missCount: 0,
   ),
   // 100.0%.
@@ -785,7 +790,7 @@
   ),
   // 100.0%.
   "package:front_end/src/kernel/hierarchy/members_node.dart": (
-    hitCount: 1121,
+    hitCount: 1123,
     missCount: 0,
   ),
   // 100.0%.
@@ -930,7 +935,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_builder_factory.dart": (
-    hitCount: 1156,
+    hitCount: 1165,
     missCount: 0,
   ),
   // 100.0%.
@@ -940,7 +945,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_class_builder.dart": (
-    hitCount: 1434,
+    hitCount: 1435,
     missCount: 0,
   ),
   // 100.0%.
@@ -1001,7 +1006,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_property_builder.dart": (
-    hitCount: 635,
+    hitCount: 532,
     missCount: 0,
   ),
   // 100.0%.
@@ -1021,7 +1026,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/type_parameter_scope_builder.dart": (
-    hitCount: 1807,
+    hitCount: 1842,
     missCount: 0,
   ),
   // 100.0%.
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 791fb84..c4fe165 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -137,7 +137,6 @@
 
 dart2js/flutter_issue94561/main: SemiFuzzFailure
 dart2js/flutter_issue94561/main.no_link: SemiFuzzFailure
-static_field_lowering/opt_in: SemiFuzzFailure
 
 macros/augment_concrete: SemiFuzzFailure # https://github.com/dart-lang/sdk/issues/49414
 macros/duplicate_augment: semiFuzzFailureOnForceRebuildBodies