Fix stability
This commit is contained in:
parent
bfffa9ecfc
commit
e0c74868c3
@ -102,7 +102,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
|
||||
&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 @@ impl<'a> State<'a> {
|
||||
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 @@ impl 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 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
|
||||
}
|
||||
|
||||
struct PostExpansionVisitor<'a> {
|
||||
context: &'a Context<'a>
|
||||
context: &'a Context<'a>,
|
||||
}
|
||||
|
||||
impl<'a> PostExpansionVisitor<'a> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user