RFC-0231: FIDL versioning replacement syntax | |
---|---|
Status | Accepted |
Areas |
|
Description | Add a replaced=N argument to the @available attribute |
Issues | |
Gerrit change | |
Authors | |
Reviewers | |
Date submitted (year-month-day) | 2023-09-26 |
Date reviewed (year-month-day) | 2023-10-24 |
Summary
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.
Background
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.
Motivation
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.
Stakeholders
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.
Design
Introduce a new
@available
argument namedreplaced
. It behaves the same asremoved
except it has different validation, described below. It can be used instead ofremoved
on any element except thelibrary
declaration.When an element is marked
removed=N
, validate that there IS NOT another element with the same name markedadded=N
.When an element is marked
replaced=N
, validate that there IS another element with the same name markedadded=N
.This validation only applies to elements that are directly marked
removed
orreplaced
, not to child elements that inherit the arguments.
Examples
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
.
Implementation
Implement the
replaced
argument, including its validation.Change all FIDL files to use
replaced
instead ofremoved
when applicable.Implement the new
removed
validation. CQ will fail if (2) missed anything.
Performance
This proposal has no impact on performance.
Ergonomics
This proposal makes the swapping pattern more ergonomic by directly supporting it in the language.
Backwards compatibility
This proposal has no impact on backwards compatibility.
Security considerations
This proposal has no impact on security.
Privacy considerations
This proposal has no impact on privacy.
Testing
This following files must be updated to test the new behavior:
- tools/fidl/fidlc/tests/availability_interleaving_tests.cc
- tools/fidl/fidlc/tests/decomposition_tests.cc
- tools/fidl/fidlc/tests/versioning_tests.cc
- tools/fidl/fidlc/tests/versioning_types_tests.cc
Documentation
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.
Drawbacks, alternatives, and unknowns
Alternative: Re-added argument
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.
Prior art and references
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.