Skip to content

Commit eca6dac

Browse files
committed
rustc: Add a debug_assertions #[cfg] directive
This commit is an implementation of [RFC 563][rfc] which adds a new `cfg(debug_assertions)` directive which is specially recognized and calculated by the compiler. The flag is turned off at any optimization level greater than 1 and may also be explicitly controlled through the `-C debug-assertions` flag. [rfc]: rust-lang/rfcs#563 The `debug_assert!` and `debug_assert_eq!` macros now respect this instead of the `ndebug` variable and `ndebug` no longer holds any meaning to the standard library. Code which was previously relying on `not(ndebug)` to gate expensive code should be updated to rely on `debug_assertions` instead. Closes #22492 [breaking-change]
1 parent 14f0942 commit eca6dac

File tree

9 files changed

+96
-19
lines changed

9 files changed

+96
-19
lines changed

Diff for: mk/tests.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ TEST_SREQ$(1)_T_$(2)_H_$(3) = \
588588

589589
# The tests select when to use debug configuration on their own;
590590
# remove directive, if present, from CFG_RUSTC_FLAGS (issue #7898).
591-
CTEST_RUSTC_FLAGS := $$(subst --cfg ndebug,,$$(CFG_RUSTC_FLAGS))
591+
CTEST_RUSTC_FLAGS := $$(subst -C debug-assertions,,$$(CFG_RUSTC_FLAGS))
592592

593593
# The tests cannot be optimized while the rest of the compiler is optimized, so
594594
# filter out the optimization (if any) from rustc and then figure out if we need

Diff for: src/libcore/macros.rs

+14-10
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,12 @@ macro_rules! assert_eq {
100100
/// This will invoke the `panic!` macro if the provided expression cannot be
101101
/// evaluated to `true` at runtime.
102102
///
103-
/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing
104-
/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for
105-
/// checks that are too expensive to be present in a release build but may be
106-
/// helpful during development.
103+
/// Unlike `assert!`, `debug_assert!` statements are only enabled in non
104+
/// optimized builds by default. An optimized build will omit all
105+
/// `debug_assert!` statements unless `-C debug-assertions` is passed to the
106+
/// compiler. This makes `debug_assert!` useful for checks that are too
107+
/// expensive to be present in a release build but may be helpful during
108+
/// development.
107109
///
108110
/// # Example
109111
///
@@ -125,18 +127,20 @@ macro_rules! assert_eq {
125127
#[macro_export]
126128
#[stable(feature = "rust1", since = "1.0.0")]
127129
macro_rules! debug_assert {
128-
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
130+
($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); })
129131
}
130132

131133
/// Asserts that two expressions are equal to each other, testing equality in
132134
/// both directions.
133135
///
134136
/// On panic, this macro will print the values of the expressions.
135137
///
136-
/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by
137-
/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!`
138-
/// useful for checks that are too expensive to be present in a release build
139-
/// but may be helpful during development.
138+
/// Unlike `assert_eq!`, `debug_assert_eq!` statements are only enabled in non
139+
/// optimized builds by default. An optimized build will omit all
140+
/// `debug_assert_eq!` statements unless `-C debug-assertions` is passed to the
141+
/// compiler. This makes `debug_assert_eq!` useful for checks that are too
142+
/// expensive to be present in a release build but may be helpful during
143+
/// development.
140144
///
141145
/// # Example
142146
///
@@ -147,7 +151,7 @@ macro_rules! debug_assert {
147151
/// ```
148152
#[macro_export]
149153
macro_rules! debug_assert_eq {
150-
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); })
154+
($($arg:tt)*) => (if cfg!(debug_assertions) { assert_eq!($($arg)*); })
151155
}
152156

153157
/// Short circuiting evaluation on Err

Diff for: src/liblog/macros.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ macro_rules! info {
157157
/// ```
158158
#[macro_export]
159159
macro_rules! debug {
160-
($($arg:tt)*) => (if cfg!(not(ndebug)) { log!(::log::DEBUG, $($arg)*) })
160+
($($arg:tt)*) => (if cfg!(debug_assertions) { log!(::log::DEBUG, $($arg)*) })
161161
}
162162

163163
/// A macro to test whether a log level is enabled for the current module.
@@ -192,7 +192,7 @@ macro_rules! debug {
192192
macro_rules! log_enabled {
193193
($lvl:expr) => ({
194194
let lvl = $lvl;
195-
(lvl != ::log::DEBUG || cfg!(not(ndebug))) &&
195+
(lvl != ::log::DEBUG || cfg!(debug_assertions)) &&
196196
lvl <= ::log::log_level() &&
197197
::log::mod_enabled(lvl, module_path!())
198198
})

Diff for: src/librustc/session/config.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ pub struct Options {
8080

8181
pub gc: bool,
8282
pub optimize: OptLevel,
83+
pub debug_assertions: bool,
8384
pub debuginfo: DebugInfoLevel,
8485
pub lint_opts: Vec<(String, lint::Level)>,
8586
pub describe_lints: bool,
@@ -236,7 +237,8 @@ pub fn basic_options() -> Options {
236237
crate_name: None,
237238
alt_std_name: None,
238239
libs: Vec::new(),
239-
unstable_features: UnstableFeatures::Disallow
240+
unstable_features: UnstableFeatures::Disallow,
241+
debug_assertions: true,
240242
}
241243
}
242244

@@ -526,6 +528,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
526528
2 = full debug info with variable and type information"),
527529
opt_level: Option<uint> = (None, parse_opt_uint,
528530
"Optimize with possible levels 0-3"),
531+
debug_assertions: Option<bool> = (None, parse_opt_bool,
532+
"explicitly enable the cfg(debug_assertions) directive"),
529533
}
530534

531535

@@ -619,15 +623,19 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
619623
};
620624

621625
let mk = attr::mk_name_value_item_str;
622-
return vec!(// Target bindings.
626+
let mut ret = vec![ // Target bindings.
623627
attr::mk_word_item(fam.clone()),
624628
mk(InternedString::new("target_os"), intern(os)),
625629
mk(InternedString::new("target_family"), fam),
626630
mk(InternedString::new("target_arch"), intern(arch)),
627631
mk(InternedString::new("target_endian"), intern(end)),
628632
mk(InternedString::new("target_pointer_width"),
629633
intern(wordsz))
630-
);
634+
];
635+
if sess.opts.debug_assertions {
636+
ret.push(attr::mk_word_item(InternedString::new("debug_assertions")));
637+
}
638+
return ret;
631639
}
632640

633641
pub fn append_configuration(cfg: &mut ast::CrateConfig,
@@ -921,6 +929,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
921929
}
922930
}
923931
};
932+
let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == No);
924933
let gc = debugging_opts.gc;
925934
let debuginfo = if matches.opt_present("g") {
926935
if cg.debuginfo.is_some() {
@@ -1062,6 +1071,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
10621071
alt_std_name: None,
10631072
libs: libs,
10641073
unstable_features: get_unstable_features_setting(),
1074+
debug_assertions: debug_assertions,
10651075
}
10661076
}
10671077

Diff for: src/librustc_trans/trans/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3089,7 +3089,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
30893089
let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks {
30903090
v
30913091
} else {
3092-
!attr::contains_name(&krate.config, "ndebug")
3092+
tcx.sess.opts.debug_assertions
30933093
};
30943094

30953095
// Before we touch LLVM, make sure that multithreading is enabled.

Diff for: src/test/run-make/debug-assertions/Makefile

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-include ../tools.mk
2+
3+
all:
4+
$(RUSTC) debug.rs -C debug-assertions=no
5+
$(call RUN,debug) good
6+
$(RUSTC) debug.rs -C opt-level=0
7+
$(call RUN,debug) bad
8+
$(RUSTC) debug.rs -C opt-level=1
9+
$(call RUN,debug) good
10+
$(RUSTC) debug.rs -C opt-level=2
11+
$(call RUN,debug) good
12+
$(RUSTC) debug.rs -C opt-level=3
13+
$(call RUN,debug) good
14+
$(RUSTC) debug.rs -O
15+
$(call RUN,debug) good
16+
$(RUSTC) debug.rs
17+
$(call RUN,debug) bad
18+
$(RUSTC) debug.rs -C debug-assertions=yes -O
19+
$(call RUN,debug) bad
20+
$(RUSTC) debug.rs -C debug-assertions=yes -C opt-level=1
21+
$(call RUN,debug) bad

Diff for: src/test/run-make/debug-assertions/debug.rs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2015 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+
#![deny(warnings)]
12+
13+
use std::env;
14+
use std::thread;
15+
16+
fn main() {
17+
let should_fail = env::args().nth(1) == Some("bad".to_string());
18+
19+
assert_eq!(thread::spawn(debug_assert_eq).join().is_err(), should_fail);
20+
assert_eq!(thread::spawn(debug_assert).join().is_err(), should_fail);
21+
assert_eq!(thread::spawn(overflow).join().is_err(), should_fail);
22+
}
23+
24+
fn debug_assert_eq() {
25+
let mut hit1 = false;
26+
let mut hit2 = false;
27+
debug_assert_eq!({ hit1 = true; 1 }, { hit2 = true; 2 });
28+
assert!(!hit1);
29+
assert!(!hit2);
30+
}
31+
32+
fn debug_assert() {
33+
let mut hit = false;
34+
debug_assert!({ hit = true; false });
35+
assert!(!hit);
36+
}
37+
38+
fn overflow() {
39+
fn add(a: u8, b: u8) -> u8 { a + b }
40+
41+
add(200u8, 200u8);
42+
}

Diff for: src/test/run-pass/conditional-debug-macro-off.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// compile-flags: --cfg ndebug
11+
// compile-flags: -C debug-assertions=no
1212
// exec-env:RUST_LOG=conditional-debug-macro-off=4
1313

1414
#[macro_use]

Diff for: src/test/run-pass/logging-enabled-debug.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// compile-flags:--cfg ndebug
11+
// compile-flags:-C debug-assertions=no
1212
// exec-env:RUST_LOG=logging-enabled-debug=debug
1313

1414
#[macro_use]

0 commit comments

Comments
 (0)