about summary refs log tree commit diff
path: root/src/librustc_resolve
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2016-11-10 03:46:28 +0200
committerGitHub <noreply@github.com>2016-11-10 03:46:28 +0200
commit368281a11063e1f3e73832f7fdd321647182692b (patch)
treef99aea3896836097aee24548dbc03f870b69fbe1 /src/librustc_resolve
parent8d4a3500ff51dc4352fae847529451d51474ab0f (diff)
parent8e9106c531c559bf923de93cccbeb0fa0a47451f (diff)
downloadrust-368281a11063e1f3e73832f7fdd321647182692b.tar.gz
rust-368281a11063e1f3e73832f7fdd321647182692b.zip
Rollup merge of #37412 - eddyb:lazy-6, r=nikomatsakis
[6/n] rustc: transition HIR function bodies from Block to Expr.

_This is part of a series ([prev](https://github.com/rust-lang/rust/pull/37408) | [next](https://github.com/rust-lang/rust/pull/37676)) of patches designed to rework rustc into an out-of-order on-demand pipeline model for both better feature support (e.g. [MIR-based](https://github.com/solson/miri) early constant evaluation) and incremental execution of compiler passes (e.g. type-checking), with beneficial consequences to IDE support as well.
If any motivation is unclear, please ask for additional PR description clarifications or code comments._

<hr>

The main change here is that functions and closures both use `Expr` instead of `Block` for their bodies.
For closures this actually allows a honest representation of brace-less closure bodies, e.g. `|x| x + 1` is now distinguishable from `|x| { x + 1 }`, therefore this PR is `[syntax-breaking]` (cc @Manishearth).

Using `Expr` allows more logic to be shared between constant bodies and function bodies, with some small such changes already part of this PR, and eventually easing #35078 and per-body type tables.

Incidentally, there used to be some corners cut here and there and as such I had to (re)write divergence tracking for type-checking so that it is capable of understanding basic structured control-flow:

``` rust
fn a(x: bool) -> i32 {
    // match also works (as long as all arms diverge)
    if x { panic!("true") } else { return 1; }
    0 // "unreachable expression" after this PR
}
```

And since liveness' "not all control paths return a value" moved to type-checking we can have nice things:

``` rust
// before & after:
fn b() -> i32 { 0; } // help: consider removing this semicolon

// only after this PR
fn c() -> i32 { { 0; } } // help: consider removing this semicolon
fn d() { let x: i32 = { 0; }; } // help: consider removing this semicolon
fn e() { f({ 0; }); } // help: consider removing this semicolon
```
Diffstat (limited to 'src/librustc_resolve')
-rw-r--r--src/librustc_resolve/lib.rs69
1 files changed, 35 insertions, 34 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 0c7c1a55a61..664efc27fbb 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -596,7 +596,6 @@ impl<'a> Visitor for Resolver<'a> {
     fn visit_fn(&mut self,
                 function_kind: FnKind,
                 declaration: &FnDecl,
-                block: &Block,
                 _: Span,
                 node_id: NodeId) {
         let rib_kind = match function_kind {
@@ -604,13 +603,45 @@ impl<'a> Visitor for Resolver<'a> {
                 self.visit_generics(generics);
                 ItemRibKind
             }
-            FnKind::Method(_, sig, _) => {
+            FnKind::Method(_, sig, _, _) => {
                 self.visit_generics(&sig.generics);
                 MethodRibKind(!sig.decl.has_self())
             }
-            FnKind::Closure => ClosureRibKind(node_id),
+            FnKind::Closure(_) => ClosureRibKind(node_id),
         };
-        self.resolve_function(rib_kind, declaration, block);
+
+        // Create a value rib for the function.
+        self.value_ribs.push(Rib::new(rib_kind));
+
+        // Create a label rib for the function.
+        self.label_ribs.push(Rib::new(rib_kind));
+
+        // Add each argument to the rib.
+        let mut bindings_list = FxHashMap();
+        for argument in &declaration.inputs {
+            self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
+
+            self.visit_ty(&argument.ty);
+
+            debug!("(resolving function) recorded argument");
+        }
+        visit::walk_fn_ret_ty(self, &declaration.output);
+
+        // Resolve the function body.
+        match function_kind {
+            FnKind::ItemFn(.., body) |
+            FnKind::Method(.., body) => {
+                self.visit_block(body);
+            }
+            FnKind::Closure(body) => {
+                self.visit_expr(body);
+            }
+        };
+
+        debug!("(resolving function) leaving function");
+
+        self.label_ribs.pop();
+        self.value_ribs.pop();
     }
 }
 
@@ -1856,36 +1887,6 @@ impl<'a> Resolver<'a> {
         self.value_ribs.pop();
     }
 
-    fn resolve_function(&mut self,
-                        rib_kind: RibKind<'a>,
-                        declaration: &FnDecl,
-                        block: &Block) {
-        // Create a value rib for the function.
-        self.value_ribs.push(Rib::new(rib_kind));
-
-        // Create a label rib for the function.
-        self.label_ribs.push(Rib::new(rib_kind));
-
-        // Add each argument to the rib.
-        let mut bindings_list = FxHashMap();
-        for argument in &declaration.inputs {
-            self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
-
-            self.visit_ty(&argument.ty);
-
-            debug!("(resolving function) recorded argument");
-        }
-        visit::walk_fn_ret_ty(self, &declaration.output);
-
-        // Resolve the function body.
-        self.visit_block(block);
-
-        debug!("(resolving function) leaving function");
-
-        self.label_ribs.pop();
-        self.value_ribs.pop();
-    }
-
     fn resolve_trait_reference(&mut self,
                                id: NodeId,
                                trait_path: &Path,