From ff0830d74985246c2e2bbd28e7d8c0ef072e2458 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 26 Oct 2016 02:27:14 +0300 Subject: [PATCH] rustc: use an Expr instead of a Block for function bodies. --- src/librustc/cfg/construct.rs | 12 +- src/librustc/cfg/mod.rs | 4 +- src/librustc/diagnostics.rs | 114 ------------------ src/librustc/hir/intravisit.rs | 8 +- src/librustc/hir/lowering.rs | 13 +- src/librustc/hir/map/blocks.rs | 43 +++---- src/librustc/hir/map/collector.rs | 2 +- src/librustc/hir/mod.rs | 8 +- src/librustc/hir/print.rs | 34 ++---- src/librustc/lint/context.rs | 2 +- src/librustc/lint/mod.rs | 4 +- src/librustc/middle/dataflow.rs | 8 +- src/librustc/middle/dead.rs | 8 +- src/librustc/middle/effect.rs | 2 +- src/librustc/middle/expr_use_visitor.rs | 6 +- src/librustc/middle/intrinsicck.rs | 2 +- src/librustc/middle/liveness.rs | 93 ++++---------- src/librustc/middle/reachable.rs | 12 +- src/librustc/middle/region.rs | 13 +- src/librustc/middle/resolve_lifetime.rs | 10 +- src/librustc_borrowck/borrowck/check_loans.rs | 2 +- .../borrowck/gather_loans/mod.rs | 2 +- src/librustc_borrowck/borrowck/mir/mod.rs | 2 +- src/librustc_borrowck/borrowck/mod.rs | 12 +- src/librustc_borrowck/borrowck/move_data.rs | 2 +- src/librustc_const_eval/check_match.rs | 4 +- src/librustc_const_eval/eval.rs | 3 +- src/librustc_driver/pretty.rs | 11 +- src/librustc_lint/bad_style.rs | 2 +- src/librustc_lint/builtin.rs | 4 +- src/librustc_lint/unused.rs | 2 +- src/librustc_mir/build/mod.rs | 22 ++-- src/librustc_mir/mir_map.rs | 2 +- src/librustc_passes/consts.rs | 4 +- src/librustc_passes/hir_stats.rs | 2 +- src/librustc_passes/loops.rs | 2 +- src/librustc_passes/rvalues.rs | 2 +- src/librustc_typeck/check/closure.rs | 4 +- src/librustc_typeck/check/mod.rs | 20 ++- src/librustc_typeck/check/regionck.rs | 14 +-- src/librustc_typeck/check/upvar.rs | 19 +-- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/check/writeback.rs | 4 +- 43 files changed, 169 insertions(+), 372 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index a2fc6e044e74..22c7d14be29d 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -33,16 +33,16 @@ struct LoopScope { } pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - blk: &hir::Block) -> CFG { + body: &hir::Expr) -> CFG { let mut graph = graph::Graph::new(); let entry = graph.add_node(CFGNodeData::Entry); // `fn_exit` is target of return exprs, which lies somewhere - // outside input `blk`. (Distinguishing `fn_exit` and `block_exit` + // outside input `body`. (Distinguishing `fn_exit` and `body_exit` // also resolves chicken-and-egg problem that arises if you try to - // have return exprs jump to `block_exit` during construction.) + // have return exprs jump to `body_exit` during construction.) let fn_exit = graph.add_node(CFGNodeData::Exit); - let block_exit; + let body_exit; let mut cfg_builder = CFGBuilder { graph: graph, @@ -50,8 +50,8 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: tcx, loop_scopes: Vec::new() }; - block_exit = cfg_builder.block(blk, entry); - cfg_builder.add_contained_edge(block_exit, fn_exit); + body_exit = cfg_builder.expr(body, entry); + cfg_builder.add_contained_edge(body_exit, fn_exit); let CFGBuilder {graph, ..} = cfg_builder; CFG {graph: graph, entry: entry, diff --git a/src/librustc/cfg/mod.rs b/src/librustc/cfg/mod.rs index d06f51073df0..43434b884c8d 100644 --- a/src/librustc/cfg/mod.rs +++ b/src/librustc/cfg/mod.rs @@ -59,8 +59,8 @@ pub type CFGEdge = graph::Edge; impl CFG { pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - blk: &hir::Block) -> CFG { - construct::construct(tcx, blk) + body: &hir::Expr) -> CFG { + construct::construct(tcx, body) } pub fn node_is_reachable(&self, id: ast::NodeId) -> bool { diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 465a09505e4a..ec09877ae121 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -672,120 +672,6 @@ extern "C" { ``` "##, -E0269: r##" -A returned value was expected but not all control paths return one. - -Erroneous code example: - -```compile_fail,E0269 -fn abracada_FAIL() -> String { - "this won't work".to_string(); - // error: not all control paths return a value -} -``` - -In the previous code, the function is supposed to return a `String`, however, -the code returns nothing (because of the ';'). Another erroneous code would be: - -```compile_fail -fn abracada_FAIL(b: bool) -> u32 { - if b { - 0 - } else { - "a" // It fails because an `u32` was expected and something else is - // returned. - } -} -``` - -It is advisable to find out what the unhandled cases are and check for them, -returning an appropriate value or panicking if necessary. Check if you need -to remove a semicolon from the last expression, like in the first erroneous -code example. -"##, - -E0270: r##" -Rust lets you define functions which are known to never return, i.e. are -'diverging', by marking its return type as `!`. - -For example, the following functions never return: - -```no_run -fn foo() -> ! { - loop {} -} - -fn bar() -> ! { - foo() // foo() is diverging, so this will diverge too -} - -fn baz() -> ! { - panic!(); // this macro internally expands to a call to a diverging function -} -``` - -Such functions can be used in a place where a value is expected without -returning a value of that type, for instance: - -```no_run -fn foo() -> ! { - loop {} -} - -let x = 3; - -let y = match x { - 1 => 1, - 2 => 4, - _ => foo() // diverging function called here -}; - -println!("{}", y) -``` - -If the third arm of the match block is reached, since `foo()` doesn't ever -return control to the match block, it is fine to use it in a place where an -integer was expected. The `match` block will never finish executing, and any -point where `y` (like the print statement) is needed will not be reached. - -However, if we had a diverging function that actually does finish execution: - -```ignore -fn foo() -> ! { - loop {break;} -} -``` - -Then we would have an unknown value for `y` in the following code: - -```no_run -fn foo() -> ! { - loop {} -} - -let x = 3; - -let y = match x { - 1 => 1, - 2 => 4, - _ => foo() -}; - -println!("{}", y); -``` - -In the previous example, the print statement was never reached when the -wildcard match arm was hit, so we were okay with `foo()` not returning an -integer that we could set to `y`. But in this example, `foo()` actually does -return control, so the print statement will be executed with an uninitialized -value. - -Obviously we cannot have functions which are allowed to be used in such -positions and yet can return control. So, if you are defining a function that -returns `!`, make sure that there is no way for it to actually finish -executing. -"##, - E0271: r##" This is because of a type mismatch between the associated type of some trait (e.g. `T::Bar`, where `T` implements `trait Quux { type Bar; }`) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index b1771f52da2c..9932e5fe6862 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -138,7 +138,7 @@ pub trait Visitor<'v> : Sized { fn visit_where_predicate(&mut self, predicate: &'v WherePredicate) { walk_where_predicate(self, predicate) } - fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, id: NodeId) { + fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Expr, s: Span, id: NodeId) { walk_fn(self, fk, fd, b, s, id) } fn visit_trait_item(&mut self, ti: &'v TraitItem) { @@ -635,13 +635,13 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<' pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>, function_declaration: &'v FnDecl, - function_body: &'v Block, + function_body: &'v Expr, _span: Span, id: NodeId) { visitor.visit_id(id); walk_fn_decl(visitor, function_declaration); walk_fn_kind(visitor, function_kind); - visitor.visit_block(function_body) + visitor.visit_expr(function_body) } pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) { @@ -925,7 +925,7 @@ impl<'v> Visitor<'v> for IdRangeComputingVisitor { /// Computes the id range for a single fn body, ignoring nested items. pub fn compute_id_range_for_fn_body(fk: FnKind, decl: &FnDecl, - body: &Block, + body: &Expr, sp: Span, id: NodeId) -> IdRange { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e1fec898e41e..b985298e47cc 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -595,12 +595,13 @@ impl<'a> LoweringContext<'a> { hir::ItemConst(self.lower_ty(t), self.lower_expr(e)) } ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { + let body = self.lower_block(body); hir::ItemFn(self.lower_fn_decl(decl), self.lower_unsafety(unsafety), self.lower_constness(constness), abi, self.lower_generics(generics), - self.lower_block(body)) + self.expr_block(body, ThinVec::new())) } ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)), ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)), @@ -665,7 +666,10 @@ impl<'a> LoweringContext<'a> { } TraitItemKind::Method(ref sig, ref body) => { hir::MethodTraitItem(this.lower_method_sig(sig), - body.as_ref().map(|x| this.lower_block(x))) + body.as_ref().map(|x| { + let body = this.lower_block(x); + this.expr_block(body, ThinVec::new()) + })) } TraitItemKind::Type(ref bounds, ref default) => { hir::TypeTraitItem(this.lower_bounds(bounds), @@ -691,8 +695,9 @@ impl<'a> LoweringContext<'a> { hir::ImplItemKind::Const(this.lower_ty(ty), this.lower_expr(expr)) } ImplItemKind::Method(ref sig, ref body) => { + let body = this.lower_block(body); hir::ImplItemKind::Method(this.lower_method_sig(sig), - this.lower_block(body)) + this.expr_block(body, ThinVec::new())) } ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)), ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), @@ -1110,7 +1115,7 @@ impl<'a> LoweringContext<'a> { self.with_parent_def(e.id, |this| { hir::ExprClosure(this.lower_capture_clause(capture_clause), this.lower_fn_decl(decl), - this.lower_block(body), + this.lower_expr(body), fn_decl_span) }) } diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 448723488569..325a90ea91e0 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -21,11 +21,9 @@ //! nested within a uniquely determined `FnLike`), and users can ask //! for the `Code` associated with a particular NodeId. -pub use self::Code::*; - use hir as ast; use hir::map::{self, Node}; -use hir::{Block, FnDecl}; +use hir::{Expr, FnDecl}; use hir::intravisit::FnKind; use syntax::abi; use syntax::ast::{Attribute, Name, NodeId}; @@ -50,7 +48,7 @@ pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; } /// Components shared by fn-like things (fn items, methods, closures). pub struct FnParts<'a> { pub decl: &'a FnDecl, - pub body: &'a Block, + pub body: &'a Expr, pub kind: FnKind<'a>, pub span: Span, pub id: NodeId, @@ -77,29 +75,32 @@ impl MaybeFnLike for ast::Expr { } } -/// Carries either an FnLikeNode or a Block, as these are the two +/// Carries either an FnLikeNode or a Expr, as these are the two /// constructs that correspond to "code" (as in, something from which /// we can construct a control-flow graph). #[derive(Copy, Clone)] pub enum Code<'a> { - FnLikeCode(FnLikeNode<'a>), - BlockCode(&'a Block), + FnLike(FnLikeNode<'a>), + Expr(&'a Expr), } impl<'a> Code<'a> { pub fn id(&self) -> NodeId { match *self { - FnLikeCode(node) => node.id(), - BlockCode(block) => block.id, + Code::FnLike(node) => node.id(), + Code::Expr(block) => block.id, } } - /// Attempts to construct a Code from presumed FnLike or Block node input. - pub fn from_node(node: Node) -> Option { - if let map::NodeBlock(block) = node { - Some(BlockCode(block)) - } else { - FnLikeNode::from_node(node).map(|fn_like| FnLikeCode(fn_like)) + /// Attempts to construct a Code from presumed FnLike or Expr node input. + pub fn from_node(map: &map::Map<'a>, id: NodeId) -> Option> { + match map.get(id) { + map::NodeBlock(_) => { + // Use the parent, hopefully an expression node. + Code::from_node(map, map.get_parent_node(id)) + } + map::NodeExpr(expr) => Some(Code::Expr(expr)), + node => FnLikeNode::from_node(node).map(Code::FnLike) } } } @@ -114,7 +115,7 @@ struct ItemFnParts<'a> { abi: abi::Abi, vis: &'a ast::Visibility, generics: &'a ast::Generics, - body: &'a Block, + body: &'a Expr, id: NodeId, span: Span, attrs: &'a [Attribute], @@ -124,14 +125,14 @@ struct ItemFnParts<'a> { /// for use when implementing FnLikeNode operations. struct ClosureParts<'a> { decl: &'a FnDecl, - body: &'a Block, + body: &'a Expr, id: NodeId, span: Span, attrs: &'a [Attribute], } impl<'a> ClosureParts<'a> { - fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self { + fn new(d: &'a FnDecl, b: &'a Expr, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self { ClosureParts { decl: d, body: b, @@ -171,9 +172,9 @@ impl<'a> FnLikeNode<'a> { } } - pub fn body(self) -> &'a Block { + pub fn body(self) -> &'a Expr { self.handle(|i: ItemFnParts<'a>| &*i.body, - |_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _, _| body, + |_, _, _: &'a ast::MethodSig, _, body: &'a ast::Expr, _, _| body, |c: ClosureParts<'a>| c.body) } @@ -214,7 +215,7 @@ impl<'a> FnLikeNode<'a> { Name, &'a ast::MethodSig, Option<&'a ast::Visibility>, - &'a ast::Block, + &'a ast::Expr, Span, &'a [Attribute]) -> A, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 3d9031a136e2..e23a721da08a 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -211,7 +211,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { } fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl, - b: &'ast Block, s: Span, id: NodeId) { + b: &'ast Expr, s: Span, id: NodeId) { assert_eq!(self.parent_node, id); intravisit::walk_fn(self, fk, fd, b, s, id); } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index cbd3e39f8703..6b5b8101a146 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -904,7 +904,7 @@ pub enum Expr_ { /// A closure (for example, `move |a, b, c| {a + b + c}`). /// /// The final span is the span of the argument block `|...|` - ExprClosure(CaptureClause, P, P, Span), + ExprClosure(CaptureClause, P, P, Span), /// A block (`{ ... }`) ExprBlock(P), @@ -1035,7 +1035,7 @@ pub enum TraitItem_ { /// must contain a value) ConstTraitItem(P, Option>), /// A method with an optional body - MethodTraitItem(MethodSig, Option>), + MethodTraitItem(MethodSig, Option>), /// An associated type with (possibly empty) bounds and optional concrete /// type TypeTraitItem(TyParamBounds, Option>), @@ -1060,7 +1060,7 @@ pub enum ImplItemKind { /// of the expression Const(P, P), /// A method implementation with the given signature and body - Method(MethodSig, P), + Method(MethodSig, P), /// An associated type Type(P), } @@ -1501,7 +1501,7 @@ pub enum Item_ { /// A `const` item ItemConst(P, P), /// A function declaration - ItemFn(P, Unsafety, Constness, Abi, Generics, P), + ItemFn(P, Unsafety, Constness, Abi, Generics, P), /// A module ItemMod(Mod), /// An external module diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 657c10bab12e..2c4ffb853c1f 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -713,7 +713,9 @@ impl<'a> State<'a> { typarams, &item.vis)?; word(&mut self.s, " ")?; - self.print_block_with_attrs(&body, &item.attrs)?; + self.end()?; // need to close a box + self.end()?; // need to close a box + self.print_expr(&body)?; } hir::ItemMod(ref _mod) => { self.head(&visibility_qualified(&item.vis, "mod"))?; @@ -1002,7 +1004,9 @@ impl<'a> State<'a> { self.print_method_sig(ti.name, sig, &hir::Inherited)?; if let Some(ref body) = *body { self.nbsp()?; - self.print_block_with_attrs(body, &ti.attrs)?; + self.end()?; // need to close a box + self.end()?; // need to close a box + self.print_expr(body)?; } else { word(&mut self.s, ";")?; } @@ -1034,7 +1038,9 @@ impl<'a> State<'a> { self.head("")?; self.print_method_sig(ii.name, sig, &ii.vis)?; self.nbsp()?; - self.print_block_with_attrs(body, &ii.attrs)?; + self.end()?; // need to close a box + self.end()?; // need to close a box + self.print_expr(body)?; } hir::ImplItemKind::Type(ref ty) => { self.print_associated_type(ii.name, None, Some(ty))?; @@ -1402,26 +1408,10 @@ impl<'a> State<'a> { self.print_fn_block_args(&decl)?; space(&mut self.s)?; - let default_return = match decl.output { - hir::DefaultReturn(..) => true, - _ => false, - }; + // this is a bare expression + self.print_expr(body)?; + self.end()?; // need to close a box - if !default_return || !body.stmts.is_empty() || body.expr.is_none() { - self.print_block_unclosed(&body)?; - } else { - // we extract the block, so as not to create another set of boxes - match body.expr.as_ref().unwrap().node { - hir::ExprBlock(ref blk) => { - self.print_block_unclosed(&blk)?; - } - _ => { - // this is a bare expression - self.print_expr(body.expr.as_ref().map(|e| &**e).unwrap())?; - self.end()?; // need to close a box - } - } - } // a box will be closed by print_expr, but we didn't want an overall // wrapper so we closed the corresponding opening. so create an // empty box to satisfy the close. diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 6f56f6858ce4..f44f82860077 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -838,7 +838,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> { } fn visit_fn(&mut self, fk: hir_visit::FnKind<'v>, decl: &'v hir::FnDecl, - body: &'v hir::Block, span: Span, id: ast::NodeId) { + body: &'v hir::Expr, span: Span, id: ast::NodeId) { run_lints!(self, check_fn, late_passes, fk, decl, body, span, id); hir_visit::walk_fn(self, fk, decl, body, span, id); run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 5fba14768bf2..6f7102229f8d 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -151,9 +151,9 @@ pub trait LateLintPass: LintPass { fn check_ty(&mut self, _: &LateContext, _: &hir::Ty) { } fn check_generics(&mut self, _: &LateContext, _: &hir::Generics) { } fn check_fn(&mut self, _: &LateContext, - _: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { } + _: FnKind, _: &hir::FnDecl, _: &hir::Expr, _: Span, _: ast::NodeId) { } fn check_fn_post(&mut self, _: &LateContext, - _: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { } + _: FnKind, _: &hir::FnDecl, _: &hir::Expr, _: Span, _: ast::NodeId) { } fn check_trait_item(&mut self, _: &LateContext, _: &hir::TraitItem) { } fn check_trait_item_post(&mut self, _: &LateContext, _: &hir::TraitItem) { } fn check_impl_item(&mut self, _: &LateContext, _: &hir::ImplItem) { } diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 7f3a58808c22..1ec3d0db8e0a 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -498,7 +498,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> { // ^^^^^^^^^^^^^ only needed for pretty printing - pub fn propagate(&mut self, cfg: &cfg::CFG, blk: &hir::Block) { + pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Expr) { //! Performs the data flow analysis. if self.bits_per_id == 0 { @@ -524,17 +524,17 @@ impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> { debug!("Dataflow result for {}:", self.analysis_name); debug!("{}", { let mut v = Vec::new(); - self.pretty_print_to(box &mut v, blk).unwrap(); + self.pretty_print_to(box &mut v, body).unwrap(); String::from_utf8(v).unwrap() }); } fn pretty_print_to<'b>(&self, wr: Box, - blk: &hir::Block) -> io::Result<()> { + body: &hir::Expr) -> io::Result<()> { let mut ps = pprust::rust_printer_annotated(wr, self, None); ps.cbox(pprust::indent_unit)?; ps.ibox(0)?; - ps.print_block(blk)?; + ps.print_expr(body)?; pp::eof(&mut ps.s) } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 7fc698fdbebf..a32d5542a79e 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -567,7 +567,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> { self.warn_dead_code(impl_item.id, impl_item.span, impl_item.name, "method"); } - intravisit::walk_block(self, body) + intravisit::walk_expr(self, body) } hir::ImplItemKind::Type(..) => {} } @@ -576,11 +576,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> { // Overwrite so that we don't warn the trait item itself. fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) { match trait_item.node { - hir::ConstTraitItem(_, Some(ref expr)) => { - intravisit::walk_expr(self, expr) - } + hir::ConstTraitItem(_, Some(ref body))| hir::MethodTraitItem(_, Some(ref body)) => { - intravisit::walk_block(self, body) + intravisit::walk_expr(self, body) } hir::ConstTraitItem(_, None) | hir::MethodTraitItem(_, None) | diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 8ca3c75eaa4b..5634e2012c97 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -94,7 +94,7 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { fn visit_fn(&mut self, fn_kind: FnKind<'v>, fn_decl: &'v hir::FnDecl, - block: &'v hir::Block, span: Span, id: ast::NodeId) { + block: &'v hir::Expr, span: Span, id: ast::NodeId) { let (is_item_fn, is_unsafe_fn) = match fn_kind { FnKind::ItemFn(_, _, unsafety, ..) => diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 0543d1303a5f..711a131a68e1 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -290,14 +290,14 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { pub fn walk_fn(&mut self, decl: &hir::FnDecl, - body: &hir::Block) { + body: &hir::Expr) { self.walk_arg_patterns(decl, body); - self.walk_block(body); + self.consume_expr(body); } fn walk_arg_patterns(&mut self, decl: &hir::FnDecl, - body: &hir::Block) { + body: &hir::Expr) { for arg in &decl.inputs { let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id)); diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 57503398cfe5..7dbf9aa74144 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -144,7 +144,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> { } fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl, - b: &'v hir::Block, s: Span, id: ast::NodeId) { + b: &'v hir::Expr, s: Span, id: ast::NodeId) { if let FnKind::Closure(..) = fk { span_bug!(s, "intrinsicck: closure outside of function") } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 46bea00cca3c..a654d65bc679 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -123,10 +123,9 @@ use std::io::prelude::*; use std::io; use std::rc::Rc; use syntax::ast::{self, NodeId}; -use syntax::codemap::original_sp; use syntax::parse::token::keywords; use syntax::ptr::P; -use syntax_pos::{BytePos, Span}; +use syntax_pos::Span; use hir::Expr; use hir; @@ -187,7 +186,7 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt) -> String { impl<'a, 'tcx, 'v> Visitor<'v> for IrMaps<'a, 'tcx> { fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl, - b: &'v hir::Block, s: Span, id: NodeId) { + b: &'v hir::Expr, s: Span, id: NodeId) { visit_fn(self, fk, fd, b, s, id); } fn visit_local(&mut self, l: &hir::Local) { visit_local(self, l); } @@ -352,9 +351,9 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> { } impl<'a, 'tcx, 'v> Visitor<'v> for Liveness<'a, 'tcx> { - fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl, - b: &'v hir::Block, s: Span, n: NodeId) { - check_fn(self, fk, fd, b, s, n); + fn visit_fn(&mut self, _: FnKind<'v>, _: &'v hir::FnDecl, + _: &'v hir::Expr, _: Span, _: NodeId) { + // do not check contents of nested fns } fn visit_local(&mut self, l: &hir::Local) { check_local(self, l); @@ -370,7 +369,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Liveness<'a, 'tcx> { fn visit_fn(ir: &mut IrMaps, fk: FnKind, decl: &hir::FnDecl, - body: &hir::Block, + body: &hir::Expr, sp: Span, id: ast::NodeId) { debug!("visit_fn"); @@ -405,10 +404,10 @@ fn visit_fn(ir: &mut IrMaps, // compute liveness let mut lsets = Liveness::new(&mut fn_maps, specials); - let entry_ln = lsets.compute(decl, body); + let entry_ln = lsets.compute(body); // check for various error conditions - lsets.visit_block(body); + lsets.visit_expr(body); lsets.check_ret(id, sp, fk, entry_ln, body); lsets.warn_about_unused_args(decl, entry_ln); } @@ -821,17 +820,23 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // _______________________________________________________________________ - fn compute(&mut self, decl: &hir::FnDecl, body: &hir::Block) -> LiveNode { + fn compute(&mut self, body: &hir::Expr) -> LiveNode { // if there is a `break` or `again` at the top level, then it's // effectively a return---this only occurs in `for` loops, // where the body is really a closure. - debug!("compute: using id for block, {}", block_to_string(body)); + debug!("compute: using id for body, {}", expr_to_string(body)); let exit_ln = self.s.exit_ln; - let entry_ln: LiveNode = - self.with_loop_nodes(body.id, exit_ln, exit_ln, - |this| this.propagate_through_fn_block(decl, body)); + let entry_ln: LiveNode = self.with_loop_nodes(body.id, exit_ln, exit_ln, |this| { + // the fallthrough exit is only for those cases where we do not + // explicitly return: + let s = this.s; + this.init_from_succ(s.fallthrough_ln, s.exit_ln); + this.acc(s.fallthrough_ln, s.clean_exit_var, ACC_READ); + + this.propagate_through_expr(body, s.fallthrough_ln) + }); // hack to skip the loop unless debug! is enabled: debug!("^^ liveness computation results for body {} (entry={:?})", @@ -846,20 +851,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { entry_ln } - fn propagate_through_fn_block(&mut self, _: &hir::FnDecl, blk: &hir::Block) - -> LiveNode { - // the fallthrough exit is only for those cases where we do not - // explicitly return: - let s = self.s; - self.init_from_succ(s.fallthrough_ln, s.exit_ln); - if blk.expr.is_none() { - self.acc(s.fallthrough_ln, s.no_ret_var, ACC_READ) - } - self.acc(s.fallthrough_ln, s.clean_exit_var, ACC_READ); - - self.propagate_through_block(blk, s.fallthrough_ln) - } - fn propagate_through_block(&mut self, blk: &hir::Block, succ: LiveNode) -> LiveNode { let succ = self.propagate_through_opt_expr(blk.expr.as_ref().map(|e| &**e), succ); @@ -1448,15 +1439,6 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { } } -fn check_fn(_v: &Liveness, - _fk: FnKind, - _decl: &hir::FnDecl, - _body: &hir::Block, - _sp: Span, - _id: NodeId) { - // do not check contents of nested fns -} - impl<'a, 'tcx> Liveness<'a, 'tcx> { fn fn_ret(&self, id: NodeId) -> ty::Binder> { let fn_ty = self.ir.tcx.tables().node_id_to_type(id); @@ -1472,7 +1454,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { sp: Span, _fk: FnKind, entry_ln: LiveNode, - body: &hir::Block) + body: &hir::Expr) { // within the fn body, late-bound regions are liberated // and must outlive the *call-site* of the function. @@ -1481,13 +1463,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.ir.tcx.region_maps.call_site_extent(id, body.id), &self.fn_ret(id)); - if fn_ret.is_never() { - // FIXME(durka) this rejects code like `fn foo(x: !) -> ! { x }` - if self.live_on_entry(entry_ln, self.s.clean_exit_var).is_some() { - span_err!(self.ir.tcx.sess, sp, E0270, - "computation may converge in a function marked as diverging"); - } - } else if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { + if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { let param_env = ParameterEnvironment::for_item(self.ir.tcx, id); let t_ret_subst = fn_ret.subst(self.ir.tcx, ¶m_env.free_substs); let is_nil = self.ir.tcx.infer_ctxt(None, Some(param_env), @@ -1498,32 +1474,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // for nil return types, it is ok to not return a value expl. if !is_nil { - let ends_with_stmt = match body.expr { - None if !body.stmts.is_empty() => - match body.stmts.last().unwrap().node { - hir::StmtSemi(ref e, _) => { - self.ir.tcx.tables().expr_ty(&e) == fn_ret - }, - _ => false - }, - _ => false - }; - let mut err = struct_span_err!(self.ir.tcx.sess, - sp, - E0269, - "not all control paths return a value"); - if ends_with_stmt { - let last_stmt = body.stmts.last().unwrap(); - let original_span = original_sp(self.ir.tcx.sess.codemap(), - last_stmt.span, sp); - let span_semicolon = Span { - lo: original_span.hi - BytePos(1), - hi: original_span.hi, - expn_id: original_span.expn_id - }; - err.span_help(span_semicolon, "consider removing this semicolon:"); - } - err.emit(); + span_bug!(sp, "not all control paths return a value"); } } } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 9898ec7597d9..7868e700f270 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -248,9 +248,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { match *node { ast_map::NodeItem(item) => { match item.node { - hir::ItemFn(.., ref search_block) => { + hir::ItemFn(.., ref body) => { if item_might_be_inlined(&item) { - intravisit::walk_block(self, &search_block) + self.visit_expr(body); } } @@ -278,11 +278,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::MethodTraitItem(_, None) => { // Keep going, nothing to get exported } - hir::ConstTraitItem(_, Some(ref expr)) => { - self.visit_expr(&expr); - } + hir::ConstTraitItem(_, Some(ref body)) | hir::MethodTraitItem(_, Some(ref body)) => { - intravisit::walk_block(self, body); + self.visit_expr(body); } hir::TypeTraitItem(..) => {} } @@ -295,7 +293,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::ImplItemKind::Method(ref sig, ref body) => { let did = self.tcx.map.get_parent_did(search_item); if method_might_be_inlined(self.tcx, sig, impl_item, did) { - intravisit::walk_block(self, body) + self.visit_expr(body) } } hir::ImplItemKind::Type(_) => {} diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 8d51fda0cf2b..34a6a547d944 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -490,12 +490,7 @@ impl RegionMaps { // if there's one. Static items, for instance, won't // have an enclosing scope, hence no scope will be // returned. - let expr_extent = self.node_extent(expr_id); - // For some reason, the expr's scope itself is skipped here. - let mut id = match scope_map[expr_extent.0 as usize].into_option() { - Some(i) => i, - _ => return None - }; + let mut id = self.node_extent(expr_id); while let Some(p) = scope_map[id.0 as usize].into_option() { match code_extents[p.0 as usize] { @@ -1086,7 +1081,7 @@ fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &hir::Item) { fn resolve_fn(visitor: &mut RegionResolutionVisitor, kind: FnKind, decl: &hir::FnDecl, - body: &hir::Block, + body: &hir::Expr, sp: Span, id: ast::NodeId) { debug!("region::resolve_fn(id={:?}, \ @@ -1128,7 +1123,7 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor, parent: fn_decl_scope, var_parent: fn_decl_scope }; - visitor.visit_block(body); + visitor.visit_expr(body); // Restore context we had at the start. visitor.cx = outer_cx; @@ -1191,7 +1186,7 @@ impl<'a, 'v> Visitor<'v> for RegionResolutionVisitor<'a> { } fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, - b: &'v Block, s: Span, n: NodeId) { + b: &'v Expr, s: Span, n: NodeId) { resolve_fn(self, fk, fd, b, s, n); } fn visit_arm(&mut self, a: &Arm) { diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index e6d960735299..292d9592ceb0 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -202,7 +202,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> { } fn visit_fn(&mut self, fk: FnKind<'v>, decl: &'v hir::FnDecl, - b: &'v hir::Block, s: Span, fn_id: ast::NodeId) { + b: &'v hir::Expr, s: Span, fn_id: ast::NodeId) { match fk { FnKind::ItemFn(_, generics, ..) => { self.visit_early_late(fn_id,decl, generics, |this| { @@ -403,7 +403,7 @@ fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, sha // Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning // if one of the label shadows a lifetime or another label. -fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Block) { +fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Expr) { struct GatherLabels<'a> { sess: &'a Session, scope: Scope<'a>, @@ -415,7 +415,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Block) { scope: ctxt.scope, labels_in_fn: &mut ctxt.labels_in_fn, }; - gather.visit_block(b); + gather.visit_expr(b); return; impl<'v, 'a> Visitor<'v> for GatherLabels<'a> { @@ -493,7 +493,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn add_scope_and_walk_fn<'b>(&mut self, fk: FnKind, fd: &hir::FnDecl, - fb: &'b hir::Block, + fb: &'b hir::Expr, _span: Span, fn_id: ast::NodeId) { @@ -516,7 +516,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { extract_labels(self, fb); self.with(FnScope { fn_id: fn_id, body_id: fb.id, s: self.scope }, - |_old_scope, this| this.visit_block(fb)) + |_old_scope, this| this.visit_expr(fb)) } fn with(&mut self, wrap_scope: ScopeChain, f: F) where diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index b2032e6a1bf9..5ed628d7dcae 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -190,7 +190,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, all_loans: &[Loan<'tcx>], fn_id: ast::NodeId, decl: &hir::FnDecl, - body: &hir::Block) { + body: &hir::Expr) { debug!("check_loans(body id={})", body.id); let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 763c012a8f8a..8f2afa7f8082 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -42,7 +42,7 @@ mod move_error; pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, fn_id: NodeId, decl: &hir::FnDecl, - body: &hir::Block) + body: &hir::Expr) -> (Vec>, move_data::MoveData<'tcx>) { let mut glcx = GatherLoanCtxt { diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index cea9170da9ff..836832de5b9c 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -58,7 +58,7 @@ pub struct MoveDataParamEnv<'tcx> { pub fn borrowck_mir(bcx: &mut BorrowckCtxt, fk: FnKind, _decl: &hir::FnDecl, - body: &hir::Block, + body: &hir::Expr, _sp: Span, id: ast::NodeId, attributes: &[ast::Attribute]) { diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 2f74ea3e475b..fb842f70a54a 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -47,9 +47,7 @@ use syntax_pos::{MultiSpan, Span}; use errors::DiagnosticBuilder; use rustc::hir; -use rustc::hir::{FnDecl, Block}; -use rustc::hir::intravisit; -use rustc::hir::intravisit::{Visitor, FnKind}; +use rustc::hir::intravisit::{self, Visitor, FnKind}; pub mod check_loans; @@ -65,8 +63,8 @@ pub struct LoanDataFlowOperator; pub type LoanDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, LoanDataFlowOperator>; impl<'a, 'tcx, 'v> Visitor<'v> for BorrowckCtxt<'a, 'tcx> { - fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, - b: &'v Block, s: Span, id: ast::NodeId) { + fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl, + b: &'v hir::Expr, s: Span, id: ast::NodeId) { match fk { FnKind::ItemFn(..) | FnKind::Method(..) => { @@ -159,7 +157,7 @@ pub struct AnalysisData<'a, 'tcx: 'a> { fn borrowck_fn(this: &mut BorrowckCtxt, fk: FnKind, decl: &hir::FnDecl, - body: &hir::Block, + body: &hir::Expr, sp: Span, id: ast::NodeId, attributes: &[ast::Attribute]) { @@ -200,7 +198,7 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, fk: FnKind, decl: &hir::FnDecl, cfg: &cfg::CFG, - body: &hir::Block, + body: &hir::Expr, sp: Span, id: ast::NodeId) -> AnalysisData<'a, 'tcx> diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index afc4ccef0cc0..32bda5e11620 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -656,7 +656,7 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { cfg: &cfg::CFG, id_range: IdRange, decl: &hir::FnDecl, - body: &hir::Block) + body: &hir::Expr) -> FlowedMoveData<'a, 'tcx> { let mut dfcx_moves = DataFlowContext::new(tcx, diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 615aca90db8b..e0e8a2159192 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -65,7 +65,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for OuterVisitor<'a, 'tcx> { } fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl, - b: &'v hir::Block, s: Span, id: ast::NodeId) { + b: &'v hir::Expr, s: Span, id: ast::NodeId) { if let FnKind::Closure(..) = fk { span_bug!(s, "check_match: closure outside of function") } @@ -113,7 +113,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MatchVisitor<'a, 'tcx> { } fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl, - b: &'v hir::Block, s: Span, n: ast::NodeId) { + b: &'v hir::Expr, s: Span, n: ast::NodeId) { intravisit::walk_fn(self, fk, fd, b, s, n); for input in &fd.inputs { diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 57a5400ecadf..ee6c27655d68 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -857,11 +857,10 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, callee => signal!(e, CallOn(callee)), }; let (decl, result) = if let Some(fn_like) = lookup_const_fn_by_id(tcx, did) { - (fn_like.decl(), &fn_like.body().expr) + (fn_like.decl(), fn_like.body()) } else { signal!(e, NonConstPath) }; - let result = result.as_ref().expect("const fn has no result expression"); assert_eq!(decl.inputs.len(), args.len()); let mut call_args = DefIdMap(); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index b4ab9da92e9d..ecbf28c1082f 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -701,8 +701,8 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, mut out: W) -> io::Result<()> { let cfg = match code { - blocks::BlockCode(block) => cfg::CFG::new(tcx, &block), - blocks::FnLikeCode(fn_like) => cfg::CFG::new(tcx, &fn_like.body()), + blocks::Code::Expr(expr) => cfg::CFG::new(tcx, expr), + blocks::Code::FnLike(fn_like) => cfg::CFG::new(tcx, fn_like.body()), }; let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges; let lcfg = LabelledCFG { @@ -717,12 +717,12 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, let r = dot::render(&lcfg, &mut out); return expand_err_details(r); } - blocks::BlockCode(_) => { + blocks::Code::Expr(_) => { tcx.sess.err("--pretty flowgraph with -Z flowgraph-print annotations requires \ fn-like node id."); return Ok(()); } - blocks::FnLikeCode(fn_like) => { + blocks::Code::FnLike(fn_like) => { let (bccx, analysis_data) = borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_like.to_fn_parts(), &cfg); @@ -990,8 +990,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, tcx.sess.fatal(&format!("--pretty flowgraph couldn't find id: {}", nodeid)) }); - let code = blocks::Code::from_node(node); - match code { + match blocks::Code::from_node(&tcx.map, nodeid) { Some(code) => { let variants = gather_flowgraph_variants(tcx.sess); diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index fea3de59520c..e095bde18fd8 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -250,7 +250,7 @@ impl LateLintPass for NonSnakeCase { cx: &LateContext, fk: FnKind, _: &hir::FnDecl, - _: &hir::Block, + _: &hir::Expr, span: Span, id: ast::NodeId) { match fk { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 28dc71fd59ba..192d7be6774a 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -222,7 +222,7 @@ impl LateLintPass for UnsafeCode { cx: &LateContext, fk: FnKind, _: &hir::FnDecl, - _: &hir::Block, + _: &hir::Expr, span: Span, _: ast::NodeId) { match fk { @@ -812,7 +812,7 @@ impl LateLintPass for UnconditionalRecursion { cx: &LateContext, fn_kind: FnKind, _: &hir::FnDecl, - blk: &hir::Block, + blk: &hir::Expr, sp: Span, id: ast::NodeId) { let method = match fn_kind { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index d3fd638d6b5f..0668d362037d 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -99,7 +99,7 @@ impl LateLintPass for UnusedMut { cx: &LateContext, _: FnKind, decl: &hir::FnDecl, - _: &hir::Block, + _: &hir::Expr, _: Span, _: ast::NodeId) { for a in &decl.inputs { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index b37dd8dd0a90..902798ec9800 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -156,7 +156,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, fn_id: ast::NodeId, arguments: A, return_ty: Ty<'gcx>, - ast_block: &'gcx hir::Block) + ast_body: &'gcx hir::Expr) -> (Mir<'tcx>, ScopeAuxiliaryVec) where A: Iterator, Option<&'gcx hir::Pat>)> { @@ -166,7 +166,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let span = tcx.map.span(fn_id); let mut builder = Builder::new(hir, span, arguments.len(), return_ty); - let body_id = ast_block.id; + let body_id = ast_body.id; let call_site_extent = tcx.region_maps.lookup_code_extent( CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id }); @@ -176,7 +176,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let mut block = START_BLOCK; unpack!(block = builder.in_scope(call_site_extent, block, |builder| { unpack!(block = builder.in_scope(arg_extent, block, |builder| { - builder.args_and_body(block, return_ty, &arguments, arg_extent, ast_block) + builder.args_and_body(block, &arguments, arg_extent, ast_body) })); // Attribute epilogue to function's closing brace let fn_end = Span { lo: span.hi, ..span }; @@ -310,10 +310,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn args_and_body(&mut self, mut block: BasicBlock, - return_ty: Ty<'tcx>, arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)], argument_extent: CodeExtent, - ast_block: &'gcx hir::Block) + ast_body: &'gcx hir::Expr) -> BlockAnd<()> { // Allocate locals for the function arguments @@ -342,12 +341,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if let Some(pattern) = pattern { let pattern = Pattern::from_hir(self.hir.tcx(), pattern); - scope = self.declare_bindings(scope, ast_block.span, &pattern); + scope = self.declare_bindings(scope, ast_body.span, &pattern); unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue)); } // Make sure we drop (parts of) the argument even when not matched on. - self.schedule_drop(pattern.as_ref().map_or(ast_block.span, |pat| pat.span), + self.schedule_drop(pattern.as_ref().map_or(ast_body.span, |pat| pat.span), argument_extent, &lvalue, ty); } @@ -357,13 +356,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { self.visibility_scope = visibility_scope; } - // FIXME(#32959): temporary hack for the issue at hand - let return_is_unit = return_ty.is_nil(); - // start the first basic block and translate the body - unpack!(block = self.ast_block(&Lvalue::Local(RETURN_POINTER), - return_is_unit, block, ast_block)); - - block.unit() + let body = self.hir.mirror(ast_body); + self.into(&Lvalue::Local(RETURN_POINTER), block, body) } fn get_unit_temp(&mut self) -> Lvalue<'tcx> { diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 0ffc59fe6bf4..af2f9adfc9a8 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -209,7 +209,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { fn visit_fn(&mut self, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl, - body: &'tcx hir::Block, + body: &'tcx hir::Expr, span: Span, id: ast::NodeId) { // fetch the fully liberated fn signature (that is, all bound diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index f23539e88f78..7a93d4594ee9 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -134,7 +134,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { fn fn_like(&mut self, fk: FnKind, fd: &hir::FnDecl, - b: &hir::Block, + b: &hir::Expr, s: Span, fn_id: ast::NodeId) -> ConstQualif { @@ -265,7 +265,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl, - b: &'v hir::Block, + b: &'v hir::Expr, s: Span, fn_id: ast::NodeId) { self.fn_like(fk, fd, b, s, fn_id); diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index f8994de54a13..417987d9664e 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -164,7 +164,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_fn(&mut self, fk: hir_visit::FnKind<'v>, fd: &'v hir::FnDecl, - b: &'v hir::Block, + b: &'v hir::Expr, s: Span, id: NodeId) { self.record("FnDecl", Id::None, fd); diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index e942707acd56..e58cd8938193 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -54,7 +54,7 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> { self.with_context(Loop, |v| v.visit_block(&b)); } hir::ExprClosure(.., ref b, _) => { - self.with_context(Closure, |v| v.visit_block(&b)); + self.with_context(Closure, |v| v.visit_expr(&b)); } hir::ExprBreak(_) => self.require_loop("break", e.span), hir::ExprAgain(_) => self.require_loop("continue", e.span), diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs index c3ef5a72a294..d55ce4c35638 100644 --- a/src/librustc_passes/rvalues.rs +++ b/src/librustc_passes/rvalues.rs @@ -35,7 +35,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for RvalueContext<'a, 'tcx> { fn visit_fn(&mut self, fk: intravisit::FnKind<'v>, fd: &'v hir::FnDecl, - b: &'v hir::Block, + b: &'v hir::Expr, s: Span, fn_id: ast::NodeId) { // FIXME (@jroesch) change this to be an inference context diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index d478f1092bd8..af834f3f84d4 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -23,7 +23,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expr: &hir::Expr, _capture: hir::CaptureClause, decl: &'gcx hir::FnDecl, - body: &'gcx hir::Block, + body: &'gcx hir::Expr, expected: Expectation<'tcx>) -> Ty<'tcx> { debug!("check_expr_closure(expr={:?},expected={:?})", @@ -44,7 +44,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expr: &hir::Expr, opt_kind: Option, decl: &'gcx hir::FnDecl, - body: &'gcx hir::Block, + body: &'gcx hir::Expr, expected_sig: Option>) -> Ty<'tcx> { let expr_def_id = self.tcx.map.local_def_id(expr.id); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f7e05f4777ec..725862022c59 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -534,7 +534,7 @@ pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult { fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, decl: &'tcx hir::FnDecl, - body: &'tcx hir::Block, + body: &'tcx hir::Expr, fn_id: ast::NodeId, span: Span) { let raw_fty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(fn_id)).ty; @@ -558,7 +558,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let fcx = check_fn(&inh, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body); fcx.select_all_obligations_and_apply_defaults(); - fcx.closure_analyze_fn(body); + fcx.closure_analyze(body); fcx.select_obligations_where_possible(); fcx.check_casts(); fcx.select_all_obligations_or_error(); // Casts can introduce new obligations. @@ -654,7 +654,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { // Don't descend into the bodies of nested closures fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl, - _: &'gcx hir::Block, _: Span, _: ast::NodeId) { } + _: &'gcx hir::Expr, _: Span, _: ast::NodeId) { } } /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function @@ -669,7 +669,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, fn_sig: &ty::FnSig<'tcx>, decl: &'gcx hir::FnDecl, fn_id: ast::NodeId, - body: &'gcx hir::Block) + body: &'gcx hir::Expr) -> FnCtxt<'a, 'gcx, 'tcx> { let mut fn_sig = fn_sig.clone(); @@ -709,18 +709,12 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, fcx.write_ty(input.id, arg_ty); } - visit.visit_block(body); + visit.visit_expr(body); } inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig); - // FIXME(aburka) do we need this special case? and should it be is_uninhabited? - let expected = if fcx.ret_ty.is_never() { - NoExpectation - } else { - ExpectHasType(fcx.ret_ty) - }; - fcx.check_block_with_expected(body, expected); + fcx.check_expr_coercable_to_type(body, fcx.ret_ty); fcx } @@ -1198,7 +1192,7 @@ fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, fcx.check_expr_coercable_to_type(expr, expected_type); fcx.select_all_obligations_and_apply_defaults(); - fcx.closure_analyze_const(expr); + fcx.closure_analyze(expr); fcx.select_obligations_where_possible(); fcx.check_casts(); fcx.select_all_obligations_or_error(); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 6f6538254c46..d4e5e9a5bb35 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -142,13 +142,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn regionck_fn(&self, fn_id: ast::NodeId, decl: &hir::FnDecl, - blk: &hir::Block) { + body: &hir::Expr) { debug!("regionck_fn(id={})", fn_id); - let mut rcx = RegionCtxt::new(self, RepeatingScope(blk.id), blk.id, Subject(fn_id)); + let mut rcx = RegionCtxt::new(self, RepeatingScope(body.id), body.id, Subject(fn_id)); if self.err_count_since_creation() == 0 { // regionck assumes typeck succeeded - rcx.visit_fn_body(fn_id, decl, blk, self.tcx.map.span(fn_id)); + rcx.visit_fn_body(fn_id, decl, body, self.tcx.map.span(fn_id)); } rcx.free_region_map.relate_free_regions_from_predicates( @@ -268,7 +268,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { fn visit_fn_body(&mut self, id: ast::NodeId, // the id of the fn itself fn_decl: &hir::FnDecl, - body: &hir::Block, + body: &hir::Expr, span: Span) { // When we enter a function, we can derive @@ -305,7 +305,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { self.relate_free_regions(&fn_sig_tys[..], body.id, span); self.link_fn_args(self.tcx.region_maps.node_extent(body.id), &fn_decl.inputs[..]); - self.visit_block(body); + self.visit_expr(body); self.visit_region_obligations(body.id); let call_site_scope = self.call_site_scope.unwrap(); @@ -480,7 +480,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'gcx, 'tcx> { // regions, until regionck, as described in #3238. fn visit_fn(&mut self, _fk: intravisit::FnKind<'v>, fd: &'v hir::FnDecl, - b: &'v hir::Block, span: Span, id: ast::NodeId) { + b: &'v hir::Expr, span: Span, id: ast::NodeId) { self.visit_fn_body(id, fd, b, span) } @@ -825,7 +825,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { fn check_expr_fn_block(&mut self, expr: &hir::Expr, - body: &hir::Block) { + body: &hir::Expr) { let repeating_scope = self.set_repeating_scope(body.id); intravisit::walk_expr(self, expr); self.set_repeating_scope(repeating_scope); diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index aa221c33b5dd..2fea86cb2120 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -57,18 +57,7 @@ use rustc::util::nodemap::NodeMap; // PUBLIC ENTRY POINTS impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { - pub fn closure_analyze_fn(&self, body: &hir::Block) { - let mut seed = SeedBorrowKind::new(self); - seed.visit_block(body); - - let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds); - adjust.visit_block(body); - - // it's our job to process these. - assert!(self.deferred_call_resolutions.borrow().is_empty()); - } - - pub fn closure_analyze_const(&self, body: &hir::Expr) { + pub fn closure_analyze(&self, body: &hir::Expr) { let mut seed = SeedBorrowKind::new(self); seed.visit_expr(body); @@ -110,7 +99,7 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> { fn check_closure(&mut self, expr: &hir::Expr, capture_clause: hir::CaptureClause, - _body: &hir::Block) + _body: &hir::Expr) { let closure_def_id = self.fcx.tcx.map.local_def_id(expr.id); if !self.fcx.tables.borrow().closure_kinds.contains_key(&closure_def_id) { @@ -164,7 +153,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { id: ast::NodeId, span: Span, decl: &hir::FnDecl, - body: &hir::Block) { + body: &hir::Expr) { /*! * Analysis starting point. */ @@ -497,7 +486,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'gcx, 'tcx> { fn visit_fn(&mut self, fn_kind: intravisit::FnKind<'v>, decl: &'v hir::FnDecl, - body: &'v hir::Block, + body: &'v hir::Expr, span: Span, id: ast::NodeId) { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 741f327ac99e..2c1a9a7b1774 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -347,7 +347,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { fn check_item_fn(&mut self, item: &hir::Item, - body: &hir::Block) + body: &hir::Expr) { self.for_item(item).with_fcx(|fcx, this| { let free_substs = &fcx.parameter_environment.free_substs; diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 5ef3e8699602..9f3214a0d813 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -49,11 +49,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn resolve_type_vars_in_fn(&self, decl: &hir::FnDecl, - blk: &hir::Block, + body: &hir::Expr, item_id: ast::NodeId) { assert_eq!(self.writeback_errors.get(), false); let mut wbcx = WritebackCx::new(self); - wbcx.visit_block(blk); + wbcx.visit_expr(body); for arg in &decl.inputs { wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id); wbcx.visit_pat(&arg.pat);