diff options
| author | Tim Chevalier <chevalier@alum.wellesley.edu> | 2011-05-27 17:01:08 -0700 |
|---|---|---|
| committer | Tim Chevalier <chevalier@alum.wellesley.edu> | 2011-05-27 17:42:09 -0700 |
| commit | b6e0c5829f5bb87b9a3f0f74b1d98f6ea4cc8cef (patch) | |
| tree | 73a1da2f5f47baa70997b007cf7f3a00de3cc170 /src | |
| parent | 0c5a55f2755138a6ddd2fbdfc7b11a4117409c5e (diff) | |
| download | rust-b6e0c5829f5bb87b9a3f0f74b1d98f6ea4cc8cef.tar.gz rust-b6e0c5829f5bb87b9a3f0f74b1d98f6ea4cc8cef.zip | |
Check the declaration type in a for loop against the sequence type
Changed the typechecker to correctly typecheck the declared variable type in a for or for-each loop against the vector element type (for a for loop) or the iterator type (for a for-each loop). Added a test case.
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp/middle/typeck.rs | 54 | ||||
| -rw-r--r-- | src/test/compile-fail/for-loop-decl.rs | 23 |
2 files changed, 62 insertions, 15 deletions
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 635a9b5b404..0147806efc3 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1872,6 +1872,22 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) { check_call_or_bind(scx, f, args_opt_0); } + // A generic function for checking for or for-each loops + fn check_for_or_for_each(&@stmt_ctxt scx, &@ast::decl decl, + &ty::t element_ty, &ast::block body, + uint node_id) { + check_decl_local(scx.fcx, decl); + check_block(scx, body); + + // Unify type of decl with element type of the seq + demand::simple(scx, decl.span, ty::decl_local_ty(scx.fcx.ccx.tcx, + decl), + element_ty); + + auto typ = ty::mk_nil(scx.fcx.ccx.tcx); + write::ty_only_fixup(scx, node_id, typ); + } + alt (expr.node) { case (ast::expr_lit(?lit, ?a)) { auto typ = check_lit(scx.fcx.ccx, lit); @@ -2000,8 +2016,7 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) { case (none[@ast::expr]) { auto nil = ty::mk_nil(scx.fcx.ccx.tcx); if (!are_compatible(scx, scx.fcx.ret_ty, nil)) { - // TODO: span_err - scx.fcx.ccx.tcx.sess.span_err(expr.span, + scx.fcx.ccx.tcx.sess.span_err(expr.span, "put; in iterator yielding non-nil"); } @@ -2159,24 +2174,33 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) { } case (ast::expr_for(?decl, ?seq, ?body, ?a)) { - check_decl_local(scx.fcx, decl); check_expr(scx, seq); - check_block(scx, body); - - // FIXME: enforce that the type of the decl is the element type - // of the seq. - - auto typ = ty::mk_nil(scx.fcx.ccx.tcx); - write::ty_only_fixup(scx, a.id, typ); + alt (struct (scx.fcx.ccx.tcx, + expr_ty(scx.fcx.ccx.tcx, seq))) { + // FIXME: I include the check_for_or_each call in + // each case because of a bug in typestate; + // once that bug is fixed, the call can be moved + // out of the alt expression + case (ty::ty_vec(?vec_elt_ty)) { + auto elt_ty = vec_elt_ty.ty; + check_for_or_for_each(scx, decl, elt_ty, body, a.id); + } + case (ty::ty_str) { + auto elt_ty = ty::mk_mach(scx.fcx.ccx.tcx, + util::common::ty_u8); + check_for_or_for_each(scx, decl, elt_ty, body, a.id); + } + case (_) { + scx.fcx.ccx.tcx.sess.span_err(expr.span, + "type of for loop iterator is not a vector or string"); + } + } } case (ast::expr_for_each(?decl, ?seq, ?body, ?a)) { - check_decl_local(scx.fcx, decl); check_expr(scx, seq); - check_block(scx, body); - - auto typ = ty::mk_nil(scx.fcx.ccx.tcx); - write::ty_only_fixup(scx, a.id, typ); + check_for_or_for_each(scx, decl, expr_ty(scx.fcx.ccx.tcx, seq), + body, a.id); } case (ast::expr_while(?cond, ?body, ?a)) { diff --git a/src/test/compile-fail/for-loop-decl.rs b/src/test/compile-fail/for-loop-decl.rs new file mode 100644 index 00000000000..00da58e1745 --- /dev/null +++ b/src/test/compile-fail/for-loop-decl.rs @@ -0,0 +1,23 @@ +// error-pattern: mismatched types +use std; +import std::map::hashmap; +import std::bitv; + +type fn_info = rec(hashmap[uint, var_info] vars); +type var_info = rec(uint a, uint b); + +fn bitv_to_str(fn_info enclosing, bitv::t v) -> str { + auto s = ""; + + // error is that the value type in the hash map is var_info, not a tuple + for each (@tup(uint, tup(uint, uint)) p in enclosing.vars.items()) { + if (bitv::get(v, p._1._0)) { + s += "foo"; // " " + p._1._1 + " " + "[" + p._0 + "]"; + } + } + ret s; +} + +fn main() { + log "OK"; +} \ No newline at end of file |
