{% set rfcid = “RFC-0231” %} {% include “docs/contribute/governance/rfcs/_common/_rfc_header.md” %}
{# Fuchsia RFCs use templates to display various fields from _rfcs.yaml. View the #} {# fully rendered RFCs at https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs #}
Note: This RFC is an amendment to RFC-0083: FIDL versioning.
Change FIDL's @available
attribute to support a replaced
argument. It is like removed
, but validates that a replacement is added
at the same version.
RFC-0083: FIDL versioning introduced the @available
attribute for versioning FIDL APIs. One requirement in that design was to allow versioning all possible changes. In other words, it should be possible to express v1.fidl
transitioning to an arbitrarily different v2.fidl
in a single versioned.fidl
file. The design satisfied that requirement by allowing multiple elements to have the same name as long as their version ranges don't overlap.
For example, consider adding the @discoverable
attribute to protocol P
at version 5. We can‘t express this directly with @available
, since attributes can’t be placed on other attributes. However, we can instead do this:
@available(added=1, removed=5) protocol P {}; @available(added=5) @discoverable protocol P {};
This technique of removing an element and re-adding it at the same version is known as swapping.
The syntax for the usual lifecycle of adding, deprecating, and removing APIs is intuitive. The swapping pattern, on the other hand, is not. It makes sense when explained, but it is a hidden feature that requires explanation. In the example above, you'd be forgiven for thinking removed=5
really means the protocol is gone in version 5, especially if the corresponding added=5
is not adjacent in the source code.
Distinguishing replacement from removal also makes it possible to get rid of the legacy feature and replace it with a more general solution. This is a separate proposal: RFC-0232: FIDL bindings for multiple API levels.
Facilitator: abarth@google.com
Reviewers: hjfreyer@google.com, ianloic@google.com, ddorwin@google.com
Consulted: wez@google.com, sethladd@google.com, wilkinsonclay@google.com
Socialization: I discussed this idea with the FIDL team and the Platform Versioning working group before writing the RFC.
Introduce a new @available
argument named replaced
. It behaves the same as removed
except it has different validation, described below. It can be used instead of removed
on any element except the library
declaration.
When an element is marked removed=N
, validate that there IS NOT another element with the same name marked added=N
.
When an element is marked replaced=N
, validate that there IS another element with the same name marked added=N
.
This validation only applies to elements that are directly marked removed
or replaced
, not to child elements that inherit the arguments.
The example from the Background section of adding @discoverable
to a protocol at version 5 looks like this in the new design:
@available(added=1, replaced=5) protocol P {}; @available(added=5) @discoverable protocol P {};
As another example, consider replacing a struct that contains a member with an anonymous type:
@available(added=1, replaced=2) struct Foo { bar @generated_name("Bar") table {}; }; @available(added=2) struct Foo { baz string; };
Since the first Foo
is marked replaced=2
, fidlc validates that there is another Foo
marked added=2
. However, it does not perform similar validation for the child element bar
, nor for its anonymous type Bar
.
Implement the replaced
argument, including its validation.
Change all FIDL files to use replaced
instead of removed
when applicable.
Implement the new removed
validation. CQ will fail if (2) missed anything.
This proposal has no impact on performance.
This proposal makes the swapping pattern more ergonomic by directly supporting it in the language.
This proposal has no impact on backwards compatibility.
This proposal has no impact on security.
This proposal has no impact on privacy.
This following files must be updated to test the new behavior:
The following pages must be updated to document replaced
:
The term “swapping” should also be removed in favor of “replaced”.
The fidldoc tool currently operates on the JSON IR for a single API level, so it never sees removed
arguments, and will not see replaced
either (https://fxbug.dev/42084086). When this is fixed, fidldoc should be updated to clearly indicate when something is replaced as opposed to removed.
This proposal introduces the replaced
argument, which makes it clear when an element is being replaced rather than removed. It prevents the scenario, “I thought I couldn't use this API because it says removed=5
and we target 6.”
We could similarly introduce a re_added
argument to clarify when an element is added as a replacement rather than being added for the first time. It would prevent the scenario, “I thought I couldn't use this API yet because it says added=6
and we target 5.”
I rejected this alternative for a few reasons:
I believe the first scenario is more important than the second.
The name re_added
is unsatisfactory, and I couldn't think of a better one.
Even without this, we can still make fidldoc infer whether an element is added
for the first time or not.
I discussed a similar idea in 2021 while developing FIDL versioning, in an internal document titled “FIDL versioning: Swapping elements”.
This proposal is very specific to the design of FIDL versioning, so there is no prior art on this exact problem, as far as I know.