about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2013-03-26 16:27:34 -0400
committerNiko Matsakis <niko@alum.mit.edu>2013-04-05 05:36:02 -0400
commit1745a2cd08d1aa7437ec3d080c9ca85434b54cf5 (patch)
tree40ce12443253358a276dd6f649196c0deac97a16
parentbabe50633349cd29f0a0757079e0e13bdc0310fa (diff)
downloadrust-1745a2cd08d1aa7437ec3d080c9ca85434b54cf5.tar.gz
rust-1745a2cd08d1aa7437ec3d080c9ca85434b54cf5.zip
refactor check_call_inner to have a better name and be readable
-rw-r--r--src/librustc/middle/typeck/check/mod.rs190
1 files changed, 86 insertions, 104 deletions
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index eba207f978b..516ec3a50cd 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -1122,9 +1122,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                                unifier: &fn()) {
     debug!(">> typechecking %s", fcx.expr_to_str(expr));
 
-    // A generic function to factor out common logic from call and
-    // overloaded operations
-    fn check_call_inner(
+    fn check_argument_types(
         fcx: @mut FnCtxt,
         sp: span,
         call_expr_id: ast::node_id,
@@ -1134,18 +1132,24 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         sugar: ast::CallSugar,
         deref_args: DerefArgs) -> ty::t
     {
+        /*!
+         *
+         * Generic function that factors out common logic from
+         * function calls, method calls and overloaded operators.
+         */
+
         let tcx = fcx.ccx.tcx;
 
         // Replace all region parameters in the arguments and return
         // type with fresh region variables.
 
-        debug!("check_call_inner: before universal quant., in_fty=%s",
+        debug!("check_argument_types: before universal quant., in_fty=%s",
                fcx.infcx().ty_to_str(in_fty));
 
-        let formal_tys;
+        let sty = structure_of(fcx, sp, in_fty);
 
         // FIXME(#3678) For now, do not permit calls to C abi functions.
-        match structure_of(fcx, sp, in_fty) {
+        match sty {
             ty::ty_bare_fn(ty::BareFnTy {abis, _}) => {
                 if !abis.is_rust() {
                     tcx.sess.span_err(
@@ -1157,68 +1161,65 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
             _ => {}
         }
 
-        // This is subtle: we expect `fty` to be a function type, which
-        // normally introduce a level of binding.  In this case, we want to
-        // process the types bound by the function but not by any nested
-        // functions.  Therefore, we match one level of structure.
-        let ret_ty = match structure_of(fcx, sp, in_fty) {
-            ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
-            ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
-                let (_, _, sig) =
-                    replace_bound_regions_in_fn_sig(
-                        tcx, @Nil, None, sig,
-                        |_br| fcx.infcx().next_region_var(
-                            sp, call_expr_id));
-
-                let supplied_arg_count = args.len();
-
-                // Grab the argument types, supplying fresh type variables
-                // if the wrong number of arguments were supplied
-                let expected_arg_count = sig.inputs.len();
-                formal_tys = if expected_arg_count == supplied_arg_count {
-                    sig.inputs.map(|a| a.ty)
-                } else {
-                    let suffix = match sugar {
-                        ast::NoSugar => "",
-                        ast::DoSugar => " (including the closure passed by \
-                                         the `do` keyword)",
-                        ast::ForSugar => " (including the closure passed by \
-                                          the `for` keyword)"
-                    };
-                    let msg = fmt!("this function takes %u parameter%s but \
-                                    %u parameter%s supplied%s",
-                                   expected_arg_count,
-                                   if expected_arg_count == 1 {""}
-                                   else {"s"},
-                                   supplied_arg_count,
-                                   if supplied_arg_count == 1 {" was"}
-                                   else {"s were"},
-                                   suffix);
-
-                    tcx.sess.span_err(sp, msg);
-
-                    vec::from_fn(supplied_arg_count, |_| ty::mk_err(tcx))
-                };
-
-                sig.output
-            }
-
+        // Extract the function signature from `in_fty`.
+        let sig = match sty {
+            ty::ty_bare_fn(ty::BareFnTy {sig: sig, _}) |
+            ty::ty_closure(ty::ClosureTy {sig: sig, _}) => sig,
             _ => {
                 fcx.type_error_message(sp, |actual| {
-                    fmt!("expected function or foreign function but \
+                    fmt!("expected function but \
                           found `%s`", actual) }, in_fty, None);
 
                 // check each arg against "error", in order to set up
                 // all the node type bindings
-                formal_tys = args.map(|_x| ty::mk_err(tcx));
-                ty::mk_err(tcx)
+                FnSig {bound_lifetime_names: opt_vec::Empty,
+                       inputs: args.map(|_x| ty::arg {mode: ast::expl(ast::by_copy),
+                                                      ty: ty::mk_err(tcx)}),
+                       output: ty::mk_err(tcx)}
             }
         };
 
-        debug!("check_call_inner: after universal quant., \
-                formal_tys=%? ret_ty=%s",
+        // Replace any bound regions that appear in the function
+        // signature with region variables
+        let (_, _, sig) =
+            replace_bound_regions_in_fn_sig(
+                tcx, @Nil, None, &sig,
+                |_br| fcx.infcx().next_region_var(
+                    sp, call_expr_id));
+
+        // Grab the argument types, supplying fresh type variables
+        // if the wrong number of arguments were supplied
+        let supplied_arg_count = args.len();
+        let expected_arg_count = sig.inputs.len();
+        let formal_tys = if expected_arg_count == supplied_arg_count {
+            sig.inputs.map(|a| a.ty)
+        } else {
+            let suffix = match sugar {
+                ast::NoSugar => "",
+                ast::DoSugar => " (including the closure passed by \
+                                 the `do` keyword)",
+                ast::ForSugar => " (including the closure passed by \
+                                  the `for` keyword)"
+            };
+            let msg = fmt!("this function takes %u parameter%s but \
+                            %u parameter%s supplied%s",
+                           expected_arg_count,
+                           if expected_arg_count == 1 {""}
+                           else {"s"},
+                           supplied_arg_count,
+                           if supplied_arg_count == 1 {" was"}
+                           else {"s were"},
+                           suffix);
+
+            tcx.sess.span_err(sp, msg);
+
+            vec::from_elem(supplied_arg_count, ty::mk_err(tcx))
+        };
+
+        debug!("check_argument_types: after universal quant., \
+                formal_tys=%? sig.output=%s",
                formal_tys.map(|t| fcx.infcx().ty_to_str(*t)),
-               fcx.infcx().ty_to_str(ret_ty));
+               fcx.infcx().ty_to_str(sig.output));
 
         // Check the arguments.
         // We do this in a pretty awful way: first we typecheck any arguments
@@ -1269,7 +1270,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
             }
         }
 
-        ret_ty
+        sig.output
     }
 
     // A generic function for checking assignment expressions
@@ -1284,43 +1285,23 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         // The callee checks for bot / err, we don't need to
     }
 
-    // A generic function for doing all of the checking for call or
-    // method expressions
-    fn check_call_or_method(fcx: @mut FnCtxt,
-                            sp: span,
-                            call_expr_id: ast::node_id,
-                            fn_ty: ty::t,
-                            expr: @ast::expr,
-                            args: &[@ast::expr],
-                            sugar: ast::CallSugar)
-    {
-
-        // Call the generic checker.
-        let ret_ty = check_call_inner(fcx, sp, call_expr_id,
-                                           fn_ty, expr, args, sugar,
-                                           DontDerefArgs);
-        // Pull the return type out of the type of the function.
-        fcx.write_ty(call_expr_id, ret_ty);
-        // Callee checks for bot and err, no need for that
-    }
-
     // A generic function for doing all of the checking for call expressions
     fn check_call(fcx: @mut FnCtxt,
-                  sp: span,
-                  call_expr_id: ast::node_id,
+                  call_expr: @ast::expr,
                   f: @ast::expr,
                   args: &[@ast::expr],
                   sugar: ast::CallSugar) {
         // Index expressions need to be handled separately, to inform them
         // that they appear in call position.
-        let mut _bot = check_expr(fcx, f);
-        check_call_or_method(fcx,
-                             sp,
-                             call_expr_id,
-                             fcx.expr_ty(f),
-                             f,
-                             args,
-                             sugar)
+        check_expr(fcx, f);
+
+        // Call the generic checker.
+        let ret_ty = check_argument_types(fcx, call_expr.span, call_expr.id,
+                                          fcx.expr_ty(f), f, args, sugar,
+                                          DontDerefArgs);
+
+        // Pull the return type out of the type of the function.
+        fcx.write_ty(call_expr.id, ret_ty);
     }
 
     // Checks a method call.
@@ -1369,13 +1350,14 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
             }
         }
 
-        check_call_or_method(fcx,
-                             expr.span,
-                             expr.id,
-                             fcx.node_ty(expr.callee_id),
-                             expr,
-                             args,
-                             sugar)
+        // Call the generic checker.
+        let fn_ty = fcx.node_ty(expr.callee_id);
+        let ret_ty = check_argument_types(fcx, expr.span, expr.id,
+                                          fn_ty, expr, args, sugar,
+                                          DontDerefArgs);
+
+        // Pull the return type out of the type of the function.
+        fcx.write_ty(expr.id, ret_ty);
     }
 
     // A generic function for checking the then and else in an if
@@ -1423,10 +1405,10 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                 let method_ty = fcx.node_ty(op_ex.callee_id);
                 let method_map = fcx.inh.method_map;
                 method_map.insert(op_ex.id, *origin);
-                check_call_inner(fcx, op_ex.span,
-                                 op_ex.id, method_ty,
-                                 op_ex, args,
-                                 ast::NoSugar, deref_args)
+                check_argument_types(fcx, op_ex.span,
+                                     op_ex.id, method_ty,
+                                     op_ex, args,
+                                     ast::NoSugar, deref_args)
             }
             _ => {
                 let tcx = fcx.tcx();
@@ -1434,9 +1416,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                 // Check the args anyway
                 // so we get all the error messages
                 let expected_ty = ty::mk_err(tcx);
-                check_call_inner(fcx, op_ex.span, op_ex.id,
-                                 expected_ty, op_ex, args,
-                                 ast::NoSugar, deref_args);
+                check_argument_types(fcx, op_ex.span, op_ex.id,
+                                     expected_ty, op_ex, args,
+                                     ast::NoSugar, deref_args);
                 ty::mk_err(tcx)
             }
         }
@@ -2546,7 +2528,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         fcx.write_ty(id, fcx.node_ty(b.node.id));
       }
       ast::expr_call(f, ref args, sugar) => {
-          check_call(fcx, expr.span, expr.id, f, *args, sugar);
+          check_call(fcx, expr, f, *args, sugar);
           let f_ty = fcx.expr_ty(f);
           let (args_bot, args_err) = args.foldl((false, false),
              |&(rest_bot, rest_err), a| {