Permalink
Browse files

more sound treatment of fn& regions; change all & to be distinct

  • Loading branch information...
1 parent 8ee79c7 commit 652b312122139501ae513e9c985d9c31030684b3 @nikomatsakis nikomatsakis committed Aug 20, 2012
Showing with 229 additions and 133 deletions.
  1. +1 −1 src/libcore/option.rs
  2. +1 −1 src/libstd/arc.rs
  3. +1 −1 src/libstd/sync.rs
  4. +3 −2 src/libsyntax/ast.rs
  5. +4 −4 src/libsyntax/ast_util.rs
  6. +0 −3 src/rustc/driver/driver.rs
  7. +5 −1 src/rustc/metadata/tydecode.rs
  8. +5 −1 src/rustc/metadata/tyencode.rs
  9. +5 −2 src/rustc/middle/astencode.rs
  10. +0 −47 src/rustc/middle/block_use.rs
  11. +1 −1 src/rustc/middle/freevars.rs
  12. +2 −2 src/rustc/middle/kind.rs
  13. +1 −1 src/rustc/middle/mem_categorization.rs
  14. +5 −4 src/rustc/middle/resolve3.rs
  15. +1 −1 src/rustc/middle/trans/base.rs
  16. +2 −1 src/rustc/middle/trans/foreign.rs
  17. +1 −1 src/rustc/middle/tstate/auxiliary.rs
  18. +6 −5 src/rustc/middle/ty.rs
  19. +3 −2 src/rustc/middle/typeck/check.rs
  20. +79 −0 src/rustc/middle/typeck/check/regionck.rs
  21. +1 −1 src/rustc/middle/typeck/check/regionmanip.rs
  22. +1 −1 src/rustc/middle/typeck/check/vtable.rs
  23. +8 −3 src/rustc/middle/typeck/rscope.rs
  24. +0 −1 src/rustc/rustc.rc
  25. +16 −10 src/rustc/util/ppaux.rs
  26. +3 −1 src/test/bench/shootout-binarytrees.rs
  27. +0 −8 src/test/compile-fail/block-copy.rs
  28. +1 −1 src/test/compile-fail/borrowck-confuse-region.rs
  29. +0 −8 src/test/compile-fail/issue-1896.rs
  30. +9 −0 src/test/compile-fail/regions-freevar.rs
  31. +1 −1 src/test/compile-fail/regions-glb-free-free.rs
  32. +1 −1 src/test/compile-fail/regions-infer-borrow-scope-too-big.rs
  33. +1 −1 src/test/compile-fail/regions-infer-borrow-scope-within-loop.rs
  34. +1 −1 src/test/compile-fail/regions-infer-call-3.rs
  35. +15 −0 src/test/compile-fail/regions-steal-closure.rs
  36. +1 −1 src/test/run-pass/borrowck-root-while-cond.rs
  37. +2 −2 src/test/run-pass/explicit-self.rs
  38. +1 −1 src/test/run-pass/issue-2748-b.rs
  39. +1 −1 src/test/run-pass/region-return-interior-of-option.rs
  40. +1 −1 src/test/run-pass/regions-addr-of-interior-of-unique-box.rs
  41. +15 −0 src/test/run-pass/regions-copy-closure.rs
  42. +1 −1 src/test/run-pass/regions-creating-enums2.rs
  43. +1 −1 src/test/run-pass/regions-escape-into-other-fn.rs
  44. +1 −1 src/test/run-pass/regions-infer-borrow-scope-view.rs
  45. +1 −1 src/test/run-pass/regions-infer-borrow-scope-within-loop-ok.rs
  46. +1 −1 src/test/run-pass/regions-infer-borrow-scope.rs
  47. +1 −1 src/test/run-pass/regions-mock-trans-impls.rs
  48. +1 −1 src/test/run-pass/regions-nullary-variant.rs
  49. +1 −1 src/test/run-pass/regions-params.rs
  50. +16 −0 src/test/run-pass/regions-static-closure.rs
View
@@ -29,7 +29,7 @@ pure fn get<T: copy>(opt: option<T>) -> T {
}
}
-pure fn get_ref<T>(opt: &option<T>) -> &T {
+pure fn get_ref<T>(opt: &r/option<T>) -> &r/T {
/*!
* Gets an immutable reference to the value inside an option.
*
View
@@ -361,7 +361,7 @@ impl<T: const send> &rw_arc<T> {
}
/// To be called inside of the write_downgrade block.
- fn downgrade(+token: rw_write_mode<T>) -> rw_read_mode<T> {
+ fn downgrade(+token: rw_write_mode/&a<T>) -> rw_read_mode/&a<T> {
// The rwlock should assert that the token belongs to us for us.
let state = unsafe { get_shared_immutable_state(&self.x) };
let rw_write_mode((data, t, _poison)) = token;
View
@@ -538,7 +538,7 @@ impl &rwlock {
}
/// To be called inside of the write_downgrade block.
- fn downgrade(+token: rwlock_write_mode) -> rwlock_read_mode {
+ fn downgrade(+token: rwlock_write_mode/&a) -> rwlock_read_mode/&a {
if !ptr::ref_eq(self, token.lock) {
fail ~"Can't downgrade() with a different rwlock's write_mode!";
}
View
@@ -84,9 +84,10 @@ enum def {
def_ty_param(def_id, uint),
def_binding(node_id, binding_mode),
def_use(def_id),
- def_upvar(node_id /* local id of closed over var */,
+ def_upvar(node_id /* id of closed over var */,
@def /* closed over def */,
- node_id /* expr node that creates the closure */),
+ node_id /* expr node that creates the closure */,
+ node_id /* id for the block/body of the closure expr */),
def_class(def_id, bool /* has constructor */),
def_typaram_binder(node_id), /* class, impl or trait that has ty params */
def_region(node_id),
@@ -60,7 +60,7 @@ pure fn def_id_of_def(d: def) -> def_id {
id
}
def_arg(id, _) | def_local(id, _) | def_self(id) |
- def_upvar(id, _, _) | def_binding(id, _) | def_region(id)
+ def_upvar(id, _, _, _) | def_binding(id, _) | def_region(id)
| def_typaram_binder(id) | def_label(id) => {
local_def(id)
}
@@ -381,9 +381,9 @@ impl inlined_item: inlined_item_utils {
referring to a def_self */
fn is_self(d: ast::def) -> bool {
match d {
- def_self(_) => true,
- def_upvar(_, d, _) => is_self(*d),
- _ => false
+ def_self(_) => true,
+ def_upvar(_, d, _, _) => is_self(*d),
+ _ => false
}
}
@@ -207,9 +207,6 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
if upto == cu_typeck { return {crate: crate, tcx: some(ty_cx)}; }
- time(time_passes, ~"block-use checking", ||
- middle::block_use::check_crate(ty_cx, crate));
-
time(time_passes, ~"loop checking", ||
middle::check_loop::check_crate(ty_cx, crate));
@@ -128,7 +128,11 @@ fn parse_substs(st: @pstate, conv: conv_did) -> ty::substs {
fn parse_bound_region(st: @pstate) -> ty::bound_region {
match check next(st) {
's' => ty::br_self,
- 'a' => ty::br_anon,
+ 'a' => {
+ let id = parse_int(st) as uint;
+ assert next(st) == '|';
+ ty::br_anon(id)
+ }
'[' => ty::br_named(@parse_str(st, ']')),
'c' => {
let id = parse_int(st);
@@ -154,7 +154,11 @@ fn enc_region(w: io::Writer, cx: @ctxt, r: ty::region) {
fn enc_bound_region(w: io::Writer, br: ty::bound_region) {
match br {
ty::br_self => w.write_char('s'),
- ty::br_anon => w.write_char('a'),
+ ty::br_anon(idx) => {
+ w.write_char('a');
+ w.write_uint(idx);
+ w.write_char('|');
+ }
ty::br_named(s) => {
w.write_char('[');
w.write_str(*s);
@@ -363,8 +363,11 @@ impl ast::def: tr {
ast::def_ty_param(did, v) => ast::def_ty_param(did.tr(xcx), v),
ast::def_binding(nid, bm) => ast::def_binding(xcx.tr_id(nid), bm),
ast::def_use(did) => ast::def_use(did.tr(xcx)),
- ast::def_upvar(nid1, def, nid2) => {
- ast::def_upvar(xcx.tr_id(nid1), @(*def).tr(xcx), xcx.tr_id(nid2))
+ ast::def_upvar(nid1, def, nid2, nid3) => {
+ ast::def_upvar(xcx.tr_id(nid1),
+ @(*def).tr(xcx),
+ xcx.tr_id(nid2),
+ xcx.tr_id(nid3))
}
ast::def_class(did, has_constructor) => {
ast::def_class(did.tr(xcx), has_constructor)
@@ -1,47 +0,0 @@
-import syntax::visit;
-import syntax::ast::*;
-import driver::session::session;
-
-type ctx = {tcx: ty::ctxt, mut allow_block: bool};
-
-fn check_crate(tcx: ty::ctxt, crate: @crate) {
- let cx = {tcx: tcx, mut 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 {
- match ty::get(ty::expr_ty(cx.tcx, ex)).struct {
- ty::ty_fn({proto: p, _}) if ty::is_blockish(p) => {
- cx.tcx.sess.span_err(ex.span,
- ~"expressions with stack closure type \
- can only appear in callee or (by-ref) argument position");
- }
- _ => {}
- }
- }
- let outer = cx.allow_block;
- match ex.node {
- expr_call(f, args, _) => {
- cx.allow_block = true;
- v.visit_expr(f, cx, v);
- let mut i = 0u;
- for ty::ty_fn_args(ty::expr_ty(cx.tcx, f)).each |arg_t| {
- cx.allow_block = (ty::arg_mode(cx.tcx, arg_t) == by_ref);
- v.visit_expr(args[i], cx, v);
- i += 1u;
- }
- }
- expr_loop_body(body) | expr_do_body(body) => {
- cx.allow_block = true;
- v.visit_expr(body, cx, v);
- }
- _ => {
- cx.allow_block = false;
- visit::visit_expr(ex, cx, v);
- }
- }
- cx.allow_block = outer;
-}
@@ -55,7 +55,7 @@ fn collect_freevars(def_map: resolve3::DefMap, blk: ast::blk)
let mut def = df;
while i < depth {
match copy def {
- ast::def_upvar(_, inner, _) => { def = *inner; }
+ ast::def_upvar(_, inner, _, _) => { def = *inner; }
_ => break
}
i += 1;
View
@@ -103,7 +103,7 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) {
// copied in data must be copyable, but moved in data can be anything
let is_implicit = fv.is_some();
- if !is_move { check_copy(cx, id, var_t, sp, is_implicit); }
+ if !is_move { check_copy(cx, id, var_t, sp, is_implicit); }
// check that only immutable variables are implicitly copied in
for fv.each |fv| {
@@ -426,7 +426,7 @@ fn check_imm_free_var(cx: ctx, def: def, sp: span) {
}
}
}
- def_upvar(_, def1, _) => {
+ def_upvar(_, def1, _, _) => {
check_imm_free_var(cx, *def1, sp);
}
def_binding(*) | def_self(*) => { /*ok*/ }
@@ -378,7 +378,7 @@ impl &mem_categorization_ctxt {
mutbl:m_imm, ty:expr_ty}
}
- ast::def_upvar(upvid, inner, fn_node_id) => {
+ ast::def_upvar(upvid, inner, fn_node_id, _) => {
let ty = ty::node_id_to_type(self.tcx, fn_node_id);
let proto = ty::ty_fn_proto(ty);
match proto {
@@ -199,7 +199,7 @@ enum RibKind {
// We passed through a function scope at the given node ID. Translate
// upvars as appropriate.
- FunctionRibKind(node_id),
+ FunctionRibKind(node_id /* func id */, node_id /* body id */),
// We passed through a class, impl, or trait and are now in one of its
// methods. Allow references to ty params that that class, impl or trait
@@ -2752,11 +2752,12 @@ struct Resolver {
NormalRibKind => {
// Nothing to do. Continue.
}
- FunctionRibKind(function_id) => {
+ FunctionRibKind(function_id, body_id) => {
if !is_ty_param {
def = def_upvar(def_id_of_def(def).node,
@def,
- function_id);
+ function_id,
+ body_id);
}
}
MethodRibKind(item_id, method_id) => {
@@ -4164,7 +4165,7 @@ struct Resolver {
expr_fn(_, fn_decl, block, capture_clause) |
expr_fn_block(fn_decl, block, capture_clause) => {
- self.resolve_function(FunctionRibKind(expr.id),
+ self.resolve_function(FunctionRibKind(expr.id, block.node.id),
some(@fn_decl),
NoTypeParameters,
block,
@@ -2464,7 +2464,7 @@ fn trans_local_var(cx: block, def: ast::def) -> local_var_result {
}
}
match def {
- ast::def_upvar(nid, _, _) => {
+ ast::def_upvar(nid, _, _, _) => {
assert (cx.fcx.llupvars.contains_key(nid));
return { val: cx.fcx.llupvars.get(nid), kind: lv_owned };
}
@@ -961,7 +961,8 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
let fty = ty::mk_fn(bcx.tcx(), {
purity: ast::impure_fn,
proto:
- ty::proto_vstore(ty::vstore_slice(ty::re_bound(ty::br_anon))),
+ ty::proto_vstore(ty::vstore_slice(
+ ty::re_bound(ty::br_anon(0)))),
bounds: @~[],
inputs: ~[{
mode: ast::expl(ast::by_val),
@@ -525,7 +525,7 @@ fn expr_to_constr_arg(tcx: ty::ctxt, e: @expr) -> @constr_arg_use {
expr_path(p) {
match tcx.def_map.find(e.id) {
some(def_local(nid, _)) | some(def_arg(nid, _)) |
- some(def_binding(nid, _)) | some(def_upvar(nid, _, _)) {
+ some(def_binding(nid, _)) | some(def_upvar(nid, _, _, _)) {
return @respan(p.span,
carg_ident({ident: p.idents[0], node: nid}));
}
View
@@ -377,8 +377,8 @@ enum bound_region {
/// The self region for classes, impls (&T in a type defn or &self/T)
br_self,
- /// Anonymous region parameter for a given fn (&T)
- br_anon,
+ /// An anonymous region parameter for a given fn (&T)
+ br_anon(uint),
/// Named region parameters for functions (a in &a/T)
br_named(ast::ident),
@@ -2192,9 +2192,10 @@ fn index_sty(cx: ctxt, sty: &sty) -> option<mt> {
pure fn hash_bound_region(br: &bound_region) -> uint {
match *br { // no idea if this is any good
ty::br_self => 0u,
- ty::br_anon => 1u,
- ty::br_named(str) => str::hash(str),
- ty::br_cap_avoid(id, br) => id as uint | hash_bound_region(br)
+ ty::br_anon(idx) => 1u | (idx << 2),
+ ty::br_named(str) => 2u | (str::hash(str) << 2),
+ ty::br_cap_avoid(id, br) =>
+ 3u | (id as uint << 2) | hash_bound_region(br)
}
}
@@ -2304,7 +2304,7 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
ast::def_ty(_) | ast::def_prim_ty(_) => {
fcx.ccx.tcx.sess.span_fatal(sp, ~"expected value but found type");
}
- ast::def_upvar(_, inner, _) => {
+ ast::def_upvar(_, inner, _, _) => {
return ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
}
ast::def_ty_param(did, n) => {
@@ -2513,7 +2513,8 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
let fty = ty::mk_fn(ccx.tcx, {
purity: ast::impure_fn,
proto:
- ty::proto_vstore(ty::vstore_slice(ty::re_bound(ty::br_anon))),
+ ty::proto_vstore(ty::vstore_slice(
+ ty::re_bound(ty::br_anon(0)))),
bounds: @~[],
inputs: ~[{
mode: ast::expl(ast::by_val),
Oops, something went wrong.

0 comments on commit 652b312

Please sign in to comment.