Skip to content

Commit c9ae548

Browse files
committed
Reject programs that do a put outside of iterators.
Closes #774.
1 parent 8871462 commit c9ae548

File tree

2 files changed

+9
-6
lines changed

2 files changed

+9
-6
lines changed

src/comp/middle/typeck.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ type fn_ctxt =
6767
// (and with any functions whose environment is being captured).
6868
{ret_ty: ty::t,
6969
purity: ast::purity,
70+
proto: ast::proto,
7071
var_bindings: @ty::unify::var_bindings,
7172
locals: hashmap[ast::node_id, int],
7273
local_names: hashmap[ast::node_id, ast::ident],
@@ -1883,22 +1884,24 @@ fn check_expr(fcx: &@fn_ctxt, expr: &@ast::expr) -> bool {
18831884
}
18841885
ast::expr_put(expr_opt) {
18851886
require_impure(tcx.sess, fcx.purity, expr.span);
1887+
if (fcx.proto != ast::proto_iter) {
1888+
tcx.sess.span_fatal(expr.span, "put in non-iterator");
1889+
}
18861890
alt expr_opt {
18871891
none. {
18881892
let nil = ty::mk_nil(tcx);
18891893
if !are_compatible(fcx, fcx.ret_ty, nil) {
18901894
tcx.sess.span_fatal(expr.span,
18911895
"put; in iterator yielding non-nil");
18921896
}
1893-
write::nil_ty(tcx, id);
18941897
}
18951898
some(e) {
18961899
bot = check_expr(fcx, e);
18971900
demand::simple(fcx, expr.span, fcx.ret_ty,
18981901
expr_ty(tcx, e));
1899-
write::nil_ty(tcx, id);
19001902
}
19011903
}
1904+
write::nil_ty(tcx, id);
19021905
}
19031906
ast::expr_be(e) {
19041907
// FIXME: prove instead of assert
@@ -2619,12 +2622,12 @@ fn check_const(ccx: &@crate_ctxt, sp: &span, e: &@ast::expr,
26192622
id: &ast::node_id) {
26202623
// FIXME: this is kinda a kludge; we manufacture a fake function context
26212624
// and statement context for checking the initializer expression.
2622-
26232625
let rty = node_id_to_type(ccx.tcx, id);
26242626
let fixups: ast::node_id[] = ~[];
26252627
let fcx: @fn_ctxt =
26262628
@{ret_ty: rty,
26272629
purity: ast::pure_fn,
2630+
proto: ast::proto_fn,
26282631
var_bindings: ty::unify::mk_var_bindings(),
26292632
locals: new_int_hash[int](),
26302633
local_names: new_int_hash[ast::ident](),
@@ -2643,13 +2646,13 @@ fn check_fn(ccx: &@crate_ctxt, f: &ast::_fn, id: &ast::node_id,
26432646
let fcx: @fn_ctxt =
26442647
@{ret_ty: ast_ty_to_ty_crate(ccx, decl.output),
26452648
purity: decl.purity,
2649+
proto: f.proto,
26462650
var_bindings: gather_result.var_bindings,
26472651
locals: gather_result.locals,
26482652
local_names: gather_result.local_names,
26492653
next_var_id: gather_result.next_var_id,
26502654
mutable fixups: fixups,
26512655
ccx: ccx};
2652-
26532656
check_block(fcx, body);
26542657
alt decl.purity {
26552658
ast::pure_fn. {

src/test/compile-fail/put-in-fn.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// xfail-stage1
22
// xfail-stage2
33
// xfail-stage3
4-
// error-pattern: iterator function
4+
// error-pattern:put in non-iterator
55

66
fn f() -> int { put 10; }
77

8-
fn main() { }
8+
fn main() { }

0 commit comments

Comments
 (0)