std: Stablize the macros module
This commit performs a pass over the `std::macros` module, applying stability attributes where necessary. In particular, this audits macros for patterns such as: * Standard use of forward-to-format-args via `$($arg:tt)*` (or `+`) * Prevent macro-defined identifiers from leaking into expression arguments as hygiene is not perfectly implemented. * Wherever possible, `$crate` is used now. Specifically, the following actions were taken: * The `std::macros` module itself is no longer public. * The `panic!` macro is stable * The `assert!` macro is stable * The `assert_eq!` macro is stable * The `debug_assert!` macro is stable * The `debug_assert_eq!` macro is stable * The `unreachable!` macro is stable after removing the extra forms to bring the definition in line with the `unimplemented!` macro. * The `try!` macro is stable * The `vec!` macro is stable [breaking-change]
This commit is contained in:
parent
9e4e524e0e
commit
209c701bf9
@ -10,6 +10,7 @@
|
||||
|
||||
/// Creates a `Vec` containing the arguments.
|
||||
#[macro_export]
|
||||
#[stable]
|
||||
macro_rules! vec {
|
||||
($($x:expr),*) => ({
|
||||
let xs: $crate::boxed::Box<[_]> = box [$($x),*];
|
||||
|
@ -120,8 +120,7 @@
|
||||
extern crate log;
|
||||
|
||||
#[macro_use]
|
||||
#[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
|
||||
unreachable, unimplemented, write, writeln)]
|
||||
#[macro_reexport(write, writeln)]
|
||||
extern crate core;
|
||||
|
||||
#[macro_use]
|
||||
@ -176,7 +175,7 @@ pub use unicode::char;
|
||||
/* Exported macros */
|
||||
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
mod macros;
|
||||
|
||||
#[macro_use]
|
||||
pub mod bitflags;
|
||||
|
@ -36,23 +36,27 @@
|
||||
/// panic!("this is a {} {message}", "fancy", message = "message");
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[stable]
|
||||
macro_rules! panic {
|
||||
() => ({
|
||||
panic!("explicit panic")
|
||||
});
|
||||
($msg:expr) => ({
|
||||
// static requires less code at runtime, more constant data
|
||||
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
|
||||
::std::rt::begin_unwind($msg, &_FILE_LINE)
|
||||
$crate::rt::begin_unwind($msg, {
|
||||
// static requires less code at runtime, more constant data
|
||||
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
|
||||
&_FILE_LINE
|
||||
})
|
||||
});
|
||||
($fmt:expr, $($arg:tt)*) => ({
|
||||
// The leading _'s are to avoid dead code warnings if this is
|
||||
// used inside a dead function. Just `#[allow(dead_code)]` is
|
||||
// insufficient, since the user may have
|
||||
// `#[forbid(dead_code)]` and which cannot be overridden.
|
||||
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
|
||||
::std::rt::begin_unwind_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE)
|
||||
|
||||
($fmt:expr, $($arg:tt)+) => ({
|
||||
$crate::rt::begin_unwind_fmt(format_args!($fmt, $($arg)+), {
|
||||
// The leading _'s are to avoid dead code warnings if this is
|
||||
// used inside a dead function. Just `#[allow(dead_code)]` is
|
||||
// insufficient, since the user may have
|
||||
// `#[forbid(dead_code)]` and which cannot be overridden.
|
||||
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
|
||||
&_FILE_LINE
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@ -77,15 +81,16 @@ macro_rules! panic {
|
||||
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[stable]
|
||||
macro_rules! assert {
|
||||
($cond:expr) => (
|
||||
if !$cond {
|
||||
panic!(concat!("assertion failed: ", stringify!($cond)))
|
||||
}
|
||||
);
|
||||
($cond:expr, $($arg:expr),+) => (
|
||||
($cond:expr, $($arg:tt)+) => (
|
||||
if !$cond {
|
||||
panic!($($arg),+)
|
||||
panic!($($arg)+)
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -103,6 +108,7 @@ macro_rules! assert {
|
||||
/// assert_eq!(a, b);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[stable]
|
||||
macro_rules! assert_eq {
|
||||
($left:expr , $right:expr) => ({
|
||||
match (&($left), &($right)) {
|
||||
@ -144,6 +150,7 @@ macro_rules! assert_eq {
|
||||
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[stable]
|
||||
macro_rules! debug_assert {
|
||||
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
|
||||
}
|
||||
@ -210,6 +217,7 @@ macro_rules! debug_assert_eq {
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[unstable = "relationship with panic is unclear"]
|
||||
macro_rules! unreachable {
|
||||
() => ({
|
||||
panic!("internal error: entered unreachable code")
|
||||
@ -225,6 +233,7 @@ macro_rules! unreachable {
|
||||
/// A standardised placeholder for marking unfinished code. It panics with the
|
||||
/// message `"not yet implemented"` when executed.
|
||||
#[macro_export]
|
||||
#[unstable = "relationship with panic is unclear"]
|
||||
macro_rules! unimplemented {
|
||||
() => (panic!("not yet implemented"))
|
||||
}
|
||||
@ -242,7 +251,7 @@ macro_rules! unimplemented {
|
||||
#[macro_export]
|
||||
#[stable]
|
||||
macro_rules! format {
|
||||
($($arg:tt)*) => (::std::fmt::format(format_args!($($arg)*)))
|
||||
($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*)))
|
||||
}
|
||||
|
||||
/// Equivalent to the `println!` macro except that a newline is not printed at
|
||||
@ -250,7 +259,7 @@ macro_rules! format {
|
||||
#[macro_export]
|
||||
#[stable]
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => (::std::io::stdio::print_args(format_args!($($arg)*)))
|
||||
($($arg:tt)*) => ($crate::io::stdio::print_args(format_args!($($arg)*)))
|
||||
}
|
||||
|
||||
/// Macro for printing to a task's stdout handle.
|
||||
@ -268,20 +277,19 @@ macro_rules! print {
|
||||
#[macro_export]
|
||||
#[stable]
|
||||
macro_rules! println {
|
||||
($($arg:tt)*) => (::std::io::stdio::println_args(format_args!($($arg)*)))
|
||||
($($arg:tt)*) => ($crate::io::stdio::println_args(format_args!($($arg)*)))
|
||||
}
|
||||
|
||||
/// Helper macro for unwrapping `Result` values while returning early with an
|
||||
/// error if the value of the expression is `Err`. For more information, see
|
||||
/// `std::io`.
|
||||
#[macro_export]
|
||||
#[stable]
|
||||
macro_rules! try {
|
||||
($expr:expr) => ({
|
||||
use $crate::result::Result::{Ok, Err};
|
||||
|
||||
match $expr {
|
||||
Ok(val) => val,
|
||||
Err(err) => return Err($crate::error::FromError::from_error(err)),
|
||||
($expr:expr) => (match $expr {
|
||||
$crate::result::Result::Ok(val) => val,
|
||||
$crate::result::Result::Err(err) => {
|
||||
return $crate::result::Result::Err($crate::error::FromError::from_error(err))
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -412,26 +420,6 @@ pub mod builtin {
|
||||
#[macro_export]
|
||||
macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) }
|
||||
|
||||
/// Concatenate literals into a static byte slice.
|
||||
///
|
||||
/// This macro takes any number of comma-separated literal expressions,
|
||||
/// yielding an expression of type `&'static [u8]` which is the
|
||||
/// concatenation (left to right) of all the literals in their byte format.
|
||||
///
|
||||
/// This extension currently only supports string literals, character
|
||||
/// literals, and integers less than 256. The byte slice returned is the
|
||||
/// utf8-encoding of strings and characters.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// let rust = bytes!("r", 'u', "st", 255);
|
||||
/// assert_eq!(rust[1], b'u');
|
||||
/// assert_eq!(rust[4], 255);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! bytes { ($($e:expr),*) => ({ /* compiler built-in */ }) }
|
||||
|
||||
/// Concatenate identifiers into one identifier.
|
||||
///
|
||||
/// This macro takes any number of comma-separated identifiers, and
|
||||
@ -565,10 +553,6 @@ pub mod builtin {
|
||||
#[macro_export]
|
||||
macro_rules! include_bytes { ($file:expr) => ({ /* compiler built-in */ }) }
|
||||
|
||||
/// Deprecated alias for `include_bytes!()`.
|
||||
#[macro_export]
|
||||
macro_rules! include_bin { ($file:expr) => ({ /* compiler built-in */}) }
|
||||
|
||||
/// Expands to a string that represents the current module path.
|
||||
///
|
||||
/// The current module path can be thought of as the hierarchy of modules
|
||||
|
@ -341,9 +341,6 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
|
||||
|
||||
let mut syntax_expanders = SyntaxEnv::new();
|
||||
syntax_expanders.insert(intern("macro_rules"), MacroRulesTT);
|
||||
syntax_expanders.insert(intern("fmt"),
|
||||
builtin_normal_expander(
|
||||
ext::fmt::expand_syntax_ext));
|
||||
syntax_expanders.insert(intern("format_args"),
|
||||
builtin_normal_expander(
|
||||
ext::format::expand_format_args));
|
||||
@ -353,9 +350,6 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
|
||||
syntax_expanders.insert(intern("option_env"),
|
||||
builtin_normal_expander(
|
||||
ext::env::expand_option_env));
|
||||
syntax_expanders.insert(intern("bytes"),
|
||||
builtin_normal_expander(
|
||||
ext::bytes::expand_syntax_ext));
|
||||
syntax_expanders.insert(intern("concat_idents"),
|
||||
builtin_normal_expander(
|
||||
ext::concat_idents::expand_syntax_ext));
|
||||
@ -367,8 +361,6 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
|
||||
ext::log_syntax::expand_syntax_ext));
|
||||
syntax_expanders.insert(intern("derive"),
|
||||
Decorator(box ext::deriving::expand_meta_derive));
|
||||
syntax_expanders.insert(intern("deriving"),
|
||||
Decorator(box ext::deriving::expand_meta_deriving));
|
||||
|
||||
if ecfg.enable_quotes {
|
||||
// Quasi-quoting expanders
|
||||
@ -416,9 +408,6 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
|
||||
syntax_expanders.insert(intern("include_str"),
|
||||
builtin_normal_expander(
|
||||
ext::source_util::expand_include_str));
|
||||
syntax_expanders.insert(intern("include_bin"),
|
||||
builtin_normal_expander(
|
||||
ext::source_util::expand_include_bin));
|
||||
syntax_expanders.insert(intern("include_bytes"),
|
||||
builtin_normal_expander(
|
||||
ext::source_util::expand_include_bytes));
|
||||
|
@ -1,117 +0,0 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
/* The compiler code necessary to support the bytes! extension. */
|
||||
|
||||
use ast;
|
||||
use codemap::Span;
|
||||
use ext::base::*;
|
||||
use ext::base;
|
||||
use ext::build::AstBuilder;
|
||||
use std::ascii::AsciiExt;
|
||||
|
||||
pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[ast::TokenTree])
|
||||
-> Box<base::MacResult+'cx> {
|
||||
cx.span_warn(sp, "`bytes!` is deprecated, use `b\"foo\"` literals instead");
|
||||
cx.parse_sess.span_diagnostic.span_help(sp,
|
||||
"see http://doc.rust-lang.org/reference.html#byte-and-byte-string-literals \
|
||||
for documentation");
|
||||
cx.parse_sess.span_diagnostic.span_help(sp,
|
||||
"see https://github.com/rust-lang/rust/blob/master/src/etc/2014-06-rewrite-bytes-macros.py \
|
||||
for an automated migration");
|
||||
|
||||
// Gather all argument expressions
|
||||
let exprs = match get_exprs_from_tts(cx, sp, tts) {
|
||||
None => return DummyResult::expr(sp),
|
||||
Some(e) => e,
|
||||
};
|
||||
let mut bytes = Vec::new();
|
||||
let mut err = false;
|
||||
|
||||
for expr in exprs.iter() {
|
||||
match expr.node {
|
||||
// expression is a literal
|
||||
ast::ExprLit(ref lit) => match lit.node {
|
||||
// string literal, push each byte to vector expression
|
||||
ast::LitStr(ref s, _) => {
|
||||
for byte in s.get().bytes() {
|
||||
bytes.push(cx.expr_u8(expr.span, byte));
|
||||
}
|
||||
}
|
||||
|
||||
// u8 literal, push to vector expression
|
||||
ast::LitInt(v, ast::UnsignedIntLit(ast::TyU8)) => {
|
||||
if v > 0xFF {
|
||||
cx.span_err(expr.span, "too large u8 literal in bytes!");
|
||||
err = true;
|
||||
} else {
|
||||
bytes.push(cx.expr_u8(expr.span, v as u8));
|
||||
}
|
||||
}
|
||||
|
||||
// integer literal, push to vector expression
|
||||
ast::LitInt(_, ast::UnsuffixedIntLit(ast::Minus)) => {
|
||||
cx.span_err(expr.span, "negative integer literal in bytes!");
|
||||
err = true;
|
||||
}
|
||||
ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => {
|
||||
if v > 0xFF {
|
||||
cx.span_err(expr.span, "too large integer literal in bytes!");
|
||||
err = true;
|
||||
} else {
|
||||
bytes.push(cx.expr_u8(expr.span, v as u8));
|
||||
}
|
||||
}
|
||||
|
||||
// char literal, push to vector expression
|
||||
ast::LitChar(v) => {
|
||||
if v.is_ascii() {
|
||||
bytes.push(cx.expr_u8(expr.span, v as u8));
|
||||
} else {
|
||||
cx.span_err(expr.span, "non-ascii char literal in bytes!");
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
cx.span_err(expr.span, "unsupported literal in bytes!");
|
||||
err = true;
|
||||
}
|
||||
},
|
||||
|
||||
_ => {
|
||||
cx.span_err(expr.span, "non-literal in bytes!");
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For some reason using quote_expr!() here aborts if we threw an error.
|
||||
// I'm assuming that the end of the recursive parse tricks the compiler
|
||||
// into thinking this is a good time to stop. But we'd rather keep going.
|
||||
if err {
|
||||
// Since the compiler will stop after the macro expansion phase anyway, we
|
||||
// don't need type info, so we can just return a DummyResult
|
||||
return DummyResult::expr(sp);
|
||||
}
|
||||
|
||||
let len = bytes.len();
|
||||
let e = cx.expr_vec(sp, bytes);
|
||||
let ty = cx.ty(sp, ast::TyFixedLengthVec(cx.ty_ident(sp, cx.ident_of("u8")),
|
||||
cx.expr_uint(sp, len)));
|
||||
let item = cx.item_static(sp, cx.ident_of("BYTES"), ty, ast::MutImmutable, e);
|
||||
let ret = cx.expr_ident(sp, cx.ident_of("BYTES"));
|
||||
let ret = cx.expr_addr_of(sp, ret);
|
||||
let e = cx.expr_block(cx.block(sp, vec![cx.stmt_item(sp, item)],
|
||||
Some(ret)));
|
||||
MacExpr::new(e)
|
||||
}
|
@ -40,16 +40,6 @@ pub mod totalord;
|
||||
|
||||
pub mod generic;
|
||||
|
||||
pub fn expand_meta_deriving(cx: &mut ExtCtxt,
|
||||
_span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Item,
|
||||
push: Box<FnMut(P<Item>)>) {
|
||||
cx.span_warn(mitem.span, "`deriving` is deprecated; use `derive`");
|
||||
|
||||
expand_meta_derive(cx, _span, mitem, item, push)
|
||||
}
|
||||
|
||||
pub fn expand_meta_derive(cx: &mut ExtCtxt,
|
||||
_span: Span,
|
||||
mitem: &MetaItem,
|
||||
|
@ -1,29 +0,0 @@
|
||||
// Copyright 2012-2013 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.
|
||||
|
||||
/// Deprecated fmt! syntax extension
|
||||
|
||||
use ast;
|
||||
use codemap::Span;
|
||||
use ext::base;
|
||||
use ext::build::AstBuilder;
|
||||
|
||||
|
||||
pub fn expand_syntax_ext(ecx: &mut base::ExtCtxt,
|
||||
sp: Span,
|
||||
_tts: &[ast::TokenTree])
|
||||
-> Box<base::MacResult+'static> {
|
||||
ecx.span_err(sp, "`fmt!` is deprecated, use `format!` instead");
|
||||
ecx.parse_sess.span_diagnostic.span_note(sp,
|
||||
"see http://doc.rust-lang.org/std/fmt/ \
|
||||
for documentation");
|
||||
|
||||
base::MacExpr::new(ecx.expr_uint(sp, 2))
|
||||
}
|
@ -161,12 +161,6 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> Box<base::MacResult+'static> {
|
||||
cx.span_warn(sp, "include_bin! is deprecated; use include_bytes! instead");
|
||||
expand_include_bytes(cx, sp, tts)
|
||||
}
|
||||
|
||||
pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> Box<base::MacResult+'static> {
|
||||
let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
|
||||
|
@ -81,7 +81,6 @@ pub mod ext {
|
||||
pub mod asm;
|
||||
pub mod base;
|
||||
pub mod build;
|
||||
pub mod bytes;
|
||||
pub mod cfg;
|
||||
pub mod cfg_attr;
|
||||
pub mod concat;
|
||||
@ -89,7 +88,6 @@ pub mod ext {
|
||||
pub mod deriving;
|
||||
pub mod env;
|
||||
pub mod expand;
|
||||
pub mod fmt;
|
||||
pub mod format;
|
||||
pub mod log_syntax;
|
||||
pub mod mtwt;
|
||||
|
Loading…
x
Reference in New Issue
Block a user