From 0cde8ba684e738fa71ce62d691ba2886776e49f9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 2 May 2013 18:33:08 -0400 Subject: [PATCH] Implement a new protocol for `for` loops that's much more easily composable --- src/librustc/middle/trans/callee.rs | 9 ++++++++- 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 e5e60b2d4ac3..c530cd973978 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 a6f2f0da234d..89eef1c7cb7f 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