Skip to content

Commit 73806dd

Browse files
author
Keegan McAllister
committed
Use $crate and macro reexport to reduce duplicated code
Many of libstd's macros are now re-exported from libcore and libcollections. Their libstd definitions have moved to a macros_stage0 module and can disappear after the next snapshot. Where the two crates had already diverged, I took the libstd versions as they're generally newer and better-tested. See e.g. d3c831b, which was a fix to libstd's assert_eq!() that didn't make it into libcore's. Fixes #16806.
1 parent 1c2fddc commit 73806dd

File tree

13 files changed

+913
-244
lines changed

13 files changed

+913
-244
lines changed

src/libcollections/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ pub use string::String;
5151
pub use vec::Vec;
5252
pub use vec_map::VecMap;
5353

54+
// Needed for the vec! macro
55+
pub use alloc::boxed;
56+
5457
mod macros;
5558

5659
pub mod binary_heap;

src/libcollections/macros.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#![macro_escape]
1212

1313
/// Creates a `std::vec::Vec` containing the arguments.
14+
// NOTE: remove after the next snapshot
15+
#[cfg(stage0)]
1416
macro_rules! vec {
1517
($($e:expr),*) => ({
1618
// leading _ to allow empty construction without a warning.
@@ -21,3 +23,13 @@ macro_rules! vec {
2123
($($e:expr),+,) => (vec!($($e),+))
2224
}
2325

26+
/// Creates a `Vec` containing the arguments.
27+
#[cfg(not(stage0))]
28+
#[macro_export]
29+
macro_rules! vec {
30+
($($x:expr),*) => ({
31+
let xs: $crate::boxed::Box<[_]> = box [$($x),*];
32+
$crate::slice::SliceExt::into_vec(xs)
33+
});
34+
($($x:expr,)*) => (vec![$($x),*])
35+
}

src/libcore/fmt/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@ use mem;
2020
use option::Option;
2121
use option::Option::{Some, None};
2222
use ops::{Deref, FnOnce};
23-
use result::Result::{Ok, Err};
23+
use result::Result::Ok;
2424
use result;
2525
use slice::SliceExt;
2626
use slice;
2727
use str::{self, StrExt, Utf8Error};
2828

29+
// NOTE: for old macros; remove after the next snapshot
30+
#[cfg(stage0)] use result::Result::Err;
31+
2932
pub use self::num::radix;
3033
pub use self::num::Radix;
3134
pub use self::num::RadixFmt;

src/libcore/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ mod array;
130130
#[doc(hidden)]
131131
mod core {
132132
pub use panicking;
133+
pub use fmt;
133134
}
134135

135136
#[doc(hidden)]

src/libcore/macros.rs

Lines changed: 177 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,69 +30,224 @@ macro_rules! panic {
3030
});
3131
}
3232

33-
/// Runtime assertion, for details see std::macros
33+
/// Ensure that a boolean expression is `true` at runtime.
34+
///
35+
/// This will invoke the `panic!` macro if the provided expression cannot be
36+
/// evaluated to `true` at runtime.
37+
///
38+
/// # Example
39+
///
40+
/// ```
41+
/// // the panic message for these assertions is the stringified value of the
42+
/// // expression given.
43+
/// assert!(true);
44+
/// # fn some_computation() -> bool { true }
45+
/// assert!(some_computation());
46+
///
47+
/// // assert with a custom message
48+
/// # let x = true;
49+
/// assert!(x, "x wasn't true!");
50+
/// # let a = 3i; let b = 27i;
51+
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
52+
/// ```
3453
#[macro_export]
3554
macro_rules! assert {
3655
($cond:expr) => (
3756
if !$cond {
3857
panic!(concat!("assertion failed: ", stringify!($cond)))
3958
}
4059
);
41-
($cond:expr, $($arg:tt)*) => (
60+
($cond:expr, $($arg:expr),+) => (
4261
if !$cond {
43-
panic!($($arg)*)
62+
panic!($($arg),+)
4463
}
4564
);
4665
}
4766

48-
/// Runtime assertion for equality, for details see std::macros
67+
/// Asserts that two expressions are equal to each other, testing equality in
68+
/// both directions.
69+
///
70+
/// On panic, this macro will print the values of the expressions.
71+
///
72+
/// # Example
73+
///
74+
/// ```
75+
/// let a = 3i;
76+
/// let b = 1i + 2i;
77+
/// assert_eq!(a, b);
78+
/// ```
4979
#[macro_export]
5080
macro_rules! assert_eq {
51-
($cond1:expr, $cond2:expr) => ({
52-
let c1 = $cond1;
53-
let c2 = $cond2;
54-
if c1 != c2 || c2 != c1 {
55-
panic!("expressions not equal, left: {}, right: {}", c1, c2);
81+
($left:expr , $right:expr) => ({
82+
match (&($left), &($right)) {
83+
(left_val, right_val) => {
84+
// check both directions of equality....
85+
if !((*left_val == *right_val) &&
86+
(*right_val == *left_val)) {
87+
panic!("assertion failed: `(left == right) && (right == left)` \
88+
(left: `{}`, right: `{}`)", *left_val, *right_val)
89+
}
90+
}
5691
}
5792
})
5893
}
5994

60-
/// Runtime assertion for equality, only without `--cfg ndebug`
95+
/// Ensure that a boolean expression is `true` at runtime.
96+
///
97+
/// This will invoke the `panic!` macro if the provided expression cannot be
98+
/// evaluated to `true` at runtime.
99+
///
100+
/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing
101+
/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for
102+
/// checks that are too expensive to be present in a release build but may be
103+
/// helpful during development.
104+
///
105+
/// # Example
106+
///
107+
/// ```
108+
/// // the panic message for these assertions is the stringified value of the
109+
/// // expression given.
110+
/// debug_assert!(true);
111+
/// # fn some_expensive_computation() -> bool { true }
112+
/// debug_assert!(some_expensive_computation());
113+
///
114+
/// // assert with a custom message
115+
/// # let x = true;
116+
/// debug_assert!(x, "x wasn't true!");
117+
/// # let a = 3i; let b = 27i;
118+
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
119+
/// ```
120+
#[macro_export]
121+
macro_rules! debug_assert {
122+
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
123+
}
124+
125+
/// Asserts that two expressions are equal to each other, testing equality in
126+
/// both directions.
127+
///
128+
/// On panic, this macro will print the values of the expressions.
129+
///
130+
/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by
131+
/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!`
132+
/// useful for checks that are too expensive to be present in a release build
133+
/// but may be helpful during development.
134+
///
135+
/// # Example
136+
///
137+
/// ```
138+
/// let a = 3i;
139+
/// let b = 1i + 2i;
140+
/// debug_assert_eq!(a, b);
141+
/// ```
61142
#[macro_export]
62143
macro_rules! debug_assert_eq {
63-
($($a:tt)*) => ({
64-
if cfg!(not(ndebug)) {
65-
assert_eq!($($a)*);
66-
}
67-
})
144+
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); })
68145
}
69146

70-
/// Runtime assertion, disableable at compile time with `--cfg ndebug`
147+
#[cfg(stage0)]
71148
#[macro_export]
72-
macro_rules! debug_assert {
73-
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
149+
macro_rules! try {
150+
($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
74151
}
75152

76153
/// Short circuiting evaluation on Err
154+
///
155+
/// `libstd` contains a more general `try!` macro that uses `FromError`.
156+
#[cfg(not(stage0))]
77157
#[macro_export]
78158
macro_rules! try {
79-
($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
159+
($e:expr) => ({
160+
use $crate::result::Result::{Ok, Err};
161+
162+
match $e {
163+
Ok(e) => e,
164+
Err(e) => return Err(e),
165+
}
166+
})
80167
}
81168

82-
/// Writing a formatted string into a writer
169+
/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
170+
/// See `std::fmt` for more information.
171+
///
172+
/// # Example
173+
///
174+
/// ```
175+
/// # #![allow(unused_must_use)]
176+
///
177+
/// let mut w = Vec::new();
178+
/// write!(&mut w, "test");
179+
/// write!(&mut w, "formatted {}", "arguments");
180+
/// ```
83181
#[macro_export]
84182
macro_rules! write {
85183
($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*)))
86184
}
87185

88-
/// Writing a formatted string plus a newline into a writer
186+
/// Equivalent to the `write!` macro, except that a newline is appended after
187+
/// the message is written.
89188
#[macro_export]
189+
#[stable]
90190
macro_rules! writeln {
91191
($dst:expr, $fmt:expr $($arg:tt)*) => (
92192
write!($dst, concat!($fmt, "\n") $($arg)*)
93193
)
94194
}
95195

196+
/// A utility macro for indicating unreachable code.
197+
///
198+
/// This is useful any time that the compiler can't determine that some code is unreachable. For
199+
/// example:
200+
///
201+
/// * Match arms with guard conditions.
202+
/// * Loops that dynamically terminate.
203+
/// * Iterators that dynamically terminate.
204+
///
205+
/// # Panics
206+
///
207+
/// This will always panic.
208+
///
209+
/// # Examples
210+
///
211+
/// Match arms:
212+
///
213+
/// ```rust
214+
/// fn foo(x: Option<int>) {
215+
/// match x {
216+
/// Some(n) if n >= 0 => println!("Some(Non-negative)"),
217+
/// Some(n) if n < 0 => println!("Some(Negative)"),
218+
/// Some(_) => unreachable!(), // compile error if commented out
219+
/// None => println!("None")
220+
/// }
221+
/// }
222+
/// ```
223+
///
224+
/// Iterators:
225+
///
226+
/// ```rust
227+
/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
228+
/// for i in std::iter::count(0_u32, 1) {
229+
/// if 3*i < i { panic!("u32 overflow"); }
230+
/// if x < 3*i { return i-1; }
231+
/// }
232+
/// unreachable!();
233+
/// }
234+
/// ```
96235
#[macro_export]
97-
macro_rules! unreachable { () => (panic!("unreachable code")) }
236+
macro_rules! unreachable {
237+
() => ({
238+
panic!("internal error: entered unreachable code")
239+
});
240+
($msg:expr) => ({
241+
unreachable!("{}", $msg)
242+
});
243+
($fmt:expr, $($arg:tt)*) => ({
244+
panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
245+
});
246+
}
98247

248+
/// A standardised placeholder for marking unfinished code. It panics with the
249+
/// message `"not yet implemented"` when executed.
250+
#[macro_export]
251+
macro_rules! unimplemented {
252+
() => (panic!("not yet implemented"))
253+
}

src/libstd/collections/hash/set.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ use hash::{Hash, Hasher, RandomSipHasher};
2121
use iter::{Iterator, IteratorExt, IteratorCloneExt, FromIterator, Map, Chain, Extend};
2222
use ops::{BitOr, BitAnd, BitXor, Sub};
2323
use option::Option::{Some, None, self};
24-
use result::Result::{Ok, Err};
24+
25+
// NOTE: for old macros; remove after the next snapshot
26+
#[cfg(stage0)] use result::Result::{Ok, Err};
2527

2628
use super::map::{self, HashMap, Keys, INITIAL_CAPACITY};
2729

src/libstd/io/buffered.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@ use iter::ExactSizeIterator;
1818
use ops::Drop;
1919
use option::Option;
2020
use option::Option::{Some, None};
21-
use result::Result::{Ok, Err};
21+
use result::Result::Ok;
2222
use slice::{SliceExt};
2323
use slice;
2424
use vec::Vec;
2525

26+
// NOTE: for old macros; remove after the next snapshot
27+
#[cfg(stage0)] use result::Result::Err;
28+
2629
/// Wraps a Reader and buffers input from it
2730
///
2831
/// It can be excessively inefficient to work directly with a `Reader`. For

src/libstd/lib.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,18 @@
117117

118118
#![reexport_test_harness_main = "test_main"]
119119

120+
#![macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
121+
unreachable, unimplemented, write, writeln, vec)]
122+
120123
#[cfg(test)] #[phase(plugin, link)] extern crate log;
121124

122-
extern crate alloc;
123-
extern crate unicode;
125+
#[phase(plugin, link)]
124126
extern crate core;
127+
#[phase(plugin, link)]
125128
extern crate "collections" as core_collections;
126129
extern crate "rand" as core_rand;
130+
extern crate alloc;
131+
extern crate unicode;
127132
extern crate libc;
128133

129134
// Make std testable by not duplicating lang items. See #2912
@@ -167,7 +172,8 @@ pub use unicode::char;
167172

168173
/* Exported macros */
169174

170-
pub mod macros;
175+
#[cfg(stage0)] pub mod macros_stage0;
176+
#[cfg(not(stage0))] pub mod macros;
171177
pub mod bitflags;
172178

173179
mod rtdeps;

0 commit comments

Comments
 (0)