diff options
author | Lang Hames <lhames@gmail.com> | 2017-02-27 21:09:47 +0000 |
---|---|---|
committer | Lang Hames <lhames@gmail.com> | 2017-02-27 21:09:47 +0000 |
commit | 530cc1a7c8ae6daf499bd88e7fd4b6518dd5e6eb (patch) | |
tree | 3f6a26aea38f6e012598cd028bea4ea01c066892 /docs/ProgrammersManual.rst | |
parent | 563a987b91362dfbf6ec4cdd78ba9715d3032a77 (diff) |
[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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296384 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'docs/ProgrammersManual.rst')
-rw-r--r-- | docs/ProgrammersManual.rst | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/docs/ProgrammersManual.rst b/docs/ProgrammersManual.rst index f6480d0f8b4..d07f7c58f03 100644 --- a/docs/ProgrammersManual.rst +++ b/docs/ProgrammersManual.rst @@ -564,18 +564,18 @@ the boolean conversion operator): .. 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 @@ exiting with an error code, the :ref:`ExitOnError <err_exitonerr>` utility 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 @@ mapping can also be supplied from ``Error`` values to exit codes using the 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 """"""""""""""""""""" |