]> git.lizzy.rs Git - rust.git/commitdiff
Move closure checking into its own file. Shrink check/mod.rs!
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 18 Nov 2014 20:00:23 +0000 (15:00 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 19 Nov 2014 10:31:16 +0000 (05:31 -0500)
src/librustc/middle/typeck/check/closure.rs [new file with mode: 0644]
src/librustc/middle/typeck/check/mod.rs

diff --git a/src/librustc/middle/typeck/check/closure.rs b/src/librustc/middle/typeck/check/closure.rs
new file mode 100644 (file)
index 0000000..12b0a90
--- /dev/null
@@ -0,0 +1,193 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+ * Code for type-checking closure expressions.
+ */
+
+use super::check_fn;
+use super::Expectation;
+use super::FnCtxt;
+
+use middle::ty;
+use middle::typeck::astconv;
+use middle::typeck::infer;
+use middle::typeck::rscope::RegionScope;
+use syntax::abi;
+use syntax::ast;
+use syntax::ast_util;
+use util::ppaux::Repr;
+
+pub fn check_unboxed_closure(fcx: &FnCtxt,
+                             expr: &ast::Expr,
+                             kind: ast::UnboxedClosureKind,
+                             decl: &ast::FnDecl,
+                             body: &ast::Block) {
+    let expr_def_id = ast_util::local_def(expr.id);
+
+    let mut fn_ty = astconv::ty_of_closure(
+        fcx,
+        ast::NormalFn,
+        ast::Many,
+
+        // The `RegionTraitStore` and region_existential_bounds
+        // are lies, but we ignore them so it doesn't matter.
+        //
+        // FIXME(pcwalton): Refactor this API.
+        ty::region_existential_bound(ty::ReStatic),
+        ty::RegionTraitStore(ty::ReStatic, ast::MutImmutable),
+
+        decl,
+        abi::RustCall,
+        None);
+
+    let region = match fcx.infcx().anon_regions(expr.span, 1) {
+        Err(_) => {
+            fcx.ccx.tcx.sess.span_bug(expr.span,
+                                      "can't make anon regions here?!")
+        }
+        Ok(regions) => regions[0],
+    };
+
+    let closure_type = ty::mk_unboxed_closure(fcx.ccx.tcx,
+                                              expr_def_id,
+                                              region,
+                                              fcx.inh.param_env.free_substs.clone());
+
+    fcx.write_ty(expr.id, closure_type);
+
+    check_fn(fcx.ccx,
+             ast::NormalFn,
+             expr.id,
+             &fn_ty.sig,
+             decl,
+             expr.id,
+             &*body,
+             fcx.inh);
+
+    // Tuple up the arguments and insert the resulting function type into
+    // the `unboxed_closures` table.
+    fn_ty.sig.inputs = vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.inputs)];
+
+    let kind = match kind {
+        ast::FnUnboxedClosureKind => ty::FnUnboxedClosureKind,
+        ast::FnMutUnboxedClosureKind => ty::FnMutUnboxedClosureKind,
+        ast::FnOnceUnboxedClosureKind => ty::FnOnceUnboxedClosureKind,
+    };
+
+    debug!("unboxed_closure for {} --> sig={} kind={}",
+           expr_def_id.repr(fcx.tcx()),
+           fn_ty.sig.repr(fcx.tcx()),
+           kind);
+
+    let unboxed_closure = ty::UnboxedClosure {
+        closure_type: fn_ty,
+        kind: kind,
+    };
+
+    fcx.inh
+        .unboxed_closures
+        .borrow_mut()
+        .insert(expr_def_id, unboxed_closure);
+}
+
+pub fn check_expr_fn<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
+                              expr: &ast::Expr,
+                              store: ty::TraitStore,
+                              decl: &ast::FnDecl,
+                              body: &ast::Block,
+                              expected: Expectation<'tcx>) {
+    let tcx = fcx.ccx.tcx;
+
+    // Find the expected input/output types (if any). Substitute
+    // fresh bound regions for any bound regions we find in the
+    // expected types so as to avoid capture.
+    let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
+    let (expected_sig,
+         expected_onceness,
+         expected_bounds) = {
+        match expected_sty {
+            Some(ty::ty_closure(ref cenv)) => {
+                let (sig, _) =
+                    ty::replace_late_bound_regions(
+                        tcx,
+                        &cenv.sig,
+                        |_, debruijn| fcx.inh.infcx.fresh_bound_region(debruijn));
+                let onceness = match (&store, &cenv.store) {
+                    // As the closure type and onceness go, only three
+                    // combinations are legit:
+                    //      once closure
+                    //      many closure
+                    //      once proc
+                    // If the actual and expected closure type disagree with
+                    // each other, set expected onceness to be always Once or
+                    // Many according to the actual type. Otherwise, it will
+                    // yield either an illegal "many proc" or a less known
+                    // "once closure" in the error message.
+                    (&ty::UniqTraitStore, &ty::UniqTraitStore) |
+                    (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
+                        cenv.onceness,
+                    (&ty::UniqTraitStore, _) => ast::Once,
+                    (&ty::RegionTraitStore(..), _) => ast::Many,
+                };
+                (Some(sig), onceness, cenv.bounds)
+            }
+            _ => {
+                // Not an error! Means we're inferring the closure type
+                let (bounds, onceness) = match expr.node {
+                    ast::ExprProc(..) => {
+                        let mut bounds = ty::region_existential_bound(ty::ReStatic);
+                        bounds.builtin_bounds.insert(ty::BoundSend); // FIXME
+                        (bounds, ast::Once)
+                    }
+                    _ => {
+                        let region = fcx.infcx().next_region_var(
+                            infer::AddrOfRegion(expr.span));
+                        (ty::region_existential_bound(region), ast::Many)
+                    }
+                };
+                (None, onceness, bounds)
+            }
+        }
+    };
+
+    // construct the function type
+    let fn_ty = astconv::ty_of_closure(fcx,
+                                       ast::NormalFn,
+                                       expected_onceness,
+                                       expected_bounds,
+                                       store,
+                                       decl,
+                                       abi::Rust,
+                                       expected_sig);
+    let fty_sig = fn_ty.sig.clone();
+    let fty = ty::mk_closure(tcx, fn_ty);
+    debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
+
+    fcx.write_ty(expr.id, fty);
+
+    // If the closure is a stack closure and hasn't had some non-standard
+    // style inferred for it, then check it under its parent's style.
+    // Otherwise, use its own
+    let (inherited_style, inherited_style_id) = match store {
+        ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
+                                     fcx.ps.borrow().def),
+        ty::UniqTraitStore => (ast::NormalFn, expr.id)
+    };
+
+    check_fn(fcx.ccx,
+             inherited_style,
+             inherited_style_id,
+             &fty_sig,
+             &*decl,
+             expr.id,
+             &*body,
+             fcx.inh);
+}
index 543eb44697c06ce5fdaaa5c79293326b1330685c..02ac6379a5696916f35ba4885f4d8aa8383e9f72 100644 (file)
 pub mod demand;
 pub mod method;
 pub mod wf;
+mod closure;
 
 /// Fields that are part of a `FnCtxt` which are inherited by
 /// closures defined within the function.  For example:
@@ -3519,174 +3520,6 @@ fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         })
     }
 
-    fn check_unboxed_closure(fcx: &FnCtxt,
-                             expr: &ast::Expr,
-                             kind: ast::UnboxedClosureKind,
-                             decl: &ast::FnDecl,
-                             body: &ast::Block) {
-        let mut fn_ty = astconv::ty_of_closure(
-            fcx,
-            ast::NormalFn,
-            ast::Many,
-
-            // The `RegionTraitStore` and region_existential_bounds
-            // are lies, but we ignore them so it doesn't matter.
-            //
-            // FIXME(pcwalton): Refactor this API.
-            ty::region_existential_bound(ty::ReStatic),
-            ty::RegionTraitStore(ty::ReStatic, ast::MutImmutable),
-
-            decl,
-            abi::RustCall,
-            None);
-
-        let region = match fcx.infcx().anon_regions(expr.span, 1) {
-            Err(_) => {
-                fcx.ccx.tcx.sess.span_bug(expr.span,
-                                          "can't make anon regions here?!")
-            }
-            Ok(regions) => regions[0],
-        };
-        let closure_type = ty::mk_unboxed_closure(fcx.ccx.tcx,
-                                                  local_def(expr.id),
-                                                  region,
-                                                  fcx.inh.param_env.free_substs.clone());
-        fcx.write_ty(expr.id, closure_type);
-
-        check_fn(fcx.ccx,
-                 ast::NormalFn,
-                 expr.id,
-                 &fn_ty.sig,
-                 decl,
-                 expr.id,
-                 &*body,
-                 fcx.inh);
-
-        // Tuple up the arguments and insert the resulting function type into
-        // the `unboxed_closures` table.
-        fn_ty.sig.inputs = vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.inputs)];
-
-        let kind = match kind {
-            ast::FnUnboxedClosureKind => ty::FnUnboxedClosureKind,
-            ast::FnMutUnboxedClosureKind => ty::FnMutUnboxedClosureKind,
-            ast::FnOnceUnboxedClosureKind => ty::FnOnceUnboxedClosureKind,
-        };
-
-        debug!("unboxed_closure for {} --> sig={} kind={}",
-               local_def(expr.id).repr(fcx.tcx()),
-               fn_ty.sig.repr(fcx.tcx()),
-               kind);
-
-        let unboxed_closure = ty::UnboxedClosure {
-            closure_type: fn_ty,
-            kind: kind,
-        };
-
-        fcx.inh
-           .unboxed_closures
-           .borrow_mut()
-           .insert(local_def(expr.id), unboxed_closure);
-    }
-
-    fn check_expr_fn<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                               expr: &ast::Expr,
-                               store: ty::TraitStore,
-                               decl: &ast::FnDecl,
-                               body: &ast::Block,
-                               expected: Expectation<'tcx>) {
-        let tcx = fcx.ccx.tcx;
-
-        debug!("check_expr_fn(expr={}, expected={})",
-               expr.repr(tcx),
-               expected.repr(tcx));
-
-        // Find the expected input/output types (if any). Substitute
-        // fresh bound regions for any bound regions we find in the
-        // expected types so as to avoid capture.
-        let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
-        let (expected_sig,
-             expected_onceness,
-             expected_bounds) = {
-            match expected_sty {
-                Some(ty::ty_closure(ref cenv)) => {
-                    let (sig, _) =
-                        replace_late_bound_regions(
-                            tcx,
-                            &cenv.sig,
-                            |_, debruijn| fcx.inh.infcx.fresh_bound_region(debruijn));
-                    let onceness = match (&store, &cenv.store) {
-                        // As the closure type and onceness go, only three
-                        // combinations are legit:
-                        //      once closure
-                        //      many closure
-                        //      once proc
-                        // If the actual and expected closure type disagree with
-                        // each other, set expected onceness to be always Once or
-                        // Many according to the actual type. Otherwise, it will
-                        // yield either an illegal "many proc" or a less known
-                        // "once closure" in the error message.
-                        (&ty::UniqTraitStore, &ty::UniqTraitStore) |
-                        (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
-                            cenv.onceness,
-                        (&ty::UniqTraitStore, _) => ast::Once,
-                        (&ty::RegionTraitStore(..), _) => ast::Many,
-                    };
-                    (Some(sig), onceness, cenv.bounds)
-                }
-                _ => {
-                    // Not an error! Means we're inferring the closure type
-                    let (bounds, onceness) = match expr.node {
-                        ast::ExprProc(..) => {
-                            let mut bounds = ty::region_existential_bound(ty::ReStatic);
-                            bounds.builtin_bounds.insert(ty::BoundSend); // FIXME
-                            (bounds, ast::Once)
-                        }
-                        _ => {
-                            let region = fcx.infcx().next_region_var(
-                                infer::AddrOfRegion(expr.span));
-                            (ty::region_existential_bound(region), ast::Many)
-                        }
-                    };
-                    (None, onceness, bounds)
-                }
-            }
-        };
-
-        // construct the function type
-        let fn_ty = astconv::ty_of_closure(fcx,
-                                           ast::NormalFn,
-                                           expected_onceness,
-                                           expected_bounds,
-                                           store,
-                                           decl,
-                                           abi::Rust,
-                                           expected_sig);
-        let fty_sig = fn_ty.sig.clone();
-        let fty = ty::mk_closure(tcx, fn_ty);
-        debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
-
-        fcx.write_ty(expr.id, fty);
-
-        // If the closure is a stack closure and hasn't had some non-standard
-        // style inferred for it, then check it under its parent's style.
-        // Otherwise, use its own
-        let (inherited_style, inherited_style_id) = match store {
-            ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
-                                         fcx.ps.borrow().def),
-            ty::UniqTraitStore => (ast::NormalFn, expr.id)
-        };
-
-        check_fn(fcx.ccx,
-                 inherited_style,
-                 inherited_style_id,
-                 &fty_sig,
-                 &*decl,
-                 expr.id,
-                 &*body,
-                 fcx.inh);
-    }
-
-
     // Check field access expressions
     fn check_field(fcx: &FnCtxt,
                    expr: &ast::Expr,
@@ -4320,27 +4153,27 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
                                                        fcx.infcx(),
                                                        expr.span,
                                                        &None);
-        check_expr_fn(fcx,
-                      expr,
-                      ty::RegionTraitStore(region, ast::MutMutable),
-                      &**decl,
-                      &**body,
-                      expected);
+        closure::check_expr_fn(fcx,
+                               expr,
+                               ty::RegionTraitStore(region, ast::MutMutable),
+                               &**decl,
+                               &**body,
+                               expected);
       }
       ast::ExprUnboxedFn(_, kind, ref decl, ref body) => {
-        check_unboxed_closure(fcx,
-                              expr,
-                              kind,
-                              &**decl,
-                              &**body);
+          closure::check_unboxed_closure(fcx,
+                                         expr,
+                                         kind,
+                                         &**decl,
+                                         &**body);
       }
       ast::ExprProc(ref decl, ref body) => {
-        check_expr_fn(fcx,
-                      expr,
-                      ty::UniqTraitStore,
-                      &**decl,
-                      &**body,
-                      expected);
+          closure::check_expr_fn(fcx,
+                                 expr,
+                                 ty::UniqTraitStore,
+                                 &**decl,
+                                 &**body,
+                                 expected);
       }
       ast::ExprBlock(ref b) => {
         check_block_with_expected(fcx, &**b, expected);