Remove the push_unsafe! and pop_unsafe! macros.

This is a [breaking change].
This commit is contained in:
Nick Cameron 2015-10-12 15:50:12 +13:00
parent 81b3b27cf5
commit d399098fd8
9 changed files with 2 additions and 251 deletions

View File

@ -1489,8 +1489,6 @@ pub fn lower_block_check_mode(_lctx: &LoweringContext, b: &BlockCheckMode) -> hi
match *b {
DefaultBlock => hir::DefaultBlock,
UnsafeBlock(u) => hir::UnsafeBlock(lower_unsafe_source(_lctx, u)),
PushUnsafeBlock(u) => hir::PushUnsafeBlock(lower_unsafe_source(_lctx, u)),
PopUnsafeBlock(u) => hir::PopUnsafeBlock(lower_unsafe_source(_lctx, u)),
}
}

View File

@ -765,8 +765,6 @@ pub type SpannedIdent = Spanned<Ident>;
pub enum BlockCheckMode {
DefaultBlock,
UnsafeBlock(UnsafeSource),
PushUnsafeBlock(UnsafeSource),
PopUnsafeBlock(UnsafeSource),
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]

View File

@ -544,12 +544,6 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
syntax_expanders.insert(intern("cfg"),
builtin_normal_expander(
ext::cfg::expand_cfg));
syntax_expanders.insert(intern("push_unsafe"),
builtin_normal_expander(
ext::pushpop_safe::expand_push_unsafe));
syntax_expanders.insert(intern("pop_unsafe"),
builtin_normal_expander(
ext::pushpop_safe::expand_pop_unsafe));
syntax_expanders.insert(intern("trace_macros"),
builtin_normal_expander(
ext::trace_macros::expand_trace_macros));

View File

@ -1,94 +0,0 @@
// Copyright 2015 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 `push_unsafe!` and
* `pop_unsafe!` macros.
*
* This is a hack to allow a kind of "safety hygiene", where a macro
* can generate code with an interior expression that inherits the
* safety of some outer context.
*
* For example, in:
*
* ```rust
* fn foo() { push_unsafe!( { EXPR_1; pop_unsafe!( EXPR_2 ) } ) }
* ```
*
* the `EXPR_1` is considered to be in an `unsafe` context,
* but `EXPR_2` is considered to be in a "safe" (i.e. checked) context.
*
* For comparison, in:
*
* ```rust
* fn foo() { unsafe { push_unsafe!( { EXPR_1; pop_unsafe!( EXPR_2 ) } ) } }
* ```
*
* both `EXPR_1` and `EXPR_2` are considered to be in `unsafe`
* contexts.
*
*/
use ast;
use codemap::Span;
use ext::base::*;
use ext::base;
use ext::build::AstBuilder;
use feature_gate;
use ptr::P;
enum PushPop { Push, Pop }
pub fn expand_push_unsafe<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> Box<base::MacResult+'cx> {
expand_pushpop_unsafe(cx, sp, tts, PushPop::Push)
}
pub fn expand_pop_unsafe<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> Box<base::MacResult+'cx> {
expand_pushpop_unsafe(cx, sp, tts, PushPop::Pop)
}
fn expand_pushpop_unsafe<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree],
pp: PushPop) -> Box<base::MacResult+'cx> {
feature_gate::check_for_pushpop_syntax(
cx.ecfg.features, &cx.parse_sess.span_diagnostic, sp);
let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
Some(exprs) => exprs.into_iter(),
None => return DummyResult::expr(sp),
};
let expr = match (exprs.next(), exprs.next()) {
(Some(expr), None) => expr,
_ => {
let msg = match pp {
PushPop::Push => "push_unsafe! takes 1 arguments",
PushPop::Pop => "pop_unsafe! takes 1 arguments",
};
cx.span_err(sp, msg);
return DummyResult::expr(sp);
}
};
let source = ast::UnsafeSource::CompilerGenerated;
let check_mode = match pp {
PushPop::Push => ast::BlockCheckMode::PushUnsafeBlock(source),
PushPop::Pop => ast::BlockCheckMode::PopUnsafeBlock(source),
};
MacEager::expr(cx.expr_block(P(ast::Block {
stmts: vec![],
expr: Some(expr),
id: ast::DUMMY_NODE_ID,
rules: check_mode,
span: sp
})))
}

View File

@ -121,7 +121,6 @@ pub mod ext {
pub mod log_syntax;
pub mod mtwt;
pub mod quote;
pub mod pushpop_safe;
pub mod source_util;
pub mod trace_macros;

View File

@ -1671,8 +1671,8 @@ impl<'a> State<'a> {
attrs: &[ast::Attribute],
close_box: bool) -> io::Result<()> {
match blk.rules {
ast::UnsafeBlock(..) | ast::PushUnsafeBlock(..) => try!(self.word_space("unsafe")),
ast::DefaultBlock | ast::PopUnsafeBlock(..) => ()
ast::UnsafeBlock(..) => try!(self.word_space("unsafe")),
ast::DefaultBlock => ()
}
try!(self.maybe_print_comment(blk.span.lo));
try!(self.ann.pre(self, NodeBlock(blk)));

View File

@ -1,14 +0,0 @@
// Copyright 2015 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.
fn main() {
let c = push_unsafe!('c'); //~ ERROR push/pop_unsafe macros are experimental
let c = pop_unsafe!('c'); //~ ERROR push/pop_unsafe macros are experimental
}

View File

@ -1,74 +0,0 @@
// Copyright 2012 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.
// Basic sanity check for `push_unsafe!(EXPR)` and
// `pop_unsafe!(EXPR)`: we can call unsafe code when there are a
// positive number of pushes in the stack, or if we are within a
// normal `unsafe` block, but otherwise cannot.
#![feature(pushpop_unsafe)]
static mut X: i32 = 0;
unsafe fn f() { X += 1; return; }
fn g() { unsafe { X += 1_000; } return; }
fn main() {
push_unsafe!( {
f(); pop_unsafe!({
f() //~ ERROR: call to unsafe function
})
} );
push_unsafe!({
f();
pop_unsafe!({
g();
f(); //~ ERROR: call to unsafe function
})
} );
push_unsafe!({
g(); pop_unsafe!({
unsafe {
f();
}
f(); //~ ERROR: call to unsafe function
})
});
// Note: For implementation simplicity the compiler just
// ICE's if you underflow the push_unsafe stack.
//
// Thus all of the following cases cause an ICE.
//
// (The "ERROR" notes are from an earlier version
// that used saturated arithmetic rather than checked
// arithmetic.)
// pop_unsafe!{ g() };
//
// push_unsafe!({
// pop_unsafe!(pop_unsafe!{ g() })
// });
//
// push_unsafe!({
// g();
// pop_unsafe!(pop_unsafe!({
// f() // ERROR: call to unsafe function
// }))
// });
//
// pop_unsafe!({
// f(); // ERROR: call to unsafe function
// })
}

View File

@ -1,56 +0,0 @@
// Copyright 2015 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.
// Basic sanity check for `push_unsafe!(EXPR)` and
// `pop_unsafe!(EXPR)`: we can call unsafe code when there are a
// positive number of pushes in the stack, or if we are within a
// normal `unsafe` block, but otherwise cannot.
// ignore-pretty because the `push_unsafe!` and `pop_unsafe!` macros
// are not integrated with the pretty-printer.
#![feature(pushpop_unsafe)]
static mut X: i32 = 0;
unsafe fn f() { X += 1; return; }
fn g() { unsafe { X += 1_000; } return; }
fn check_reset_x(x: i32) -> bool {
#![allow(unused_parens)] // dont you judge my style choices!
unsafe {
let ret = (x == X);
X = 0;
ret
}
}
fn main() {
// double-check test infrastructure
assert!(check_reset_x(0));
unsafe { f(); }
assert!(check_reset_x(1));
assert!(check_reset_x(0));
{ g(); }
assert!(check_reset_x(1000));
assert!(check_reset_x(0));
unsafe { f(); g(); g(); }
assert!(check_reset_x(2001));
push_unsafe!( { f(); pop_unsafe!( g() ) } );
assert!(check_reset_x(1_001));
push_unsafe!( { g(); pop_unsafe!( unsafe { f(); f(); } ) } );
assert!(check_reset_x(1_002));
unsafe { push_unsafe!( { f(); pop_unsafe!( { f(); f(); } ) } ); }
assert!(check_reset_x(3));
push_unsafe!( { f(); push_unsafe!( { pop_unsafe!( { f(); f(); f(); } ) } ); } );
assert!(check_reset_x(4));
}