[Support][Error] Add a 'cantFail' utility function for known-safe calls to
fallible functions.
Some fallible functions (those returning Error or Expected<T>) may only fail
for a subset of their inputs. For example, a "safe" square root function will
succeed for all finite positive inputs:
Expected<double> safeSqrt(double d) {
if (d < 0 && !isnan(d) && !isinf(d))
return make_error<...>("Cannot sqrt -ve values, nans or infs");
return sqrt(d);
}
At a safe callsite for such a function, checking the error return value is
redundant:
if (auto ValOrErr = safeSqrt(42.0)) {
// use *ValOrErr.
} else
llvm_unreachable("safeSqrt should always succeed for +ve values");
The cantFail function wraps this check and extracts the contained value,
simplifying control flow:
double Result = cantFail(safeSqrt(42.0));
This function should be used with care: it is a programmatic error to wrap a
call with cantFail if it can in fact fail. For debug builds this will
result in llvm_unreachable being called. For release builds the behavior is
undefined.
Use of this function is likely to be rare in library code, but more common
for tool and unit-test code where inputs and mock functions may be known to be
safe.
llvm-svn: 296384
diff --git a/llvm/docs/ProgrammersManual.rst b/llvm/docs/ProgrammersManual.rst
index f6480d0..d07f7c5 100644
--- a/llvm/docs/ProgrammersManual.rst
+++ b/llvm/docs/ProgrammersManual.rst
@@ -564,18 +564,18 @@
.. code-block:: c++
- if (auto Err = canFail(...))
+ if (auto Err = mayFail(...))
return Err; // Failure value - move error to caller.
// Safe to continue: Err was checked.
-In contrast, the following code will always cause an abort, even if ``canFail``
+In contrast, the following code will always cause an abort, even if ``mayFail``
returns a success value:
.. code-block:: c++
- canFail();
- // Program will always abort here, even if canFail() returns Success, since
+ mayFail();
+ // Program will always abort here, even if mayFail() returns Success, since
// the value is not checked.
Failure values are considered checked once a handler for the error type has
@@ -633,6 +633,12 @@
may be a better choice than handleErrors, as it simplifies control flow when
calling fallible functions.
+In situations where it is known that a particular call to a fallible function
+will always succeed (for example, a call to a function that can only fail on a
+subset of inputs with an input that is known to be safe) the
+:ref:`cantFail <err_cantfail>` functions can be used to remove the error type,
+simplifying control flow.
+
StringError
"""""""""""
@@ -765,6 +771,43 @@
Use ``ExitOnError`` in your tool code where possible as it can greatly improve
readability.
+.. _err_cantfail:
+
+Using cantFail to simplify safe callsites
+"""""""""""""""""""""""""""""""""""""""""
+
+Some functions may only fail for a subset of their inputs. For such functions
+call-sites using known-safe inputs can assume that the result will be a success
+value.
+
+The cantFail functions encapsulate this by wrapping an assertion that their
+argument is a success value and, in the case of Expected<T>, unwrapping the
+T value from the Expected<T> argument:
+
+.. code-block:: c++
+
+ Error mayFail(int X);
+ Expected<int> mayFail2(int X);
+
+ void foo() {
+ cantFail(mayFail(KnownSafeValue));
+ int Y = cantFail(mayFail2(KnownSafeValue));
+ ...
+ }
+
+Like the ExitOnError utility, cantFail simplifies control flow. Their treatment
+of error cases is very different however: Where ExitOnError is guaranteed to
+terminate the program on an error input, cantFile simply asserts that the result
+is success. In debug builds this will result in an assertion failure if an error
+is encountered. In release builds the behavior of cantFail for failure values is
+undefined. As such, care must be taken in the use of cantFail: clients must be
+certain that a cantFail wrapped call really can not fail under any
+circumstances.
+
+Use of the cantFail functions should be rare in library code, but they are
+likely to be of more use in tool and unit-test code where inputs and/or
+mocked-up classes or functions may be known to be safe.
+
Fallible constructors
"""""""""""""""""""""