diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2016-11-10 03:46:28 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-11-10 03:46:28 +0200 |
| commit | 368281a11063e1f3e73832f7fdd321647182692b (patch) | |
| tree | f99aea3896836097aee24548dbc03f870b69fbe1 /src/librustc_resolve | |
| parent | 8d4a3500ff51dc4352fae847529451d51474ab0f (diff) | |
| parent | 8e9106c531c559bf923de93cccbeb0fa0a47451f (diff) | |
| download | rust-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.rs | 69 |
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, |
