diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 595059332895d..5e6566b5fcf54 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -32,7 +32,7 @@ struct LoopScope { } pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - body: &hir::Expr) -> CFG { + body: &hir::Body) -> CFG { let mut graph = graph::Graph::new(); let entry = graph.add_node(CFGNodeData::Entry); @@ -43,26 +43,18 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let fn_exit = graph.add_node(CFGNodeData::Exit); let body_exit; - // Find the function this expression is from. - let mut node_id = body.id; - loop { - let node = tcx.hir.get(node_id); - if hir::map::blocks::FnLikeNode::from_node(node).is_some() { - break; - } - let parent = tcx.hir.get_parent_node(node_id); - assert!(node_id != parent); - node_id = parent; - } + // Find the tables for this body. + let owner_def_id = tcx.hir.local_def_id(tcx.hir.body_owner(body.id())); + let tables = tcx.item_tables(owner_def_id); let mut cfg_builder = CFGBuilder { tcx: tcx, - tables: tcx.item_tables(tcx.hir.local_def_id(node_id)), + tables: tables, graph: graph, fn_exit: fn_exit, loop_scopes: Vec::new() }; - body_exit = cfg_builder.expr(body, entry); + body_exit = cfg_builder.expr(&body.value, entry); cfg_builder.add_contained_edge(body_exit, fn_exit); let CFGBuilder {graph, ..} = cfg_builder; CFG {graph: graph, diff --git a/src/librustc/cfg/mod.rs b/src/librustc/cfg/mod.rs index 43434b884c8d4..1473dbb1676f3 100644 --- a/src/librustc/cfg/mod.rs +++ b/src/librustc/cfg/mod.rs @@ -59,7 +59,7 @@ pub type CFGEdge = graph::Edge; impl CFG { pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - body: &hir::Expr) -> CFG { + body: &hir::Body) -> CFG { construct::construct(tcx, body) } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index b31b54a25415a..28b6c7a13f171 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -28,9 +28,6 @@ use rustc::ty::{self, TyCtxt}; use syntax::ast; use syntax_pos::Span; use rustc::hir; -use rustc::hir::Expr; -use rustc::hir::intravisit; -use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; use self::restrictions::RestrictionResult; @@ -514,53 +511,3 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { } } -/// Context used while gathering loans on static initializers -/// -/// This visitor walks static initializer's expressions and makes -/// sure the loans being taken are sound. -struct StaticInitializerCtxt<'a, 'tcx: 'a> { - bccx: &'a BorrowckCtxt<'a, 'tcx>, - body_id: hir::BodyId, -} - -impl<'a, 'tcx> Visitor<'tcx> for StaticInitializerCtxt<'a, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - - fn visit_expr(&mut self, ex: &'tcx Expr) { - if let hir::ExprAddrOf(mutbl, ref base) = ex.node { - let infcx = self.bccx.tcx.borrowck_fake_infer_ctxt(self.body_id); - let mc = mc::MemCategorizationContext::new(&infcx); - let base_cmt = mc.cat_expr(&base).unwrap(); - let borrow_kind = ty::BorrowKind::from_mutbl(mutbl); - // Check that we don't allow borrows of unsafe static items. - let err = check_aliasability(self.bccx, ex.span, - BorrowViolation(euv::AddrOf), - base_cmt, borrow_kind).is_err(); - if err { - return; // reported an error, no sense in reporting more. - } - } - - intravisit::walk_expr(self, ex); - } -} - -pub fn gather_loans_in_static_initializer<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - body: hir::BodyId) { - debug!("gather_loans_in_static_initializer(expr={:?})", body); - - let bccx = &BorrowckCtxt { - tcx: tcx, - tables: None - }; - - let mut sicx = StaticInitializerCtxt { - bccx: bccx, - body_id: body - }; - - let body = sicx.bccx.tcx.hir.body(body); - sicx.visit_body(body); -} diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 9c29cd375ff51..613f28138a519 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -89,7 +89,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowckCtxt<'a, 'tcx> { match item.node { hir::ItemStatic(.., ex) | hir::ItemConst(_, ex) => { - gather_loans::gather_loans_in_static_initializer(self.tcx, ex); + borrowck_fn(self.tcx, ex); } _ => { } } @@ -99,14 +99,14 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowckCtxt<'a, 'tcx> { fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { if let hir::TraitItemKind::Const(_, Some(expr)) = ti.node { - gather_loans::gather_loans_in_static_initializer(self.tcx, expr); + borrowck_fn(self.tcx, expr); } intravisit::walk_trait_item(self, ti); } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { if let hir::ImplItemKind::Const(_, expr) = ii.node { - gather_loans::gather_loans_in_static_initializer(self.tcx, expr); + borrowck_fn(self.tcx, expr); } intravisit::walk_impl_item(self, ii); } @@ -147,7 +147,7 @@ fn borrowck_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, body_id: hir::BodyId) { mir::borrowck_mir(bccx, owner_id, &attributes); } - let cfg = cfg::CFG::new(bccx.tcx, &body.value); + let cfg = cfg::CFG::new(bccx.tcx, &body); let AnalysisData { all_loans, loans: loan_dfcx, move_data: flowed_moves } = diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 7fd4fa44ca45d..9810f121ef2c1 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -24,6 +24,7 @@ #![deny(warnings)] #![feature(box_syntax)] +#![feature(loop_break_value)] #![feature(libc)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 21fe13997b787..54b4ae61ebe43 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -718,13 +718,24 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, mode: PpFlowGraphMode, mut out: W) -> io::Result<()> { - let cfg = match code { - blocks::Code::Expr(expr) => cfg::CFG::new(tcx, expr), - blocks::Code::FnLike(fn_like) => { - let body = tcx.hir.body(fn_like.body()); - cfg::CFG::new(tcx, &body.value) - }, + let body_id = match code { + blocks::Code::Expr(expr) => { + // Find the function this expression is from. + let mut node_id = expr.id; + loop { + let node = tcx.hir.get(node_id); + if let Some(n) = hir::map::blocks::FnLikeNode::from_node(node) { + break n.body(); + } + let parent = tcx.hir.get_parent_node(node_id); + assert!(node_id != parent); + node_id = parent; + } + } + blocks::Code::FnLike(fn_like) => fn_like.body(), }; + let body = tcx.hir.body(body_id); + let cfg = cfg::CFG::new(tcx, &body); let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges; let lcfg = LabelledCFG { hir_map: &tcx.hir, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 1592d17817641..c363810c50d2f 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -712,7 +712,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // to have behaviour like the above, rather than // e.g. accidentally recurring after an assert. - let cfg = cfg::CFG::new(cx.tcx, &body.value); + let cfg = cfg::CFG::new(cx.tcx, &body); let mut work_queue = vec![cfg.entry]; let mut reached_exit_without_self_call = false; diff --git a/src/test/compile-fail/E0017.rs b/src/test/compile-fail/E0017.rs index 44d2f158d20bb..c6bec6090f242 100644 --- a/src/test/compile-fail/E0017.rs +++ b/src/test/compile-fail/E0017.rs @@ -19,8 +19,7 @@ static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 //~| NOTE statics require immutable values //~| ERROR E0017 //~| NOTE statics require immutable values - //~| ERROR E0388 - //~| NOTE cannot write data in a static definition + //~| ERROR cannot borrow static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 //~| NOTE statics require immutable values //~| ERROR E0017 diff --git a/src/test/compile-fail/E0388.rs b/src/test/compile-fail/E0388.rs index 13f2c23d8c4a9..2c88039d373e5 100644 --- a/src/test/compile-fail/E0388.rs +++ b/src/test/compile-fail/E0388.rs @@ -15,7 +15,7 @@ const CR: &'static mut i32 = &mut C; //~ ERROR E0017 //~| ERROR E0017 static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 //~| ERROR E0017 - //~| ERROR E0388 + //~| ERROR cannot borrow static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 //~| ERROR E0017 diff --git a/src/test/compile-fail/borrowck/move-in-static-initializer-issue-38520.rs b/src/test/compile-fail/borrowck/move-in-static-initializer-issue-38520.rs new file mode 100644 index 0000000000000..3c1980e5b366c --- /dev/null +++ b/src/test/compile-fail/borrowck/move-in-static-initializer-issue-38520.rs @@ -0,0 +1,28 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #38520. Check that moves of `Foo` are not +// permitted as `Foo` is not copy (even in a static/const +// initializer). + +#![feature(const_fn)] + +struct Foo(usize); + +const fn get(x: Foo) -> usize { + x.0 +} + +const X: Foo = Foo(22); +static Y: usize = get(*&X); //~ ERROR E0507 +const Z: usize = get(*&X); //~ ERROR E0507 + +fn main() { +} diff --git a/src/test/compile-fail/issue-18118.rs b/src/test/compile-fail/issue-18118.rs index 3afb34f037bcc..35e57dffb6c45 100644 --- a/src/test/compile-fail/issue-18118.rs +++ b/src/test/compile-fail/issue-18118.rs @@ -13,6 +13,6 @@ pub fn main() { //~^ ERROR blocks in constants are limited to items and tail expressions let p = 3; //~^ ERROR blocks in constants are limited to items and tail expressions - &p + &p //~ ERROR `p` does not live long enough }; }