blob: cb5174e88b9f3aed93f3d9500cc678ded5c0208a [file] [log] [blame]
//===- LogicalResult.h - Utilities for handling success/failure -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_SUPPORT_LOGICAL_RESULT_H
#define MLIR_SUPPORT_LOGICAL_RESULT_H
#include "mlir/Support/LLVM.h"
#include "llvm/ADT/Optional.h"
namespace mlir {
/// This class represents an efficient way to signal success or failure. It
/// should be preferred over the use of `bool` when appropriate, as it avoids
/// all of the ambiguity that arises in interpreting a boolean result. This
/// class is marked as NODISCARD to ensure that the result is processed. Users
/// may explicitly discard a result by using `(void)`, e.g.
/// `(void)functionThatReturnsALogicalResult();`. Given the intended nature of
/// this class, it generally shouldn't be used as the result of functions that
/// very frequently have the result ignored. This class is intended to be used
/// in conjunction with the utility functions below.
struct LLVM_NODISCARD LogicalResult {
public:
/// If isSuccess is true a `success` result is generated, otherwise a
/// 'failure' result is generated.
static LogicalResult success(bool isSuccess = true) {
return LogicalResult(isSuccess);
}
/// If isFailure is true a `failure` result is generated, otherwise a
/// 'success' result is generated.
static LogicalResult failure(bool isFailure = true) {
return success(!isFailure);
}
/// Returns true if the provided LogicalResult corresponds to a success value.
bool succeeded() const { return isSuccess; }
/// Returns true if the provided LogicalResult corresponds to a failure value.
bool failed() const { return !succeeded(); }
private:
LogicalResult(bool isSuccess) : isSuccess(isSuccess) {}
/// Boolean indicating if this is a success result, if false this is a
/// failure result.
bool isSuccess;
};
/// Utility function to generate a LogicalResult. If isSuccess is true a
/// `success` result is generated, otherwise a 'failure' result is generated.
inline LogicalResult success(bool isSuccess = true) {
return LogicalResult::success(isSuccess);
}
/// Utility function to generate a LogicalResult. If isFailure is true a
/// `failure` result is generated, otherwise a 'success' result is generated.
inline LogicalResult failure(bool isFailure = true) {
return LogicalResult::failure(isFailure);
}
/// Utility function that returns true if the provided LogicalResult corresponds
/// to a success value.
inline bool succeeded(LogicalResult result) { return result.succeeded(); }
/// Utility function that returns true if the provided LogicalResult corresponds
/// to a failure value.
inline bool failed(LogicalResult result) { return result.failed(); }
/// This class provides support for representing a failure result, or a valid
/// value of type `T`. This allows for integrating with LogicalResult, while
/// also providing a value on the success path.
template <typename T> class LLVM_NODISCARD FailureOr : public Optional<T> {
public:
/// Allow constructing from a LogicalResult. The result *must* be a failure.
/// Success results should use a proper instance of type `T`.
FailureOr(LogicalResult result) {
assert(failed(result) &&
"success should be constructed with an instance of 'T'");
}
FailureOr() : FailureOr(failure()) {}
FailureOr(T &&y) : Optional<T>(std::forward<T>(y)) {}
FailureOr(const T &y) : Optional<T>(y) {}
template <typename U,
std::enable_if_t<std::is_constructible<T, U>::value> * = nullptr>
FailureOr(const FailureOr<U> &other)
: Optional<T>(failed(other) ? Optional<T>() : Optional<T>(*other)) {}
operator LogicalResult() const { return success(this->hasValue()); }
private:
/// Hide the bool conversion as it easily creates confusion.
using Optional<T>::operator bool;
using Optional<T>::hasValue;
};
} // namespace mlir
#endif // MLIR_SUPPORT_LOGICAL_RESULT_H