diff options
| author | Marijn Haverbeke <marijnh@gmail.com> | 2011-11-21 10:56:00 +0100 |
|---|---|---|
| committer | Marijn Haverbeke <marijnh@gmail.com> | 2011-11-21 11:01:15 +0100 |
| commit | b4217b383bbbebafbdc621f31716d5bee3cd0c72 (patch) | |
| tree | 14713c2dbf711758939b4ee4db22de5db25e6e57 /src/comp/middle | |
| parent | 86c1f16a1066317fdde988c0357e21ecdb336fca (diff) | |
| download | rust-b4217b383bbbebafbdc621f31716d5bee3cd0c72.tar.gz rust-b4217b383bbbebafbdc621f31716d5bee3cd0c72.zip | |
Add a pass that checks that blocks are only used in safe ways
Closes #1188
Diffstat (limited to 'src/comp/middle')
| -rw-r--r-- | src/comp/middle/block_use.rs | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/comp/middle/block_use.rs b/src/comp/middle/block_use.rs new file mode 100644 index 00000000000..78a49692e01 --- /dev/null +++ b/src/comp/middle/block_use.rs @@ -0,0 +1,41 @@ +import syntax::visit; +import syntax::ast::*; + +type ctx = {tcx: ty::ctxt, mutable allow_block: bool}; + +fn check_crate(tcx: ty::ctxt, crate: @crate) { + let cx = {tcx: tcx, mutable allow_block: false}; + let v = visit::mk_vt(@{visit_expr: visit_expr + with *visit::default_visitor()}); + visit::visit_crate(*crate, cx, v); +} + +fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) { + if !cx.allow_block { + alt ty::struct(cx.tcx, ty::expr_ty(cx.tcx, ex)) { + ty::ty_fn(proto_block., _, _, _, _) { + cx.tcx.sess.span_err(ex.span, "expressions with block type \ + can only appear in callee or (by-ref) argument position"); + } + _ {} + } + } + let outer = cx.allow_block; + alt ex.node { + expr_call(f, args, _) { + cx.allow_block = true; + v.visit_expr(f, cx, v); + let i = 0u; + for arg_t in ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f)) { + cx.allow_block = arg_t.mode == by_ref; + v.visit_expr(args[i], cx, v); + i += 1u; + } + } + _ { + cx.allow_block = false; + visit::visit_expr(ex, cx, v); + } + } + cx.allow_block = outer; +} |
