about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2013-05-02 18:33:08 -0400
committerAlex Crichton <alex@alexcrichton.com>2013-05-10 02:46:18 -0400
commit0cde8ba684e738fa71ce62d691ba2886776e49f9 (patch)
tree03e2b976872095fa549630f576fd6137a4e9b434
parentad8e236f32fccf6ec99025e2ba77f79b4c98d399 (diff)
downloadrust-0cde8ba684e738fa71ce62d691ba2886776e49f9.tar.gz
rust-0cde8ba684e738fa71ce62d691ba2886776e49f9.zip
Implement a new protocol for `for` loops that's much more easily composable
-rw-r--r--src/librustc/middle/trans/callee.rs9
-rw-r--r--src/librustc/middle/typeck/check/mod.rs26
2 files changed, 30 insertions, 5 deletions
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index e5e60b2d4ac..c530cd97397 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -550,7 +550,14 @@ pub fn trans_call_inner(in_cx: block,
                 // drop the value if it is not being saved.
                 unsafe {
                     if llvm::LLVMIsUndef(llretslot) != lib::llvm::True {
-                        if ty::type_is_immediate(ret_ty) {
+                        if ty::type_is_nil(ret_ty) {
+                            // When implementing the for-loop sugar syntax, the
+                            // type of the for-loop is nil, but the function
+                            // it's invoking returns a bool. This is a special
+                            // case to ignore instead of invoking the Store
+                            // below into a scratch pointer of a mismatched
+                            // type.
+                        } else if ty::type_is_immediate(ret_ty) {
                             let llscratchptr = alloc_ty(bcx, ret_ty);
                             Store(bcx, llresult, llscratchptr);
                             bcx = glue::drop_ty(bcx, llscratchptr, ret_ty);
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index a6f2f0da234..89eef1c7cb7 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -1294,6 +1294,26 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         // The callee checks for bot / err, we don't need to
     }
 
+    fn write_call(fcx: @mut FnCtxt,
+                  call_expr: @ast::expr,
+                  output: ty::t,
+                  sugar: ast::CallSugar) {
+        let ret_ty = match sugar {
+            ast::ForSugar => {
+                match ty::get(output).sty {
+                    ty::ty_bool => {}
+                    _ => fcx.type_error_message(call_expr.span, |actual| {
+                            fmt!("expected `for` closure to return `bool`, \
+                                  but found `%s`", actual) },
+                            output, None)
+                }
+                ty::mk_nil()
+            }
+            _ => output
+        };
+        fcx.write_ty(call_expr.id, ret_ty);
+    }
+
     // A generic function for doing all of the checking for call expressions
     fn check_call(fcx: @mut FnCtxt,
                   call_expr: @ast::expr,
@@ -1344,8 +1364,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         check_argument_types(fcx, call_expr.span, fn_sig.inputs, f,
                              args, sugar, DontDerefArgs);
 
-        // Pull the return type out of the type of the function.
-        fcx.write_ty(call_expr.id, fn_sig.output);
+        write_call(fcx, call_expr, fn_sig.output, sugar);
     }
 
     // Checks a method call.
@@ -1401,8 +1420,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                                                  fn_ty, expr, args, sugar,
                                                  DontDerefArgs);
 
-        // Pull the return type out of the type of the function.
-        fcx.write_ty(expr.id, ret_ty);
+        write_call(fcx, expr, ret_ty, sugar);
     }
 
     // A generic function for checking the then and else in an if