Skip to content

Instantly share code, notes, and snippets.

@erica
Created February 5, 2019 21:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erica/8108f39c4247b40942ace7ff739c06d4 to your computer and use it in GitHub Desktop.
Save erica/8108f39c4247b40942ace7ff739c06d4 to your computer and use it in GitHub Desktop.
/// Unconditionally prints a given message and stops execution.
///
/// - Parameters:
/// - reason: The string to print.
/// - function: The name of the calling function to print with `reason`. The
/// default is the calling scope where `fatalError(because:, function:, file:, line:)`
/// is called.
/// - file: The file name to print with `reason`. The default is the file
/// where `fatalError(because:, function:, file:, line:)` is called.
/// - line: The line number to print along with `reason`. The default is the
/// line number where `fatalError(because:, function:, file:, line:)` is called.
@inlinable // FIXME(sil-serialize-all)
@_transparent
public func fatalError(
because reason: @autoclosure () -> CustomStringConvertible,
file: StaticString = #file,
line: UInt = #line,
function: StaticString = #function
) -> Never {
// FIXME: This includes the name of the calling function. This should probably
// be redesigned to use _assertionFailure()
Abort.because(reason(), file: file, line: line, function: function)
}
// Even after redesign, none of the following C-style calls currently uses
// policies to determine whether they fire in optimized and debug configurations.
/// Performs a traditional C-style assert with an optional message.
///
/// Use this function for internal sanity checks that are active during testing
/// but do not impact performance of shipping code. To check for invalid usage
/// in Release builds, see `precondition(_:_:file:line:)`.
///
/// * In playgrounds and `-Onone` builds (the default for Xcode's Debug
/// configuration): If `condition` evaluates to `false`, stop program
/// execution in a debuggable state after printing `reason`.
///
/// * In `-O` builds (the default for Xcode's Release configuration),
/// `condition` is not evaluated, and there are no effects.
///
/// * In `-Ounchecked` builds, `condition` is not evaluated, but the optimizer
/// may assume that it *always* evaluates to `true`. Failure to satisfy that
/// assumption is a serious programming error.
///
/// - Parameters:
/// - condition: The condition to test. `condition` is only evaluated in
/// playgrounds and `-Onone` builds.
/// - reason: A reason to print if `condition` is `false`.
/// - file: The file name to print with `reason` if the assertion fails. The
/// default is the file where `assert(_:_:file:line:)` is called.
/// - line: The line number to print along with `reason` if the assertion
/// fails. The default is the line number where `assert(_:_:file:line:)`
/// is called.
@_transparent
public func assert(
that condition: @autoclosure () -> Bool,
because reason: @autoclosure () -> CustomStringConvertible,
file: StaticString = #file,
line: UInt = #line,
function: StaticString = #function
) {
// Only assert in debug mode.
if _isDebugAssertConfiguration() {
Assert.that(condition(),
because: reason(),
file: file, line: line, function: function)
// if !_branchHint(condition(), expected: true) {
// _assertionFailure("Assertion failed", message(), file: file, line: line,
// flags: _fatalErrorFlags())
// }
}
}
/// Checks a necessary condition for making forward progress.
///
/// Use this function to detect conditions that must prevent the program from
/// proceeding, even in shipping code.
///
/// * In playgrounds and `-Onone` builds (the default for Xcode's Debug
/// configuration): If `condition` evaluates to `false`, stop program
/// execution in a debuggable state after printing `reason`.
///
/// * In `-O` builds (the default for Xcode's Release configuration): If
/// `condition` evaluates to `false`, stop program execution.
///
/// * In `-Ounchecked` builds, `condition` is not evaluated, but the optimizer
/// may assume that it *always* evaluates to `true`. Failure to satisfy that
/// assumption is a serious programming error.
///
/// - Parameters:
/// - condition: The condition to test. `condition` is not evaluated in
/// `-Ounchecked` builds.
/// - reason: A reason to print in a playground or `-Onone` build if the
/// `condition` is false.
/// - file: The file name to print with `reason` if the precondition fails.
/// The default is the file where `precondition(_:_:file:line:)` is
/// called.
/// - line: The line number to print along with `reason` if the assertion
/// fails. The default is the line number where
/// `precondition(_:_:file:line:)` is called.
@_transparent
public func precondition(
that condition: @autoclosure () -> Bool,
because reason: @autoclosure () -> CustomStringConvertible,
file: StaticString = #file,
line: UInt = #line,
function: StaticString = #function
) {
// Only check in debug and release mode. In release mode just trap.
if _isDebugAssertConfiguration() {
Assert.that(condition(),
because: reason(),
file: file, line: line, function: function)
}
// The following would have to be fixed
// if !_branchHint(condition(), expected: true) {
// _assertionFailure("Precondition failed", message(), file: file, line: line,
// flags: _fatalErrorFlags())
// }
// } else if _isReleaseAssertConfiguration() {
// let error = !condition()
// Builtin.condfail(error._value)
// }
}
/// Indicates that a precondition was violated.
///
/// Use this function to stop the program when control flow can only reach the
/// call if your API was improperly used. This function's effects vary
/// depending on the build flag used:
///
/// * In playgrounds and `-Onone` builds (the default for Xcode's Debug
/// configuration), stops program execution in a debuggable state after
/// printing `reason`.
///
/// * In `-O` builds (the default for Xcode's Release configuration), stops
/// program execution.
///
/// * In `-Ounchecked` builds, the optimizer may assume that this function is
/// never called. Failure to satisfy that assumption is a serious
/// programming error.
///
/// - Parameters:
/// - reason: A reason to print in a playground or `-Onone` build.
/// - file: The file name to print with `reason`. The default is the file
/// where `preconditionFailure(_:file:line:)` is called.
/// - line: The line number to print along with `reason`. The default is the
/// line number where `preconditionFailure(_:file:line:)` is called.
@_transparent
public func preconditionFailure(
because reason: @autoclosure () -> CustomStringConvertible,
file: StaticString = #file,
line: UInt = #line,
function: StaticString = #function
) -> Never {
// Only check in debug and release mode. In release mode just trap.
if _isDebugAssertConfiguration() {
Abort.because(reason(),
file: file, line: line, function: function)
// _assertionFailure("Fatal error", reason(), file: file, line: line,
// flags: _fatalErrorFlags())
// } else if _isReleaseAssertConfiguration() {
// Builtin.int_trap()
}
// _conditionallyUnreachable()
}
/// Indicates that an internal sanity check failed.
///
/// Use this function to stop the program, without impacting the performance of
/// shipping code, when control flow is not expected to reach the call---for
/// example, in the `default` case of a `switch` where you have knowledge that
/// one of the other cases must be satisfied. To protect code from invalid
/// usage in Release builds, see `preconditionFailure(_:file:line:)`.
///
/// * In playgrounds and -Onone builds (the default for Xcode's Debug
/// configuration), stop program execution in a debuggable state after
/// printing `reason`.
///
/// * In -O builds, has no effect.
///
/// * In -Ounchecked builds, the optimizer may assume that this function is
/// never called. Failure to satisfy that assumption is a serious
/// programming error.
///
/// - Parameters:
/// - reason: A reason to print in a playground or `-Onone` build.
/// - file: The file name to print with `reason`. The default is the file
/// where `assertionFailure(_:file:line:)` is called.
/// - line: The line number to print along with `reason`. The default is the
/// line number where `assertionFailure(_:file:line:)` is called.
@inlinable
@inline(__always)
public func assertionFailure(
because reason: @autoclosure () -> CustomStringConvertible,
file: StaticString = #file,
line: UInt = #line,
function: StaticString = #function
) {
if _isDebugAssertConfiguration() {
Abort.because(reason(),
file: file, line: line, function: function)
}
// _assertionFailure("Fatal error", message(), file: file, line: line,
// flags: _fatalErrorFlags())
// }
// else if _isFastAssertConfiguration() {
// _conditionallyUnreachable()
// }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment