提交 73806ddd 编写于 作者: K Keegan McAllister

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. d3c831ba, which was a fix to
libstd's assert_eq!() that didn't make it into libcore's.

Fixes #16806.
上级 1c2fddc6
......@@ -51,6 +51,9 @@
pub use vec::Vec;
pub use vec_map::VecMap;
// Needed for the vec! macro
pub use alloc::boxed;
mod macros;
pub mod binary_heap;
......
......@@ -11,6 +11,8 @@
#![macro_escape]
/// Creates a `std::vec::Vec` containing the arguments.
// NOTE: remove after the next snapshot
#[cfg(stage0)]
macro_rules! vec {
($($e:expr),*) => ({
// leading _ to allow empty construction without a warning.
......@@ -21,3 +23,13 @@
($($e:expr),+,) => (vec!($($e),+))
}
/// Creates a `Vec` containing the arguments.
#[cfg(not(stage0))]
#[macro_export]
macro_rules! vec {
($($x:expr),*) => ({
let xs: $crate::boxed::Box<[_]> = box [$($x),*];
$crate::slice::SliceExt::into_vec(xs)
});
($($x:expr,)*) => (vec![$($x),*])
}
......@@ -20,12 +20,15 @@
use option::Option;
use option::Option::{Some, None};
use ops::{Deref, FnOnce};
use result::Result::{Ok, Err};
use result::Result::Ok;
use result;
use slice::SliceExt;
use slice;
use str::{self, StrExt, Utf8Error};
// NOTE: for old macros; remove after the next snapshot
#[cfg(stage0)] use result::Result::Err;
pub use self::num::radix;
pub use self::num::Radix;
pub use self::num::RadixFmt;
......
......@@ -130,6 +130,7 @@
#[doc(hidden)]
mod core {
pub use panicking;
pub use fmt;
}
#[doc(hidden)]
......
......@@ -30,7 +30,26 @@
});
}
/// Runtime assertion, for details see std::macros
/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// # Example
///
/// ```
/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// assert!(true);
/// # fn some_computation() -> bool { true }
/// assert!(some_computation());
///
/// // assert with a custom message
/// # let x = true;
/// assert!(x, "x wasn't true!");
/// # let a = 3i; let b = 27i;
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
macro_rules! assert {
($cond:expr) => (
......@@ -38,61 +57,197 @@
panic!(concat!("assertion failed: ", stringify!($cond)))
}
);
($cond:expr, $($arg:tt)*) => (
($cond:expr, $($arg:expr),+) => (
if !$cond {
panic!($($arg)*)
panic!($($arg),+)
}
);
}
/// Runtime assertion for equality, for details see std::macros
/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
///
/// On panic, this macro will print the values of the expressions.
///
/// # Example
///
/// ```
/// let a = 3i;
/// let b = 1i + 2i;
/// assert_eq!(a, b);
/// ```
#[macro_export]
macro_rules! assert_eq {
($cond1:expr, $cond2:expr) => ({
let c1 = $cond1;
let c2 = $cond2;
if c1 != c2 || c2 != c1 {
panic!("expressions not equal, left: {}, right: {}", c1, c2);
($left:expr , $right:expr) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
// check both directions of equality....
if !((*left_val == *right_val) &&
(*right_val == *left_val)) {
panic!("assertion failed: `(left == right) && (right == left)` \
(left: `{}`, right: `{}`)", *left_val, *right_val)
}
}
}
})
}
/// Runtime assertion for equality, only without `--cfg ndebug`
/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing
/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for
/// checks that are too expensive to be present in a release build but may be
/// helpful during development.
///
/// # Example
///
/// ```
/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// debug_assert!(true);
/// # fn some_expensive_computation() -> bool { true }
/// debug_assert!(some_expensive_computation());
///
/// // assert with a custom message
/// # let x = true;
/// debug_assert!(x, "x wasn't true!");
/// # let a = 3i; let b = 27i;
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
macro_rules! debug_assert {
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
}
/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
///
/// On panic, this macro will print the values of the expressions.
///
/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by
/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!`
/// useful for checks that are too expensive to be present in a release build
/// but may be helpful during development.
///
/// # Example
///
/// ```
/// let a = 3i;
/// let b = 1i + 2i;
/// debug_assert_eq!(a, b);
/// ```
#[macro_export]
macro_rules! debug_assert_eq {
($($a:tt)*) => ({
if cfg!(not(ndebug)) {
assert_eq!($($a)*);
}
})
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); })
}
/// Runtime assertion, disableable at compile time with `--cfg ndebug`
#[cfg(stage0)]
#[macro_export]
macro_rules! debug_assert {
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
macro_rules! try {
($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
}
/// Short circuiting evaluation on Err
///
/// `libstd` contains a more general `try!` macro that uses `FromError`.
#[cfg(not(stage0))]
#[macro_export]
macro_rules! try {
($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
($e:expr) => ({
use $crate::result::Result::{Ok, Err};
match $e {
Ok(e) => e,
Err(e) => return Err(e),
}
})
}
/// Writing a formatted string into a writer
/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
/// See `std::fmt` for more information.
///
/// # Example
///
/// ```
/// # #![allow(unused_must_use)]
///
/// let mut w = Vec::new();
/// write!(&mut w, "test");
/// write!(&mut w, "formatted {}", "arguments");
/// ```
#[macro_export]
macro_rules! write {
($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*)))
}
/// Writing a formatted string plus a newline into a writer
/// Equivalent to the `write!` macro, except that a newline is appended after
/// the message is written.
#[macro_export]
#[stable]
macro_rules! writeln {
($dst:expr, $fmt:expr $($arg:tt)*) => (
write!($dst, concat!($fmt, "\n") $($arg)*)
)
}
/// A utility macro for indicating unreachable code.
///
/// This is useful any time that the compiler can't determine that some code is unreachable. For
/// example:
///
/// * Match arms with guard conditions.
/// * Loops that dynamically terminate.
/// * Iterators that dynamically terminate.
///
/// # Panics
///
/// This will always panic.
///
/// # Examples
///
/// Match arms:
///
/// ```rust
/// fn foo(x: Option<int>) {
/// match x {
/// Some(n) if n >= 0 => println!("Some(Non-negative)"),
/// Some(n) if n < 0 => println!("Some(Negative)"),
/// Some(_) => unreachable!(), // compile error if commented out
/// None => println!("None")
/// }
/// }
/// ```
///
/// Iterators:
///
/// ```rust
/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
/// for i in std::iter::count(0_u32, 1) {
/// if 3*i < i { panic!("u32 overflow"); }
/// if x < 3*i { return i-1; }
/// }
/// unreachable!();
/// }
/// ```
#[macro_export]
macro_rules! unreachable { () => (panic!("unreachable code")) }
macro_rules! unreachable {
() => ({
panic!("internal error: entered unreachable code")
});
($msg:expr) => ({
unreachable!("{}", $msg)
});
($fmt:expr, $($arg:tt)*) => ({
panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
});
}
/// A standardised placeholder for marking unfinished code. It panics with the
/// message `"not yet implemented"` when executed.
#[macro_export]
macro_rules! unimplemented {
() => (panic!("not yet implemented"))
}
......@@ -21,7 +21,9 @@
use iter::{Iterator, IteratorExt, IteratorCloneExt, FromIterator, Map, Chain, Extend};
use ops::{BitOr, BitAnd, BitXor, Sub};
use option::Option::{Some, None, self};
use result::Result::{Ok, Err};
// NOTE: for old macros; remove after the next snapshot
#[cfg(stage0)] use result::Result::{Ok, Err};
use super::map::{self, HashMap, Keys, INITIAL_CAPACITY};
......
......@@ -18,11 +18,14 @@
use ops::Drop;
use option::Option;
use option::Option::{Some, None};
use result::Result::{Ok, Err};
use result::Result::Ok;
use slice::{SliceExt};
use slice;
use vec::Vec;
// NOTE: for old macros; remove after the next snapshot
#[cfg(stage0)] use result::Result::Err;
/// Wraps a Reader and buffers input from it
///
/// It can be excessively inefficient to work directly with a `Reader`. For
......
......@@ -117,13 +117,18 @@
#![reexport_test_harness_main = "test_main"]
#![macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
unreachable, unimplemented, write, writeln, vec)]
#[cfg(test)] #[phase(plugin, link)] extern crate log;
extern crate alloc;
extern crate unicode;
#[phase(plugin, link)]
extern crate core;
#[phase(plugin, link)]
extern crate "collections" as core_collections;
extern crate "rand" as core_rand;
extern crate alloc;
extern crate unicode;
extern crate libc;
// Make std testable by not duplicating lang items. See #2912
......@@ -167,7 +172,8 @@
/* Exported macros */
pub mod macros;
#[cfg(stage0)] pub mod macros_stage0;
#[cfg(not(stage0))] pub mod macros;
pub mod bitflags;
mod rtdeps;
......
......@@ -57,179 +57,6 @@
});
}
/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// # Example
///
/// ```
/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// assert!(true);
/// # fn some_computation() -> bool { true }
/// assert!(some_computation());
///
/// // assert with a custom message
/// # let x = true;
/// assert!(x, "x wasn't true!");
/// # let a = 3i; let b = 27i;
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
macro_rules! assert {
($cond:expr) => (
if !$cond {
panic!(concat!("assertion failed: ", stringify!($cond)))
}
);
($cond:expr, $($arg:expr),+) => (
if !$cond {
panic!($($arg),+)
}
);
}
/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
///
/// On panic, this macro will print the values of the expressions.
///
/// # Example
///
/// ```
/// let a = 3i;
/// let b = 1i + 2i;
/// assert_eq!(a, b);
/// ```
#[macro_export]
macro_rules! assert_eq {
($left:expr , $right:expr) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
// check both directions of equality....
if !((*left_val == *right_val) &&
(*right_val == *left_val)) {
panic!("assertion failed: `(left == right) && (right == left)` \
(left: `{}`, right: `{}`)", *left_val, *right_val)
}
}
}
})
}
/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing
/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for
/// checks that are too expensive to be present in a release build but may be
/// helpful during development.
///
/// # Example
///
/// ```
/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// debug_assert!(true);
/// # fn some_expensive_computation() -> bool { true }
/// debug_assert!(some_expensive_computation());
///
/// // assert with a custom message
/// # let x = true;
/// debug_assert!(x, "x wasn't true!");
/// # let a = 3i; let b = 27i;
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
macro_rules! debug_assert {
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
}
/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
///
/// On panic, this macro will print the values of the expressions.
///
/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by
/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!`
/// useful for checks that are too expensive to be present in a release build
/// but may be helpful during development.
///
/// # Example
///
/// ```
/// let a = 3i;
/// let b = 1i + 2i;
/// debug_assert_eq!(a, b);
/// ```
#[macro_export]
macro_rules! debug_assert_eq {
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); })
}
/// A utility macro for indicating unreachable code.
///
/// This is useful any time that the compiler can't determine that some code is unreachable. For
/// example:
///
/// * Match arms with guard conditions.
/// * Loops that dynamically terminate.
/// * Iterators that dynamically terminate.
///
/// # Panics
///
/// This will always panic.
///
/// # Examples
///
/// Match arms:
///
/// ```rust
/// fn foo(x: Option<int>) {
/// match x {
/// Some(n) if n >= 0 => println!("Some(Non-negative)"),
/// Some(n) if n < 0 => println!("Some(Negative)"),
/// Some(_) => unreachable!(), // compile error if commented out
/// None => println!("None")
/// }
/// }
/// ```
///
/// Iterators:
///
/// ```rust
/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
/// for i in std::iter::count(0_u32, 1) {
/// if 3*i < i { panic!("u32 overflow"); }
/// if x < 3*i { return i-1; }
/// }
/// unreachable!();
/// }
/// ```
#[macro_export]
macro_rules! unreachable {
() => ({
panic!("internal error: entered unreachable code")
});
($msg:expr) => ({
unreachable!("{}", $msg)
});
($fmt:expr, $($arg:tt)*) => ({
panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
});
}
/// A standardised placeholder for marking unfinished code. It panics with the
/// message `"not yet implemented"` when executed.
#[macro_export]
macro_rules! unimplemented {
() => (panic!("not yet implemented"))
}
/// Use the syntax described in `std::fmt` to create a value of type `String`.
/// See `std::fmt` for more information.
///
......@@ -246,34 +73,6 @@
($($arg:tt)*) => (::std::fmt::format(format_args!($($arg)*)))
}
/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
/// See `std::fmt` for more information.
///
/// # Example
///
/// ```
/// # #![allow(unused_must_use)]
///
/// let mut w = Vec::new();
/// write!(&mut w, "test");
/// write!(&mut w, "formatted {}", "arguments");
/// ```
#[macro_export]
#[stable]
macro_rules! write {
($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*)))
}
/// Equivalent to the `write!` macro, except that a newline is appended after
/// the message is written.
#[macro_export]
#[stable]
macro_rules! writeln {
($dst:expr, $fmt:expr $($arg:tt)*) => (
write!($dst, concat!($fmt, "\n") $($arg)*)
)
}
/// Equivalent to the `println!` macro except that a newline is not printed at
/// the end of the message.
#[macro_export]
......@@ -306,23 +105,15 @@
#[macro_export]
macro_rules! try {
($expr:expr) => ({
use $crate::result::Result::{Ok, Err};
match $expr {
Ok(val) => val,
Err(err) => return Err(::std::error::FromError::from_error(err))
Err(err) => return Err($crate::error::FromError::from_error(err)),
}
})
}
/// Create a `std::vec::Vec` containing the arguments.
#[macro_export]
macro_rules! vec {
($($x:expr),*) => ({
let xs: ::std::boxed::Box<[_]> = box [$($x),*];
::std::slice::SliceExt::into_vec(xs)
});
($($x:expr,)*) => (vec![$($x),*])
}
/// A macro to select an event from a number of receivers.
///
/// This macro is used to wait for the first event to occur on a number of
......@@ -358,7 +149,7 @@
(
$($name:pat = $rx:ident.$meth:ident() => $code:expr),+
) => ({
use std::sync::mpsc::Select;
use $crate::sync::mpsc::Select;
let sel = Select::new();
$( let mut $rx = sel.handle(&$rx); )+
unsafe {
......
此差异已折叠。
......@@ -23,11 +23,14 @@ mod imp {
use path::Path;
use rand::Rng;
use rand::reader::ReaderRng;
use result::Result::{Ok, Err};
use result::Result::Ok;
use slice::SliceExt;
use mem;
use os::errno;
// NOTE: for old macros; remove after the next snapshot
#[cfg(stage0)] use result::Result::Err;
#[cfg(all(target_os = "linux",
any(target_arch = "x86_64",
target_arch = "x86",
......
......@@ -17,8 +17,10 @@
use option::Option;
use option::Option::{Some, None};
use num::Int;
use result::Result;
use result::Result::{Ok, Err};
use result::Result::Ok;
// NOTE: for old macros; remove after the next snapshot
#[cfg(stage0)] use result::Result::Err;
/// The number of nanoseconds in a microsecond.
const NANOS_PER_MICRO: i32 = 1000;
......
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(phase, lang_items)]
#![no_std]
#[phase(plugin, link)]
extern crate core;
extern crate libc;
#[phase(plugin, link)]
extern crate collections;
use core::option::Option::Some;
use core::slice::SliceExt;
use collections::vec::Vec;
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
// Issue #16806
#[start]
fn start(_argc: int, _argv: *const *const u8) -> int {
let x: Vec<u8> = vec![0, 1, 2];
match x.last() {
Some(&2) => (),
_ => panic!(),
}
0
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册