Skip to content

Commit 517083f

Browse files
committed
Make assert macro a built-in procedural macro
1 parent 6f2100b commit 517083f

File tree

5 files changed

+137
-1
lines changed

5 files changed

+137
-1
lines changed

src/libcore/macros.rs

+15
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ macro_rules! panic {
7676
/// ```
7777
#[macro_export]
7878
#[stable(feature = "rust1", since = "1.0.0")]
79+
#[cfg(stage0)]
7980
macro_rules! assert {
8081
($cond:expr) => (
8182
if !$cond {
@@ -784,4 +785,18 @@ mod builtin {
784785
($file:expr) => ({ /* compiler built-in */ });
785786
($file:expr,) => ({ /* compiler built-in */ });
786787
}
788+
789+
/// Ensure that a boolean expression is `true` at runtime.
790+
///
791+
/// For more information, see the documentation for [`std::assert!`].
792+
///
793+
/// [`std::assert!`]: ../std/macro.assert.html
794+
#[macro_export]
795+
#[stable(feature = "rust1", since = "1.0.0")]
796+
#[cfg(dox)]
797+
macro_rules! assert {
798+
($cond:expr) => ({ /* compiler built-in */ });
799+
($cond:expr,) => ({ /* compiler built-in */ });
800+
($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
801+
}
787802
}

src/libstd/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,9 @@ use prelude::v1::*;
355355
// We want to re-export a few macros from core but libcore has already been
356356
// imported by the compiler (via our #[no_std] attribute) In this case we just
357357
// add a new crate name so we can attach the re-exports to it.
358-
#[macro_reexport(assert, assert_eq, assert_ne, debug_assert, debug_assert_eq,
358+
#[macro_reexport(assert_eq, assert_ne, debug_assert, debug_assert_eq,
359359
debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
360+
#[cfg_attr(stage0, macro_reexport(assert))]
360361
extern crate core as __core;
361362

362363
#[macro_use]

src/libstd/macros.rs

+54
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,60 @@ pub mod builtin {
719719
($file:expr) => ({ /* compiler built-in */ });
720720
($file:expr,) => ({ /* compiler built-in */ });
721721
}
722+
723+
/// Ensure that a boolean expression is `true` at runtime.
724+
///
725+
/// This will invoke the [`panic!`] macro if the provided expression cannot be
726+
/// evaluated to `true` at runtime.
727+
///
728+
/// # Uses
729+
///
730+
/// Assertions are always checked in both debug and release builds, and cannot
731+
/// be disabled. See [`debug_assert!`] for assertions that are not enabled in
732+
/// release builds by default.
733+
///
734+
/// Unsafe code relies on `assert!` to enforce run-time invariants that, if
735+
/// violated could lead to unsafety.
736+
///
737+
/// Other use-cases of `assert!` include [testing] and enforcing run-time
738+
/// invariants in safe code (whose violation cannot result in unsafety).
739+
///
740+
/// # Custom Messages
741+
///
742+
/// This macro has a second form, where a custom panic message can
743+
/// be provided with or without arguments for formatting. See [`std::fmt`]
744+
/// for syntax for this form.
745+
///
746+
/// [`panic!`]: macro.panic.html
747+
/// [`debug_assert!`]: macro.debug_assert.html
748+
/// [testing]: ../book/second-edition/ch11-01-writing-tests.html#checking-results-with-the-assert-macro
749+
/// [`std::fmt`]: ../std/fmt/index.html
750+
///
751+
/// # Examples
752+
///
753+
/// ```
754+
/// // the panic message for these assertions is the stringified value of the
755+
/// // expression given.
756+
/// assert!(true);
757+
///
758+
/// fn some_computation() -> bool { true } // a very simple function
759+
///
760+
/// assert!(some_computation());
761+
///
762+
/// // assert with a custom message
763+
/// let x = true;
764+
/// assert!(x, "x wasn't true!");
765+
///
766+
/// let a = 3; let b = 27;
767+
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
768+
/// ```
769+
#[stable(feature = "rust1", since = "1.0.0")]
770+
#[macro_export]
771+
macro_rules! assert {
772+
($cond:expr) => ({ /* compiler built-in */ });
773+
($cond:expr,) => ({ /* compiler built-in */ });
774+
($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
775+
}
722776
}
723777

724778
/// A macro for defining #[cfg] if-else statements.

src/libsyntax_ext/assert.rs

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use syntax::ast::*;
12+
use syntax::codemap::Spanned;
13+
use syntax::ext::base::*;
14+
use syntax::ext::build::AstBuilder;
15+
use syntax::parse::token;
16+
use syntax::print::pprust;
17+
use syntax::tokenstream::{TokenStream, TokenTree};
18+
use syntax_pos::Span;
19+
20+
pub fn expand_assert<'cx>(
21+
cx: &'cx mut ExtCtxt,
22+
sp: Span,
23+
tts: &[TokenTree],
24+
) -> Box<MacResult + 'cx> {
25+
let mut parser = cx.new_parser_from_tts(tts);
26+
let cond_expr = panictry!(parser.parse_expr());
27+
let custom_msg_args = if parser.eat(&token::Comma) {
28+
let ts = parser.parse_tokens();
29+
if !ts.is_empty() {
30+
Some(ts)
31+
} else {
32+
None
33+
}
34+
} else {
35+
None
36+
};
37+
38+
let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
39+
let panic_call = Mac_ {
40+
path: Path::from_ident(sp, Ident::from_str("panic")),
41+
tts: if let Some(ts) = custom_msg_args {
42+
ts.into()
43+
} else {
44+
let panic_str = format!("assertion failed: {}", pprust::expr_to_string(&cond_expr));
45+
TokenStream::from(token::Literal(
46+
token::Lit::Str_(Name::intern(&panic_str)),
47+
None,
48+
)).into()
49+
},
50+
};
51+
let if_expr = cx.expr_if(
52+
sp,
53+
cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)),
54+
cx.expr(
55+
sp,
56+
ExprKind::Mac(Spanned {
57+
span: sp,
58+
node: panic_call,
59+
}),
60+
),
61+
None,
62+
);
63+
MacEager::expr(if_expr)
64+
}

src/libsyntax_ext/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ extern crate proc_macro;
2626
extern crate rustc_data_structures;
2727
extern crate rustc_errors as errors;
2828

29+
mod assert;
2930
mod asm;
3031
mod cfg;
3132
mod compile_error;
@@ -111,6 +112,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
111112
log_syntax: log_syntax::expand_syntax_ext,
112113
trace_macros: trace_macros::expand_trace_macros,
113114
compile_error: compile_error::expand_compile_error,
115+
assert: assert::expand_assert,
114116
}
115117

116118
// format_args uses `unstable` things internally.

0 commit comments

Comments
 (0)