diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 8a206e3d88e..f849580871c 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -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); diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index be227e620b8..c2235591cee 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -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, - used_features: FnvHashMap + used_features: FnvHashMap, + // 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 diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs index a89bc26ec09..c9f13da0633 100644 --- a/src/librustc_front/hir.rs +++ b/src/librustc_front/hir.rs @@ -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)] diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs index 8a8620cbcca..2b63e0615ee 100644 --- a/src/librustc_front/lowering.rs +++ b/src/librustc_front/lowering.rs @@ -749,12 +749,28 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { 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 { }; // 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!()); + // 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>, - expr: P, span: Span) - -> P { - let rules = hir::PushUnsafeBlock(hir::CompilerGenerated); +fn signal_block_expr(lctx: &LoweringContext, stmts: Vec>, expr: P, span: Span, rule: hir::BlockCheckMode) -> P { 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, span: Span) - -> P { - 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), - })) -} diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index db0981728ac..80b0a984681 100644 --- a/src/librustc_front/print/pprust.rs +++ b/src/librustc_front/print/pprust.rs @@ -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))); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 278aa9450ee..0978ea2295b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index abda406dcc8..72d89e246ad 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -70,7 +70,7 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { 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) => { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 18c6d74d62e..49835afbfa5 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -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> {