diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2013-05-02 18:33:08 -0400 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-05-10 02:46:18 -0400 |
| commit | 0cde8ba684e738fa71ce62d691ba2886776e49f9 (patch) | |
| tree | 03e2b976872095fa549630f576fd6137a4e9b434 | |
| parent | ad8e236f32fccf6ec99025e2ba77f79b4c98d399 (diff) | |
| download | rust-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.rs | 9 | ||||
| -rw-r--r-- | src/librustc/middle/typeck/check/mod.rs | 26 |
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 |
