about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2016-10-26 02:27:14 +0300
committerEduard Burtescu <edy.burt@gmail.com>2016-11-10 01:44:45 +0200
commitff0830d74985246c2e2bbd28e7d8c0ef072e2458 (patch)
tree1b8e0487cbe5169aa52415f882f572dc664ffe1a /src
parent49772fbf5dc1137a031086999b20ab7b961f3655 (diff)
downloadrust-ff0830d74985246c2e2bbd28e7d8c0ef072e2458.tar.gz
rust-ff0830d74985246c2e2bbd28e7d8c0ef072e2458.zip
rustc: use an Expr instead of a Block for function bodies.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/cfg/construct.rs12
-rw-r--r--src/librustc/cfg/mod.rs4
-rw-r--r--src/librustc/diagnostics.rs114
-rw-r--r--src/librustc/hir/intravisit.rs8
-rw-r--r--src/librustc/hir/lowering.rs13
-rw-r--r--src/librustc/hir/map/blocks.rs43
-rw-r--r--src/librustc/hir/map/collector.rs2
-rw-r--r--src/librustc/hir/mod.rs8
-rw-r--r--src/librustc/hir/print.rs34
-rw-r--r--src/librustc/lint/context.rs2
-rw-r--r--src/librustc/lint/mod.rs4
-rw-r--r--src/librustc/middle/dataflow.rs8
-rw-r--r--src/librustc/middle/dead.rs8
-rw-r--r--src/librustc/middle/effect.rs2
-rw-r--r--src/librustc/middle/expr_use_visitor.rs6
-rw-r--r--src/librustc/middle/intrinsicck.rs2
-rw-r--r--src/librustc/middle/liveness.rs93
-rw-r--r--src/librustc/middle/reachable.rs12
-rw-r--r--src/librustc/middle/region.rs13
-rw-r--r--src/librustc/middle/resolve_lifetime.rs10
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs2
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/mod.rs2
-rw-r--r--src/librustc_borrowck/borrowck/mir/mod.rs2
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs12
-rw-r--r--src/librustc_borrowck/borrowck/move_data.rs2
-rw-r--r--src/librustc_const_eval/check_match.rs4
-rw-r--r--src/librustc_const_eval/eval.rs3
-rw-r--r--src/librustc_driver/pretty.rs11
-rw-r--r--src/librustc_lint/bad_style.rs2
-rw-r--r--src/librustc_lint/builtin.rs4
-rw-r--r--src/librustc_lint/unused.rs2
-rw-r--r--src/librustc_mir/build/mod.rs22
-rw-r--r--src/librustc_mir/mir_map.rs2
-rw-r--r--src/librustc_passes/consts.rs4
-rw-r--r--src/librustc_passes/hir_stats.rs2
-rw-r--r--src/librustc_passes/loops.rs2
-rw-r--r--src/librustc_passes/rvalues.rs2
-rw-r--r--src/librustc_typeck/check/closure.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs20
-rw-r--r--src/librustc_typeck/check/regionck.rs14
-rw-r--r--src/librustc_typeck/check/upvar.rs19
-rw-r--r--src/librustc_typeck/check/wfcheck.rs2
-rw-r--r--src/librustc_typeck/check/writeback.rs4
43 files changed, 169 insertions, 372 deletions
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index a2fc6e044e7..22c7d14be29 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 d06f51073df..43434b884c8 100644
--- a/src/librustc/cfg/mod.rs
+++ b/src/librustc/cfg/mod.rs
@@ -59,8 +59,8 @@ pub type CFGEdge = graph::Edge<CFGEdgeData>;
 
 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 465a09505e4..ec09877ae12 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 b1771f52da2..9932e5fe686 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 e1fec898e41..b985298e47c 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 44872348856..325a90ea91e 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<Code> {
-        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<Code<'a>> {
+        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 3d9031a136e..e23a721da08 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 cbd3e39f870..6b5b8101a14 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<FnDecl>, P<Block>, Span),
+    ExprClosure(CaptureClause, P<FnDecl>, P<Expr>, Span),
     /// A block (`{ ... }`)
     ExprBlock(P<Block>),
 
@@ -1035,7 +1035,7 @@ pub enum TraitItem_ {
     /// must contain a value)
     ConstTraitItem(P<Ty>, Option<P<Expr>>),
     /// A method with an optional body
-    MethodTraitItem(MethodSig, Option<P<Block>>),
+    MethodTraitItem(MethodSig, Option<P<Expr>>),
     /// An associated type with (possibly empty) bounds and optional concrete
     /// type
     TypeTraitItem(TyParamBounds, Option<P<Ty>>),
@@ -1060,7 +1060,7 @@ pub enum ImplItemKind {
     /// of the expression
     Const(P<Ty>, P<Expr>),
     /// A method implementation with the given signature and body
-    Method(MethodSig, P<Block>),
+    Method(MethodSig, P<Expr>),
     /// An associated type
     Type(P<Ty>),
 }
@@ -1501,7 +1501,7 @@ pub enum Item_ {
     /// A `const` item
     ItemConst(P<Ty>, P<Expr>),
     /// A function declaration
-    ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Block>),
+    ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Expr>),
     /// A module
     ItemMod(Mod),
     /// An external module
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 657c10bab12..2c4ffb853c1 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 6f56f6858ce..f44f8286007 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 5fba14768bf..6f7102229f8 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 7f3a58808c2..1ec3d0db8e0 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<io::Write + 'b>,
-                           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 7fc698fdbeb..a32d5542a79 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 8ca3c75eaa4..5634e2012c9 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 0543d1303a5..711a131a68e 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 57503398cfe..7dbf9aa7414 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 46bea00cca3..a654d65bc67 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<Ty<'tcx>> {
         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, &param_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 9898ec7597d..7868e700f27 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 8d51fda0cf2..34a6a547d94 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 e6d96073529..292d9592ceb 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<F>(&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 b2032e6a1bf..5ed628d7dca 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 763c012a8f8..8f2afa7f808 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<Loan<'tcx>>,
                                         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 cea9170da9f..836832de5b9 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 2f74ea3e475..fb842f70a54 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 afc4ccef0cc..32bda5e1162 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 615aca90db8..e0e8a215919 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 57a5400ecad..ee6c27655d6 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 b4ab9da92e9..ecbf28c1082 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<borrowck_dot::Variant>,
                                        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<borrowck_dot::Variant>,
             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 fea3de59520..e095bde18fd 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 28dc71fd59b..192d7be6774 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 d3fd638d6b5..0668d362037 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 b37dd8dd0a9..902798ec980 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<Item=(Ty<'gcx>, 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 0ffc59fe6bf..af2f9adfc9a 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 f23539e88f7..7a93d4594ee 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 f8994de54a1..417987d9664 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 e942707acd5..e58cd893819 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 c3ef5a72a29..d55ce4c3563 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 d478f1092bd..af834f3f84d 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<ty::ClosureKind>,
                      decl: &'gcx hir::FnDecl,
-                     body: &'gcx hir::Block,
+                     body: &'gcx hir::Expr,
                      expected_sig: Option<ty::FnSig<'tcx>>)
                      -> 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 f7e05f4777e..725862022c5 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 6f6538254c4..d4e5e9a5bb3 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 aa221c33b5d..2fea86cb212 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 741f327ac99..2c1a9a7b177 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 5ef3e869960..9f3214a0d81 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);