| RFC-0036: Update to struct declarations ||
|---|---|
| Status | Rejected |
| Areas | - FIDL |
| Description | To better convey ABI implications of re-ordering and renaming fields, we propose a syntactic change to introduce ordinals for structs fields, with similar syntactic rules then those for tables. |
| Authors | - [pascallouis@google.com](https://fuchsia-review.googlesource.com/q/owner:pascallouis@google.com) |
| Date submitted (year-month-day) | 2019-03-07 |
| Date reviewed (year-month-day) | 2019-03-14 |

[Edit this RFC](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/contribute/governance/rfcs/0036_update_struct_declarations.md)
[Edit RFC metadata](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/contribute/governance/rfcs/_rfcs.yaml&searchAndJump=-+name:+'RFC-0036')

> [!NOTE]
> **Note:** Formerly known as [FTP](https://fuchsia.dev/fuchsia-src/contribute/governance/deprecated-ftp-process.md)-036.

## Rejection rationale

### Pros

- Confusion around name being important for ABI or not exists: xunion, struct, and protocols all look similar, but have different rules.

### Cons

- However, all concerned felt this was far outweighed by the
  confusion that introducing ordinals on structs would add,
  especially when compared to protobufs.

- There are other efforts addressing "does this change ABI", namely:

  - DIFL
  - API diffing, e.g. signature for libraries
- Name matters for text formats (JSON, FIDLText, etc.), and when messages
  are used in this context, name changes cannot occur.

## Summary

To better convey ABI implications of re-ordering and renaming fields, we
propose a **syntactic change to introduce ordinals for structs fields**,
with similar syntactic rules then those for tables.

## Motivation

Focusing solely on whether members can be safely renamed or re-ordered in
various declarations, we have syntactic differences, which have evolved
organically, and do not convey anything about ABI implications of possible
changes.

Furthermore, the current struct declaration syntax makes it difficult for
the compiler to provide help and [guidance when changes occur](https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0036_update_struct_declarations.md.txt#compiler-guidance).

Let's look at examples, these are chosen to be small and uniform:

    struct Name {      table Name {        enum Name {
        T abc;           1: T abc;           ABC = 1;
        U xyz;           2: U xyz;           XYZ = 2;
    };                 };                  };

    protocol Name {    xunion Name {       bits Name {
        Abc(T t);        T abc;              ABC = 1;
        Xyz(U u);        U xyz;              XYZ = 2;
    };                 };                  };

Some observations from an ABI standpoint:

- Re-ordering: All but the struct can be re-ordered without any impact.
- Renaming:
  - struct, table, enum, and bits can be renamed with no impact
  - protocol, and xunion will have their ABI impacted upon rename.

(From a source compatibility standpoint, most bindings will be source
compatible under re-order, and incompatible under rename.)

Informed from these observations, we propose to introduce an ordinal for
struct declarations.
The example above would now be:

    struct Name {
        1: T abc;
        2: U xyz;
    };

Specifically:

- Ordinals must start at 1 and no gaps are allowed in the ordinal space (if the largest ordinal is 7, then all of 1,2,3,4,5,6,7 must be present). See [rationale below](https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0036_update_struct_declarations.md.txt#disallow-reserved-keyword).
- No two fields can claim the same ordinal.
- The field ordinal determines the placement of a field with a struct, not its syntactic position.
- No change to the JSON IR in v1, the ordinal is conveyed through the order of members in struct declaration. See planned change to JSON IR in v2.

### Compiler guidance

To exemplify the guidance, which the compiler can provide with the proposed
syntax, we consider a few examples and compare their handling.

#### Removing a field (middle)

    No Ordinals        With Ordinals
    ---   ---
    struct Name {      struct Name {
        T abc;           1: T abc;
    -   U def;       -   2: U def;
        V ghi;           3: V ghi;
    };                 };
    ---   ---
    Breaks ABI, no     Breaks ABI,
    compiler help      compiler error

#### Removing a field (end)

    No Ordinals        With Ordinals
    ---   ---
    struct Name {      struct Name {
        T abc;           1: T abc;
        U def;           2: U def;
    -   V ghi;       -   3: V ghi;
    };                 };
    ---   ---
    Breaks ABI, no     Breaks ABI, no
    compiler help      compiler help

#### Add a field

    No Ordinals        With Ordinals
    ---   ---
    struct Name {      struct Name {
        T abc;           1: T abc;
    +   U def;       +   3: U def;
        V ghi;           2: V ghi;
    };                 };
    ---   ---
    Breaks ABI, no     Breaks ABI, no
    compiler help      compiler error

#### Reorder fields

    No Ordinals        With Ordinals
    ---   ---
    struct Name {      struct Name {
    +   U def;       +   2: U def;
        T abc;           1: T abc;
    -   U def;       -   2: U def;
        V ghi;           3: V ghi;
    };                 };
    ---   ---
    Breaks ABI, no     Safe
    compiler warning

### Disallow 'reserved' keyword

Since we are aligning the ordinal rules for structs on that of tables, we
could look to also allow the 'reserved' keyword.

We should do the exact opposite: properly parse an accidental use of the
reserved keyword, and provide a clear compiler error and explanation. For
instance "Cannot reserve member in structs. Adding or removing members
alters a struct layout, consider instead neutral members manually
initialized."

There are also additional important reasons **not** to allow the
'reserved' keyword:

1. Unlike for tables, introducing padding in a struct must be done with an explicit size (i.e. number of bytes);
2. Using padding in structs is done for very specific purposes, when developers need a specific memory layout. This use case is rare, or even nonexistent since FIDL layout is always 8 bytes aligned.
3. Implementation-wise, we've clarified and explained in [RFC-0066:
   Programmer Advisory Explicit Defaults](https://fuchsia.dev/docs/contribute/governance/rfcs/0066_programmer_advisory_explicit) that guaranteeing certain values be initialized is too strong of a requirement for certain bindings (e.g. C, LLCPP). As a result, should we introduce 'reserved' slots in structs, we would need to expose that to backends, in order to expose that to developers for proper initialization. All this seems unnecessary.

#### Down the road JSON IR

In order to both support ordering of fields (by ordinal) and ordering for
documentation purposes (which should respect declaration order), it would
be better to:

- Represent declaration order as the order in which fields are presented in the "members" key.
- Represent ordinal order by introducing an "ordinal" key.

## Design

TBD

# Implementation strategy

1. Introduce support for the new syntax, while at the same time support the previous one;
2. Migrate all source files to the new syntax;
3. Add a warning when using the previous syntax, give a one week period to ensure no new uses of the previous syntax are added;
4. Remove support for the previous syntax.

## Ergonomics

This proposal improves ergonomics by conveying ABI implications to
developers through syntax. See an [opposing view on this
below](https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0036_update_struct_declarations#drawback_struct-and-tables-could-be-confused).

## Documentation and examples

At least:

- [Language Specification](https://fuchsia.dev/docs/reference/fidl/language/language)
- [Grammar](https://fuchsia.dev/docs/reference/fidl/language/grammar)
- Examples using structs

## Backwards compatibility

This is not source level backwards compatible.
See [Implementation Strategy](https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0036_update_struct_declarations.md.txt#implementation-strategy) to soft migrate.

## Performance

No impact.

## Security

No impact.

## Testing

Unit testing in `fidlc` to verify among others:

- Parsing;
- Ordinals start at 1, and may not have gaps;
- No change to JSON IR.

## Drawbacks, alternatives, and unknowns

### Alternative: Ordinal Hashing for Tables

We also considered using ordinal hashing for tables: the syntactic change
would be dropping explicit ordinals, making structs be the only declarations
with this syntax (whereas it used to be on protocols and tables).

Firstly, the benefits of having explicit ordinals for structs would remain.
Developers could still re-order fields syntactically, and changing
an ordinal would indicate ABI breakage.

Secondly, we are unlikely to act on the exploration to remove ordinals
from tables since the tradeoff between run-time cost (less performance)
outweigh the ergonomic benefits.

### Drawback: Struct and tables could be confused

With the syntax between struct and tables converging, and the introduction
of ordinals, some may confuse structs with tables, and mistakenly believe
that removing fields is ABI compatible.
While removing a field in the middle of a struct would cause an error due to
a gap appearing in the ordinal sequence, removing the field(s) with the
largest ordinal(s) would be silent.

## Prior art and references

TBD
[](https://issues.fuchsia.dev/issues/new?component=1439230&template=1881640&description=Issue+on:+https://fuchsia.dev/docs/contribute/governance/rfcs/0036_update_struct_declarations.md "Report a bug or suggest improvements on this page") [](https://cs.opensource.google/fuchsia/fuchsia/+/main:docs/contribute/governance/rfcs/0036_update_struct_declarations.md "View the source code of this page") [](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/contribute/governance/rfcs/0036_update_struct_declarations.md&cloneRepo=fuchsia/fuchsia:refs/heads/main&fullPath=fuchsia/docs/contribute/governance/rfcs/0036_update_struct_declarations.md "Edit the source code of this page")