Skip to content

Test plan for "field keyword in properties" #57012

@jcouv

Description

@jcouv

Championed proposal: dotnet/csharplang#8635
Spec: proposals/field-keyword.md

public string PropertyConstraint
{
    get;
    set => field = value ?? throw new ArgumentNullException();
} = "";

Compiler:

  • language version
  • field keyword
    • based on language version
    • as primary_expression only
    • escaped with @
    • this.field, base.field, Qualifier.field
    • in simple property: object P => expr;
    • in property accessors: expression body; block body
    • in indexer accessors
    • in event accessors
    • in nested lambdas and local functions
    • in property initializer
    • in attributes on property, accessor, nested function
    • in nested function signature as default value
    • in nameof()
    • in call to [Conditional]
  • warning when previously binding to other symbol
    • based on language version
    • member of containing type, base type
    • local, in same or nested function
    • parameter in nested function
    • type parameter, in containing type or nested function
  • mixed auto- and manually-implemented accessors (see FieldKeywordTests.ImplicitAccessorBody_*)
    • get, set, init
    • in interface
  • field use
    • static and instance properties on class, struct, ref struct, interface, record*
    • get-only, set-only, init-only (see FieldKeywordTests.AutoPropertyMustHaveGetAccessor_*)
    • field references in multiple properties: each get private backing field
    • auto-implemented properties (including field) must override all accessors (see FieldKeywordTests.Override_*, New_*)
    • in nested function, including static field reference in static function (see FieldKeywordTests.Lambda_*, LocalFunction_*)
    • in attribute arguments (see FieldKeywordTests.Attribute_*)
    • ref returning property (see FieldKeywordTests.RefReturning_*)
    • properties with restricted types (see FieldKeywordTests.RestrictedTypes)
    • properties with by-ref-like types (see FieldKeywordTests.ByRefLikeType_*)
    • @field with and without backing field
    • Color Color
    • passing by reference: (see FieldKeywordTests.PassByReference_*)
      struct S
      {
          readonly object P { set { M1(ref field); M2(in field); } }
          static void M1(ref object o) { }
          static void M2(in object o) { }
      }
  • synthesized backing field
    • backing field emitted when any auto-implemented accessor or field reference
    • backing field marked [CompilerGenerated] (see FieldKeywordTests.Attribute_03)
    • emitted when used in [Conditional] code only (see FieldKeywordTests.Conditional) (see open LDM question)
          object P { set { Debug.Assert(field is null); } }
    • emitted to ref assembly
  • [field:] attributes
    • emitted on synthesized backing field (see FieldKeywordTests.Attribute_03)
    • not emitted on property (see FieldKeywordTests.Attribute_03)
    • error if no auto-implemented accessors and no field references (see FieldKeywordTests.PartialProperty_Attribute_03)
    • [field: Obsolete] (see FieldKeywordTests.ObsoleteAttribute)
  • nameof(field)
    • nameof(field) as invocation
  • property initializer (see FieldKeywordTests.Initializer_*)
    • allowed when any auto-implemented accessor or field reference
    • static and instance properties on class, struct, ref struct, interface
    • written to field directly
  • constructor assignment (see FieldKeywordTests.ConstructorAssignment_*)
    • assigns to setter if available, otherwise getter
    • static and instance properties on class, struct, ref struct, interface
    • assigned in other initializer
    • assigned in nested function
  • flow analysis
    • warning CS0414: The field is assigned but its value is never used
    • warning CS0649: Field is never assigned to, and will always have its default value
    • auto-default initialization of struct backing fields and warnings when property is accessed in constructor (see FieldKeywordTests.DefaultInitialization_*)
      • expect no auto-default inserted when a field initializer is used
      • expect an auto-default when assigning in constructor
  • readonly properties (see FieldKeywordTests.ReadOnly_*)
    • backing field is initonly when type, property, or accessor is readonly
    • error reporting when modifying field in get, set accessors
  • set accessor in readonly context for property using field (see open LDM question) (see FieldKeywordTests.ReadOnly_01)
  • partial properties (see FieldKeywordTests.PartialProperty_*)
    • mix of auto- and manually-implemented accessors
    • static and instance properties on class, struct, ref struct, interface, record*
    • field in accessors
    • initializer on definition or implementation
    • initializer on definition and implementation with same or different values
    • initializer with no field or auto-implementation
    • field references on definition or implementation
    • field references on definition and implementation
    • field references on readonly property or accessor with same or different modifiers on parts
    • [field:] attributes concatenated across parts
      • error when the attributes are the same and AllowMultiple=false
    • partial properties where the implementation uses field and one or both parts have field: targeted attribute lists. (See also PartialPropertiesTests.Attributes_Property_BackingField. This issue referenced in source.)
    • Check warning WRN_SequentialOnPartialClass is produced when needed (see also comment)
    • comment from partial properties
    • comment from partial properties
  • nullability (initial implementation) (see FieldKeywordTests.Nullability_*) Implement nullable analysis for field keyword #75244
  • SemanticModel
  • struct fulfills unmanaged constraint and managed type rules (see pointer types) depending on synthesized fields
  • ref safety:
    struct S
    {
        [UnscopedRef]
        Span<int> Prop1 => M(ref field); // should not error
    
        // Should error
        Span<int> Prop2 => M(ref field); // should error
      
        static Span<int> M(ref Span<int> span) => default;
    }
  • public API review: [API proposal] Syntax changes for field keyword #74937
  • update compiler test plan

Productivity:

Metadata

Metadata

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions