[PATCH] D34600: [Error] add expectSuccess()

Zachary Turner via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 24 21:56:34 PDT 2017


zturner created this revision.

Often times you expect an operation to succeed, and it's cumbersome and impacts readability to constantly be checking errors which you assume are going to succeed.  It's even worse with `Expected<T>`, because you have to write something like:

  auto ExpectedFoo = getFoo();
  if (!ExpectedFoo)
    return ExpectedFoo.takeError();
  auto &Foo = *ExpectedFoo;

which is 4 lines of code for something that should take 1 (assuming, again, that you have special knowledge which would allow you to know in advance it will succeed).  You can reduce it to 3 lines by doing this:

  auto ExpectedFoo = getFoo();
  consumeError(ExpectedFoo.takeError());
  auto &Foo = *ExpectedFoo;

But now if there ever actually *is* an error, it's dropped on the floor.  So we could add an assert, but now we're back to 4 lines.

It would be nice to have a function which asserts if there is an error, so we get notified in debug builds, but continues on as if nothing ever happened in release.  We already have a similar construct which is `ExitOnErr`, but we want a similar construct that doesn't exit and still allows us to extract the value and consume the error in a single line.  With this patch we can write:

  expectSuccess(doSomething());    // returns an Error
  auto Value = expectSuccess(getSomething());    // returns an Expected<T>

and it just works, with 1 line.


https://reviews.llvm.org/D34600

Files:
  llvm/include/llvm/Support/Error.h


Index: llvm/include/llvm/Support/Error.h
===================================================================
--- llvm/include/llvm/Support/Error.h
+++ llvm/include/llvm/Support/Error.h
@@ -887,6 +887,27 @@
 #endif
 };
 
+/// assert if an Error condition is present, but check it regardless.  This
+/// method should be used when an error condition is not expected and you want
+/// to forego checking the value.  For example, you may wish to write the code:
+///
+/// if (willOperationSucceed()) {
+///   expectSuccess(doOperation());
+/// }
+///
+/// and save the extra line(s) that would normally be needed to check the return
+/// value.
+inline void expectSuccess(Error Err) {
+  assert(!Err);
+  consumeError(std::move(Err));
+}
+
+/// Similar to expectSuccess(Error), but for Expected<T>
+template <typename T> T expectSuccess(Expected<T> &&Value) {
+  expectSuccess(Value.takeError());
+  return *Value;
+}
+
 /// Helper for Expected<T>s used as out-parameters.
 ///
 /// See ErrorAsOutParameter.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D34600.103857.patch
Type: text/x-patch
Size: 1004 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170625/0ca0d9da/attachment.bin>


More information about the llvm-commits mailing list