提交 e0c74868 编写于 作者: N Nick Cameron

Fix stability

上级 bfffa9ec
......@@ -102,7 +102,6 @@ fn visit_fn(&mut self, fn_kind: FnKind<'v>, fn_decl: &'v hir::FnDecl,
fn visit_block(&mut self, block: &hir::Block) {
let old_unsafe_context = self.unsafe_context;
match block.rules {
hir::DefaultBlock => {}
hir::UnsafeBlock(source) => {
// By default only the outermost `unsafe` block is
// "used" and so nested unsafe blocks are pointless
......@@ -131,6 +130,7 @@ fn visit_block(&mut self, block: &hir::Block) {
self.unsafe_context.push_unsafe_count =
self.unsafe_context.push_unsafe_count.checked_sub(1).unwrap();
}
hir::DefaultBlock | hir::PushUnstableBlock | hir:: PopUnstableBlock => {}
}
visit::walk_block(self, block);
......
......@@ -270,7 +270,8 @@ pub fn check_unstable_api_usage(tcx: &ty::ctxt)
let mut checker = Checker {
tcx: tcx,
active_features: active_features,
used_features: FnvHashMap()
used_features: FnvHashMap(),
in_skip_block: 0,
};
let krate = tcx.map.krate();
......@@ -283,14 +284,23 @@ pub fn check_unstable_api_usage(tcx: &ty::ctxt)
struct Checker<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>,
active_features: FnvHashSet<InternedString>,
used_features: FnvHashMap<InternedString, attr::StabilityLevel>
used_features: FnvHashMap<InternedString, attr::StabilityLevel>,
// Within a block where feature gate checking can be skipped.
in_skip_block: u32,
}
impl<'a, 'tcx> Checker<'a, 'tcx> {
fn check(&mut self, id: DefId, span: Span, stab: &Option<&Stability>) {
// Only the cross-crate scenario matters when checking unstable APIs
let cross_crate = !id.is_local();
if !cross_crate { return }
if !cross_crate {
return
}
// We don't need to check for stability - presumably compiler generated code.
if self.in_skip_block > 0 {
return;
}
match *stab {
Some(&Stability { level: attr::Unstable, ref feature, ref reason, issue, .. }) => {
......@@ -369,6 +379,21 @@ fn visit_pat(&mut self, pat: &hir::Pat) {
&mut |id, sp, stab| self.check(id, sp, stab));
visit::walk_pat(self, pat)
}
fn visit_block(&mut self, b: &hir::Block) {
let old_skip_count = self.in_skip_block;
match b.rules {
hir::BlockCheckMode::PushUnstableBlock => {
self.in_skip_block += 1;
}
hir::BlockCheckMode::PopUnstableBlock => {
self.in_skip_block = self.in_skip_block.checked_sub(1).unwrap();
}
_ => {}
}
visit::walk_block(self, b);
self.in_skip_block = old_skip_count;
}
}
/// Helper for discovering nodes to check for stability
......
......@@ -574,6 +574,9 @@ pub enum BlockCheckMode {
UnsafeBlock(UnsafeSource),
PushUnsafeBlock(UnsafeSource),
PopUnsafeBlock(UnsafeSource),
// Within this block (but outside a PopUnstableBlock), we suspend checking of stability.
PushUnstableBlock,
PopUnstableBlock,
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
......
......@@ -749,12 +749,28 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
P(hir::Expr {
id: e.id,
node: match e.node {
// Issue #22181:
// Eventually a desugaring for `box EXPR`
// (similar to the desugaring above for `in PLACE BLOCK`)
// should go here, desugaring
//
// to:
//
// let mut place = BoxPlace::make_place();
// let raw_place = Place::pointer(&mut place);
// let value = $value;
// unsafe {
// ::std::ptr::write(raw_place, value);
// Boxed::finalize(place)
// }
//
// But for now there are type-inference issues doing that.
ExprBox(ref e) => {
hir::ExprBox(lower_expr(lctx, e))
}
// Desugar ExprBox: `in (PLACE) EXPR`
ExprInPlace(Some(ref placer), ref value_expr) => {
ExprInPlace(ref placer, ref value_expr) => {
// to:
//
// let p = PLACE;
......@@ -810,23 +826,43 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
};
// pop_unsafe!(EXPR));
let pop_unsafe_expr = pop_unsafe_expr(lctx, value_expr, e.span);
let pop_unsafe_expr =
signal_block_expr(lctx,
vec![],
signal_block_expr(lctx,
vec![],
value_expr,
e.span,
hir::PopUnstableBlock),
e.span,
hir::PopUnsafeBlock(hir::CompilerGenerated));
// push_unsafe!({
// ptr::write(p_ptr, pop_unsafe!(<value_expr>));
// std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
// InPlace::finalize(place)
// })
let expr = {
let call_move_val_init = hir::StmtSemi(make_call(
lctx, &move_val_init, vec![expr_ident(lctx, e.span, p_ptr_ident), pop_unsafe_expr]), lctx.next_id());
let call_move_val_init =
hir::StmtSemi(make_call(lctx,
&move_val_init,
vec![expr_ident(lctx, e.span, p_ptr_ident),
pop_unsafe_expr]),
lctx.next_id());
let call_move_val_init = respan(e.span, call_move_val_init);
let call = make_call(lctx, &inplace_finalize, vec![expr_ident(lctx, e.span, agent_ident)]);
Some(push_unsafe_expr(lctx, vec![P(call_move_val_init)], call, e.span))
signal_block_expr(lctx,
vec![P(call_move_val_init)],
call,
e.span,
hir::PushUnsafeBlock(hir::CompilerGenerated))
};
let block = block_all(lctx, e.span, vec![s1, s2, s3], expr);
return expr_block(lctx, block);
return signal_block_expr(lctx,
vec![s1, s2, s3],
expr,
e.span,
hir::PushUnstableBlock);
}
ExprVec(ref exprs) => {
......@@ -1475,21 +1511,9 @@ fn core_path(lctx: &LoweringContext, span: Span, components: &[&str]) -> hir::Pa
path_global(span, idents)
}
fn push_unsafe_expr(lctx: &LoweringContext, stmts: Vec<P<hir::Stmt>>,
expr: P<hir::Expr>, span: Span)
-> P<hir::Expr> {
let rules = hir::PushUnsafeBlock(hir::CompilerGenerated);
fn signal_block_expr(lctx: &LoweringContext, stmts: Vec<P<hir::Stmt>>, expr: P<hir::Expr>, span: Span, rule: hir::BlockCheckMode) -> P<hir::Expr> {
expr_block(lctx, P(hir::Block {
rules: rules, span: span, id: lctx.next_id(),
rules: rule, span: span, id: lctx.next_id(),
stmts: stmts, expr: Some(expr),
}))
}
fn pop_unsafe_expr(lctx: &LoweringContext, expr: P<hir::Expr>, span: Span)
-> P<hir::Expr> {
let rules = hir::PopUnsafeBlock(hir::CompilerGenerated);
expr_block(lctx, P(hir::Block {
rules: rules, span: span, id: lctx.next_id(),
stmts: vec![], expr: Some(expr),
}))
}
......@@ -1089,8 +1089,12 @@ pub fn print_block_maybe_unclosed(&mut self,
close_box: bool)
-> io::Result<()> {
match blk.rules {
hir::UnsafeBlock(..) | hir::PushUnsafeBlock(..) => try!(self.word_space("unsafe")),
hir::DefaultBlock | hir::PopUnsafeBlock(..) => (),
hir::UnsafeBlock(..) => try!(self.word_space("unsafe")),
hir::PushUnsafeBlock(..) => try!(self.word_space("push_unsafe")),
hir::PopUnsafeBlock(..) => try!(self.word_space("pop_unsafe")),
hir::PushUnstableBlock => try!(self.word_space("push_unstable")),
hir::PopUnstableBlock => try!(self.word_space("pop_unstable")),
hir::DefaultBlock => (),
}
try!(self.maybe_print_comment(blk.span.lo));
try!(self.ann.pre(self, NodeBlock(blk)));
......
......@@ -269,7 +269,7 @@ pub fn recurse(&mut self, blk: &hir::Block) -> UnsafetyState {
(unsafety, blk.id, self.unsafe_push_count.checked_sub(1).unwrap()),
hir::UnsafeBlock(..) =>
(hir::Unsafety::Unsafe, blk.id, self.unsafe_push_count),
hir::DefaultBlock =>
hir::DefaultBlock | hir::PushUnstableBlock | hir:: PopUnstableBlock =>
(unsafety, self.def, self.unsafe_push_count),
};
UnsafetyState{ def: def,
......
......@@ -70,7 +70,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
let placer = fld.fold_expr(placer);
let value_expr = fld.fold_expr(value_expr);
fld.cx.expr(span, ast::ExprBox(Some(placer), value_expr))
fld.cx.expr(span, ast::ExprInPlace(placer, value_expr))
}
ast::ExprWhile(cond, body, opt_ident) => {
......
......@@ -726,7 +726,7 @@ fn visit_expr(&mut self, e: &ast::Expr) {
}
struct PostExpansionVisitor<'a> {
context: &'a Context<'a>
context: &'a Context<'a>,
}
impl<'a> PostExpansionVisitor<'a> {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册