Files
swift-mirror/stdlib/core/Assert.swift
Jordan Rose cca27d02a0 Tag everything in the standard library with accessibility attributes.
Keep calm: remember that the standard library has many more public exports
than the average target, and that this contains ALL of them at once.
I also deliberately tried to tag nearly every top-level decl, even if that
was just to explicitly mark things @internal, to make sure I didn't miss
something.

This does export more than we might want to, mostly for protocol conformance
reasons, along with our simple-but-limiting typealias rule. I tried to also
mark things private where possible, but it's really going to be up to the
standard library owners to get this right. This is also only validated
against top-level access control; I haven't fully tested against member-level
access control yet, and none of our semantic restrictions are in place.

Along the way I also noticed bits of stdlib cruft; to keep this patch
understandable, I didn't change any of them.

Swift SVN r19145
2014-06-24 21:32:18 +00:00

210 lines
6.7 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// User code assertions.
///
/// User code assertions and fatal errors are only enabled in debug mode. In
/// release or fast mode these checks are disabled. This means they may have no
/// effect on program semantics, depending on the assert configuration.
/// Traditional C-style assert with an optional message.
/// When assertions are enabled and `condition` is false, stop program
/// execution in a debuggable state after printing a message. When
/// assertions are disabled in release and fast builds, `condition` is not even
/// evaluated.
@transparent @public
func assert(
condition: @auto_closure () -> Bool, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only assert in debug mode.
if _isDebugAssertConfiguration() {
if !_branchHint(condition(), true) {
_assertionFailed("assertion failed", message, file, line)
}
}
}
@transparent @public
func assert<T : LogicValue>(
condition: @auto_closure () -> T, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only assert in debug mode.
if _isDebugAssertConfiguration() {
if !_branchHint(condition(), true) {
_assertionFailed("assertion failed", message, file, line)
}
}
}
/// A fatal error occurred and program execution should stop in debug mode. In
/// optimized builds this is a noop.
@transparent @noreturn @public
func fatalError(
message: StaticString,
file: StaticString = __FILE__, line: UWord = __LINE__
) {
if _isDebugAssertConfiguration() {
_assertionFailed("fatal error", message, file, line)
}
_conditionallyUnreachable()
}
/// Library precondition checks
///
/// Library precondition checks are enabled in debug mode and release mode. When
/// building in fast mode they are disabled. In release mode they don't print
/// an error message but just trap. In debug mode they print an error message
/// and abort.
@transparent @public
func _precondition(
condition: @auto_closure () -> Bool, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only check in debug and release mode. In release mode just trap.
if _isDebugAssertConfiguration() {
if !_branchHint(condition(), true) {
_fatalErrorMessage("fatal error", message, file, line)
}
} else if _isReleaseAssertConfiguration() {
let error = !condition()
Builtin.condfail(error.value)
}
}
@transparent @public
func _precondition<T : LogicValue>(
condition: @auto_closure () -> T, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only check in debug and release mode. In release mode just trap.
if _isDebugAssertConfiguration() {
if !_branchHint(condition(), true) {
_fatalErrorMessage("fatal error", message, file, line)
}
} else if _isReleaseAssertConfiguration() {
let error = !condition().getLogicValue();
Builtin.condfail(error.value)
}
}
@transparent @public @noreturn
func _preconditionFailure(
_ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__) {
_precondition(false, message, file:file, line: line)
_conditionallyUnreachable()
}
/// If `error` is true, prints an error message in debug mode, traps in release
/// mode, and returns an undefined error otherwise.
/// Otherwise returns `result`.
@transparent @public
func _overflowChecked<T>(
args: (T, Bool),
file: StaticString = __FILE__, line: UWord = __LINE__
) -> T {
let (result, error) = args
if _isDebugAssertConfiguration() {
if _branchHint(error, false) {
_fatalErrorMessage("fatal error", "Overflow/underflow", file, line)
}
} else {
Builtin.condfail(error.value)
}
return result
}
/// Debug library precondition checks
///
/// Debug library precondition checks are only on in debug mode. In release and
/// in fast mode they are disabled. In debug mode they print an error message
/// and abort.
/// They are meant to be used when the check is not comprehensively checking for
/// all possible errors.
@transparent @public
func _debugPrecondition(
condition: @auto_closure () -> Bool, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only check in debug mode.
if _isDebugAssertConfiguration() {
if !_branchHint(condition(), true) {
_fatalErrorMessage("fatal error", message, file, line)
}
}
}
@transparent @public
func _debugPrecondition<T : LogicValue>(
condition: @auto_closure () -> T, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only check in debug mode.
if _isDebugAssertConfiguration() {
if !_branchHint(condition(), true) {
_fatalErrorMessage("fatal error", message, file, line)
}
}
}
@transparent @noreturn @public
func _debugPreconditionFailure(
_ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__) {
if _isDebugAssertConfiguration() {
_precondition(false, message, file: file, line: line)
}
_conditionallyUnreachable()
}
/// Internal checks
///
/// Internal checks are to be used for checking correctness conditions in the
/// standard library. They are only enable when the standard library is built
/// with the build configuration INTERNAL_CHECKS_ENABLED enabled. Otherwise, the
/// call to this function is a noop.
@transparent @public
func _sanityCheck(
condition: @auto_closure () -> Bool, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
#if INTERNAL_CHECKS_ENABLED
if !_branchHint(condition(), true) {
_fatalErrorMessage("fatal error", message, file, line)
}
#endif
}
@transparent @public
func _sanityCheck<T : LogicValue>(
condition: @auto_closure () -> T, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
#if INTERNAL_CHECKS_ENABLED
if !_branchHint(condition(), true) {
_fatalErrorMessage("fatal error", message, file, line)
}
#endif
}
@transparent @noreturn @public
func _fatalError(
_ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
_sanityCheck(false, message, file: file, line: line)
_conditionallyUnreachable();
}