diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index 00943db35c64..834ccab1afee 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -6,6 +6,8 @@ import driver::session::session; import middle::ty; import syntax::{ast, visit}; +import util::common::new_def_hash; + import std::map; import std::map::hashmap; @@ -27,6 +29,8 @@ type region_map = { ast_type_to_region: hashmap, /* Mapping from a local variable to its containing block. */ local_blocks: hashmap, + /* Mapping from a region name to its function. */ + region_name_to_fn: hashmap, }; type ctxt = { @@ -105,9 +109,15 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt) { alt cx.names_in_scope.find(ident) { some(def_id) { region = ty::re_named(def_id); } none { + let def_id = {crate: ast::local_crate, + node: region_id}; + cx.names_in_scope.insert(ident, def_id); + region = ty::re_named(def_id); + alt cx.parent { - pa_item(_) | pa_nested_fn(_) { - /* ok; fall through */ + pa_item(fn_id) | pa_nested_fn(fn_id) { + let rf = cx.region_map.region_name_to_fn; + rf.insert(def_id, fn_id); } pa_block(_) { cx.sess.span_err(ty.span, @@ -120,11 +130,6 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt) { "level?!"); } } - - let def_id = {crate: ast::local_crate, - node: region_id}; - cx.names_in_scope.insert(ident, def_id); - region = ty::re_named(def_id); } } } @@ -256,7 +261,8 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate) def_map: def_map, region_map: @{parents: map::new_int_hash(), ast_type_to_region: map::new_int_hash(), - local_blocks: map::new_int_hash()}, + local_blocks: map::new_int_hash(), + region_name_to_fn: new_def_hash()}, names_in_scope: map::new_str_hash(), mut queued_locals: [], parent: pa_crate, diff --git a/src/rustc/middle/regionck.rs b/src/rustc/middle/regionck.rs index ef51a950df66..65b1d0673a65 100644 --- a/src/rustc/middle/regionck.rs +++ b/src/rustc/middle/regionck.rs @@ -22,33 +22,37 @@ type ctxt = { }; fn check_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt) { - ty::walk_ty(cx.tcx, ty::expr_ty(cx.tcx, expr)) { |t| - alt ty::get(t).struct { - ty::ty_rptr(region, _) { - alt region { - ty::re_named(_) | ty::re_caller(_) { /* ok */ } - ty::re_block(rbi) { - let referent_block_id = rbi; - let enclosing_block_id = alt cx.enclosing_block { - none { - cx.tcx.sess.span_bug(expr.span, "block " + - "region type outside " + - "a block?!"); + let t = ty::expr_ty(cx.tcx, expr); + if ty::type_has_rptrs(t) { + ty::walk_ty(cx.tcx, t) { |t| + alt ty::get(t).struct { + ty::ty_rptr(region, _) { + alt region { + ty::re_named(_) | ty::re_caller(_) { /* ok */ } + ty::re_block(rbi) { + let referent_block_id = rbi; + let enclosing_block_id = alt cx.enclosing_block { + none { + cx.tcx.sess.span_bug(expr.span, + "block region " + + "type outside a " + + "block?!"); + } + some(eb) { eb } + }; + + if !region::scope_contains(cx.tcx.region_map, + referent_block_id, + enclosing_block_id) { + + cx.tcx.sess.span_err(expr.span, "reference " + + "escapes its block"); } - some(eb) { eb } - }; - - if !region::scope_contains(cx.tcx.region_map, - referent_block_id, - enclosing_block_id) { - - cx.tcx.sess.span_err(expr.span, "reference " + - "escapes its block"); } } } + _ { /* no-op */ } } - _ { /* no-op */ } } } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 10ed85dc6c5c..01c8b2ca28c8 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -89,7 +89,7 @@ export ty_uniq, mk_uniq, mk_imm_uniq, type_is_unique_box; export ty_var, mk_var; export ty_self, mk_self; export region, re_named, re_caller, re_block; -export get, type_has_params, type_has_vars, type_id; +export get, type_has_params, type_has_vars, type_has_rptrs, type_id; export same_type; export ty_var_id; export ty_fn_args; @@ -187,6 +187,7 @@ type t_box = @{struct: sty, id: uint, has_params: bool, has_vars: bool, + has_rptrs: bool, o_def_id: option}; // To reduce refcounting cost, we're representing types as unsafe pointers @@ -206,6 +207,7 @@ pure fn get(t: t) -> t_box unsafe { fn type_has_params(t: t) -> bool { get(t).has_params } fn type_has_vars(t: t) -> bool { get(t).has_vars } +fn type_has_rptrs(t: t) -> bool { get(t).has_rptrs } fn type_def_id(t: t) -> option { get(t).o_def_id } fn type_id(t: t) -> uint { get(t).id } @@ -368,11 +370,13 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option) -> t { some(t) { unsafe { ret unsafe::reinterpret_cast(t); } } _ {} } - let has_params = false, has_vars = false; - fn derive_flags(&has_params: bool, &has_vars: bool, tt: t) { + let has_params = false, has_vars = false, has_rptrs = false; + fn derive_flags(&has_params: bool, &has_vars: bool, &has_rptrs: bool, + tt: t) { let t = get(tt); has_params |= t.has_params; has_vars |= t.has_vars; + has_rptrs |= t.has_rptrs; } alt st { ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) | @@ -381,33 +385,42 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option) -> t { ty_param(_, _) { has_params = true; } ty_var(_) | ty_self(_) { has_vars = true; } ty_enum(_, tys) | ty_iface(_, tys) | ty_class(_, tys) { - for tt in tys { derive_flags(has_params, has_vars, tt); } + for tt in tys { derive_flags(has_params, has_vars, has_rptrs, tt); } } - ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_ptr(m) | ty_rptr(_, m) { - derive_flags(has_params, has_vars, m.ty); + ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_ptr(m) { + derive_flags(has_params, has_vars, has_rptrs, m.ty); + } + ty_rptr(_, m) { + has_rptrs = true; + derive_flags(has_params, has_vars, has_rptrs, m.ty); } ty_rec(flds) { - for f in flds { derive_flags(has_params, has_vars, f.mt.ty); } + for f in flds { + derive_flags(has_params, has_vars, has_rptrs, f.mt.ty); + } } ty_tup(ts) { - for tt in ts { derive_flags(has_params, has_vars, tt); } + for tt in ts { derive_flags(has_params, has_vars, has_rptrs, tt); } } ty_fn(f) { - for a in f.inputs { derive_flags(has_params, has_vars, a.ty); } - derive_flags(has_params, has_vars, f.output); + for a in f.inputs { + derive_flags(has_params, has_vars, has_rptrs, a.ty); + } + derive_flags(has_params, has_vars, has_rptrs, f.output); } ty_res(_, tt, tps) { - derive_flags(has_params, has_vars, tt); - for tt in tps { derive_flags(has_params, has_vars, tt); } + derive_flags(has_params, has_vars, has_rptrs, tt); + for tt in tps { derive_flags(has_params, has_vars, has_rptrs, tt); } } ty_constr(tt, _) { - derive_flags(has_params, has_vars, tt); + derive_flags(has_params, has_vars, has_rptrs, tt); } } let t = @{struct: st, id: cx.next_id, has_params: has_params, has_vars: has_vars, + has_rptrs: has_rptrs, o_def_id: o_def_id}; cx.interner.insert(key, t); cx.next_id += 1u;