Skip to content

Commit c2bb2f0

Browse files
committed
When checking loop bodies and do-expr bodies, don't require the expected type to exist
If the expected type is none (due to a type error), we shouldn't fail with an ICE, but rather, just print out another type error. Changed the do-expr type error message to make sense in this context (see the test case for how it works). Closes #3044.
1 parent c9c3a49 commit c2bb2f0

File tree

2 files changed

+21
-10
lines changed

2 files changed

+21
-10
lines changed

src/rustc/middle/typeck/check.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -1316,7 +1316,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
13161316
_ { none }
13171317
}
13181318
}
1319-
ast::not | ast::neg { some(expected.get()) }
1319+
ast::not | ast::neg { expected }
13201320
ast::deref { none }
13211321
}
13221322
};
@@ -1475,10 +1475,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
14751475
capture::check_capture_clause(tcx, expr.id, cap_clause);
14761476
}
14771477
ast::expr_fn_block(decl, body, cap_clause) {
1478+
let proto = unpack_expected(fcx, expected, |sty|
1479+
alt sty { ty::ty_fn({proto, _}) { some(proto) } _ { none } }
1480+
).get_default(ast::proto_box);
14781481
// Take the prototype from the expected type, but default to block:
1479-
let proto = unpack_expected(fcx, expected, |sty|
1480-
alt sty { ty::ty_fn({proto, _}) { some(proto) } _ { none } }
1481-
).get_default(ast::proto_box);
1482+
let proto = proto_1.get_default(ast::proto_box);
14821483
check_expr_fn(fcx, expr, proto, decl, body, false, expected);
14831484
capture::check_capture_clause(tcx, expr.id, cap_clause);
14841485
}
@@ -1489,9 +1490,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
14891490
// parameter. The catch here is that we need to validate two things:
14901491
// 1. a closure that returns a bool is expected
14911492
// 2. the cloure that was given returns unit
1492-
let expected_sty = unpack_expected(fcx, expected, |x| some(x)).get();
1493+
let expected_sty = unpack_expected(fcx, expected, |x| some(x));
14931494
let (inner_ty, proto) = alt expected_sty {
1494-
ty::ty_fn(fty) {
1495+
some(ty::ty_fn(fty)) {
14951496
alt infer::mk_subty(fcx.infcx, fty.output, ty::mk_bool(tcx)) {
14961497
result::ok(_) {}
14971498
result::err(err) {
@@ -1526,14 +1527,15 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
15261527
}
15271528
}
15281529
ast::expr_do_body(b) {
1529-
let expected_sty = unpack_expected(fcx, expected, |x| some(x)).get();
1530+
let expected_sty = unpack_expected(fcx, expected, |x| some(x));
15301531
let (inner_ty, proto) = alt expected_sty {
1531-
ty::ty_fn(fty) {
1532+
some(ty::ty_fn(fty)) {
15321533
(ty::mk_fn(tcx, fty), fty.proto)
15331534
}
15341535
_ {
1535-
tcx.sess.span_fatal(expr.span, ~"a `do` function's last argument \
1536-
should be of function type");
1536+
tcx.sess.span_fatal(expr.span, ~"Non-function passed to a `do` \
1537+
function as its last argument, or wrong number of arguments \
1538+
passed to a `do` function");
15371539
}
15381540
};
15391541
alt check b.node {

src/test/compile-fail/issue-3044.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// error-pattern: Non-function passed to a `do` function as its last argument, or wrong number of arguments passed to a `do` function
2+
fn main() {
3+
let needlesArr: ~[char] = ~['a', 'f'];
4+
do vec::foldr(needlesArr) |x, y| {
5+
}
6+
// for some reason if I use the new error syntax for the two error messages this generates,
7+
// the test runner gets confused -- tjc
8+
}
9+

0 commit comments

Comments
 (0)