summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--assertions/Cargo.toml4
-rw-r--r--assertions/src/lib.rs47
-rw-r--r--assertions/src/mechanism.rs34
3 files changed, 85 insertions, 0 deletions
diff --git a/assertions/Cargo.toml b/assertions/Cargo.toml
new file mode 100644
index 0000000..36f9beb
--- /dev/null
+++ b/assertions/Cargo.toml
@@ -0,0 +1,4 @@
+[package]
+name = "assertions"
+version = "0.1.0"
+authors = ["The Chromium OS Authors"]
diff --git a/assertions/src/lib.rs b/assertions/src/lib.rs
new file mode 100644
index 0000000..c53c0c4
--- /dev/null
+++ b/assertions/src/lib.rs
@@ -0,0 +1,47 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Macros that assert properties of code at compile time.
+//!
+//! A static assertion is particularly appropriate when unsafe code relies on
+//! two types to have the same size, or on some type to have a particular size.
+
+#[doc(hidden)]
+pub mod mechanism;
+
+// Re-export so that these types appear with a more concise name in error
+// messages.
+#[doc(hidden)]
+pub use mechanism::*;
+
+/// Macro that fails to compile if a given const expression is not true.
+///
+/// # Example
+///
+/// ```rust
+/// extern crate assertions;
+/// use assertions::const_assert;
+///
+/// fn main() {
+///     const_assert!(std::mem::size_of::<String>() == 24);
+/// }
+/// ```
+///
+/// # Example that fails to compile
+///
+/// ```rust,compile_fail
+/// extern crate assertions;
+/// use assertions::const_assert;
+///
+/// fn main() {
+///     // fails to compile:
+///     const_assert!(std::mem::size_of::<String>() == 8);
+/// }
+/// ```
+#[macro_export]
+macro_rules! const_assert {
+    ($e:expr) => {
+        let _: $crate::Assert<[(); $e as bool as usize]>;
+    };
+}
diff --git a/assertions/src/mechanism.rs b/assertions/src/mechanism.rs
new file mode 100644
index 0000000..e14b91a
--- /dev/null
+++ b/assertions/src/mechanism.rs
@@ -0,0 +1,34 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use std::marker::PhantomData;
+
+pub struct True;
+pub struct False;
+
+pub trait Expr {
+    type Value;
+}
+
+impl Expr for [(); 0] {
+    type Value = False;
+}
+
+impl Expr for [(); 1] {
+    type Value = True;
+}
+
+// If the macro instantiates this with `T = [(); 1]` then it compiles successfully.
+//
+// On the other hand if `T = [(); 0]` the user receives an error like the following:
+//
+//    error[E0271]: type mismatch resolving `<[(); 0] as assertions::Expr>::Value == assertions::True`
+//     --> src/main.rs:5:5
+//      |
+//    5 |     const_assert!(std::mem::size_of::<String>() == 8);
+//      |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `assertions::True`, found struct `assertions::False`
+//
+pub struct Assert<T: Expr<Value = True>> {
+    marker: PhantomData<T>,
+}