PSA: FIDL error methods now use fitx::result in LLCPP

60 views
Skip to first unread message

Alex Zaslavsky

unread,
May 27, 2022, 6:37:55 PM5/27/22
to fidl...@fuchsia.dev

If you don't use the FIDL C++ bindings, you may stop reading.

TL;DR: FIDL methods using the error syntax, like MyMethod() -> (Foo) error Bar;, will now use fitx::result to represent their replies going forward.  You don't need to do anything, as all existing uses have been converted.


For a FIDL method that uses the error syntax, like MyMethod() -> (Foo) error Bar;, most FIDL bindings languages in use today expose the output union in a form native to the language.  For instance, the Rust signature generated for the aforementioned example is (roughly) pub fn my_method(&self) -> Result<Result<Foo, Bar>, fidl::Error>.  Rather than expose the underlying FIDL union, the Rust bindings express it as a Result<Payload, DomainError>, which is a more familiar form to that language's users.

Until recently, the LLCPP bindings were different: they exposed the result type as the underlying FIDL Union that it is on the wire.  In essence, the bindings acted as though you had written MyMethod() -> (union { response foo; err bar; }); when defining your method.  This was confusing ("I never wrote the word union in my method signature, why is this method returning one?") and unergonomic, due to an extra layer of unnecessary indirection.

Enter fitx::result, a Rust-esque result library familiar to many Fuchsia programmers.  Where before, you may have written:

auto result = fidl::WireCall(endpoints->client)->MyMethod();

if (result.status()) {

  // Handle transport error

} else if (result->result.is_err()) {

  auto my_error_value = result->result.err();

  // Handle domain error

}

auto my_payload_value = result->result.response();

// Do stuff with successful reply payload

Now, you should write (differences highlighted):

auto result = fidl::WireCall(endpoints->client)->MyMethod();

if (result.status()) {

  // Handle transport error

} else if (result->is_error()) {

  auto my_error_value = result->error_value();

  // Handle domain error

}

auto my_payload_value = result->value();

// Do stuff with successful reply payload

Dereferencing via response-> produces the type fitx::result<DomainError, Payload*>, with all of the usual methods a fitx::result carries, like is_ok(), value(), is_error(), and error_value().  This results in less verbose code, and migrates use cases such as these to a form that is very familiar to C++ programmers working on the system today.

Which APIs, specifically, will change?

Every two-way method reply in LLCPP is represented by the fidl::WireResult<M>/fidl::WireUnownedResult<M> template specializations, with M being the method name.  This type typically has two methods, Unwrap() and value(), as well as two operator overloads, -> and *, which will now operate on fitx::result<DomainError, Payload*> rather than a FIDL union of the same.

Will cases with no error payload, like MyMethod() -> (Foo);, be affected?

No, all such uses will stay the same.

What about cases where there is no success payload, like MyMethod() -> (struct{}) error Bar;?

The generated fitx::result will only have one arm, the error, creating the type fitx::result<MyMethodBar>.

Do these changes affect HLCPP?

No, only the LLCPP will be affected.  HLCPP users should consider migrating to the unified C++ bindings, which also use the fitx::result formulation, among many other quality of life improvements.

Do I need to proactively migrate anything?

No.  A benevolent wizard from a far away land (Gandalf the Fuchsia?) has waved their wand and converted the entirety of fuchsia.git to use the new syntax.

I now see value_NEW() and Unwrap_NEW() sprinkled around my code.  What gives?

The wizard mentioned above is powerful, but not omnipotent, and needs to work their magic over several CLs.  The methods you see are functionally identical to their non-_NEW() suffixed counterparts, and have only been introduced to aid the (multi-repo) migration to the new API.  These suffixes will disappear over the next few days.


Alex


Yifei Teng

unread,
May 27, 2022, 8:17:36 PM5/27/22
to Alex Zaslavsky, fidl...@fuchsia.dev
image.png

Exposing the wire format union in LLCPP lead to the confusing `result->result.response()` blurb every time one calls a method with the error syntax. It also prevented us from adding more members under the hood and implementing unknown interactions cleanly. Thank you so much for the incredible amount of wizardry (migrating all the usages) to make this possible.

--
All posts must follow the Fuchsia Code of Conduct https://fuchsia.dev/fuchsia-src/CODE_OF_CONDUCT or may be removed.
---
You received this message because you are subscribed to the Google Groups "fidl-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fidl-dev+u...@fuchsia.dev.
To view this discussion on the web visit https://groups.google.com/a/fuchsia.dev/d/msgid/fidl-dev/CAPkkwnyQXJBphcaTb%2BjgsChiiuDEGFL7249sMS1TPCdTtOKe_w%40mail.gmail.com.

David Gilhooley

unread,
Jun 2, 2022, 2:27:46 PM6/2/22
to fidl-dev, Yifei Teng, fidl...@fuchsia.dev, Alex Zaslavsky
I'm a little late to the party but this is maybe one of the greatest ergonomic wins to hit LLCPP FIDL since tables :)

I would always have the LLCPP examples page open in my browser for a working example of 
result->result.response()

And now I can actually write code from memory, or by using code suggestions.
Things are much easier to read and to write!

Thank you everyone that worked on this!
Reply all
Reply to author
Forward
0 new messages