From 209c701bf9e95542aec69455bc12c7ca295109c4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 6 Jan 2015 11:07:09 -0800 Subject: [PATCH] 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] --- src/libcollections/macros.rs | 1 + src/libstd/lib.rs | 5 +- src/libstd/macros.rs | 76 ++++++++----------- src/libsyntax/ext/base.rs | 11 --- src/libsyntax/ext/bytes.rs | 117 ------------------------------ src/libsyntax/ext/deriving/mod.rs | 10 --- src/libsyntax/ext/fmt.rs | 29 -------- src/libsyntax/ext/source_util.rs | 6 -- src/libsyntax/lib.rs | 2 - 9 files changed, 33 insertions(+), 224 deletions(-) delete mode 100644 src/libsyntax/ext/bytes.rs delete mode 100644 src/libsyntax/ext/fmt.rs diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index 68e2482964dbb..92c71d968ccc5 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -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),*]; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index eef5bdb60eeaa..48c6fe4e4020e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -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; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index befdc156094d1..0594b711ad62e 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -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 diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 52e402689ba77..45ad27e5b8ef6 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -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)); diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs deleted file mode 100644 index 9f225d55b444f..0000000000000 --- a/src/libsyntax/ext/bytes.rs +++ /dev/null @@ -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 or the MIT license -// , 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 { - 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) -} diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 43a0e0606f8bb..ab7ac4d3c3811 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -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)>) { - 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, diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs deleted file mode 100644 index 5352cfaf749b0..0000000000000 --- a/src/libsyntax/ext/fmt.rs +++ /dev/null @@ -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 or the MIT license -// , 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 { - 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)) -} diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 1ba91dd371c60..8021474c1beba 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -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 { - 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 { let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") { diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 9e14f9dd1eaae..a9fc6df535ee6 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -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;