diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs index 92ede8890166..81e9eff4a9d8 100644 --- a/src/rustc/metadata/tyencode.rs +++ b/src/rustc/metadata/tyencode.rs @@ -103,6 +103,7 @@ fn enc_region(w: io::writer, cx: @ctxt, r: ty::region) { ty::re_block(nid) { w.write_char('b'); w.write_int(nid); w.write_char('|'); } + ty::re_inferred { w.write_char('?'); } } } fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) { diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index 73409893e5c8..bacde1d02930 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -15,9 +15,10 @@ import std::map::hashmap; /* Represents the type of the most immediate parent node. */ enum parent { - pa_item(ast::node_id), + pa_fn_item(ast::node_id), pa_block(ast::node_id), pa_nested_fn(ast::node_id), + pa_item(ast::node_id), pa_crate } @@ -66,6 +67,7 @@ fn region_to_scope(region_map: @region_map, region: ty::region) ty::re_caller(def_id) { def_id.node } ty::re_named(def_id) { region_map.region_name_to_fn.get(def_id) } ty::re_block(node_id) { node_id } + ty::re_inferred { fail "unresolved region in region_to_scope" } }; } @@ -90,10 +92,11 @@ fn get_inferred_region(cx: ctxt, sp: syntax::codemap::span) -> ty::region { // TODO: What do we do if we're in an alt? ret alt cx.parent { - pa_item(item_id) | pa_nested_fn(item_id) { + pa_fn_item(item_id) | pa_nested_fn(item_id) { ty::re_caller({crate: ast::local_crate, node: item_id}) } pa_block(block_id) { ty::re_block(block_id) } + pa_item(_) { ty::re_inferred } pa_crate { cx.sess.span_bug(sp, "inferred region at crate level?!"); } } } @@ -121,10 +124,16 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt) { region = ty::re_named(def_id); alt cx.parent { - pa_item(fn_id) | pa_nested_fn(fn_id) { + pa_fn_item(fn_id) | pa_nested_fn(fn_id) { let rf = cx.region_map.region_name_to_fn; rf.insert(def_id, fn_id); } + pa_item(_) { + cx.sess.span_err(ty.span, + "named region not " + + "allowed in this " + + "context"); + } pa_block(_) { cx.sess.span_err(ty.span, "unknown region `" + @@ -152,7 +161,10 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt) { fn record_parent(cx: ctxt, child_id: ast::node_id) { alt cx.parent { - pa_item(parent_id) | pa_block(parent_id) | pa_nested_fn(parent_id) { + pa_fn_item(parent_id) | + pa_item(parent_id) | + pa_block(parent_id) | + pa_nested_fn(parent_id) { cx.region_map.parents.insert(child_id, parent_id); } pa_crate { /* no-op */ } @@ -231,8 +243,12 @@ fn resolve_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt) { fn resolve_item(item: @ast::item, cx: ctxt, visitor: visit::vt) { // Items create a new outer block scope as far as we're concerned. + let parent = alt item.node { + ast::item_fn(_, _, _) { pa_fn_item(item.id) } + _ { pa_item(item.id) } + }; let new_cx: ctxt = {bindings: @list::nil, - parent: pa_item(item.id), + parent: parent, in_alt: false with cx}; visit::visit_item(item, new_cx, visitor); diff --git a/src/rustc/middle/regionck.rs b/src/rustc/middle/regionck.rs index 65b1d0673a65..702c844c0f2e 100644 --- a/src/rustc/middle/regionck.rs +++ b/src/rustc/middle/regionck.rs @@ -49,6 +49,10 @@ fn check_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt) { "escapes its block"); } } + ty::re_inferred { + cx.tcx.sess.span_bug(expr.span, + "unresolved region"); + } } } _ { /* no-op */ } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 5f5ac939a228..06764a472ce4 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -35,7 +35,7 @@ export field; export field_idx; export get_field; export get_fields; -export fm_general; +export fm_general, fm_rptr; export get_element_type; export is_binopable; export is_pred_ty; @@ -88,7 +88,7 @@ export ty_uint, mk_uint, mk_mach_uint; 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 region, re_named, re_caller, re_block, re_inferred; export get, type_has_params, type_has_vars, type_has_rptrs, type_id; export same_type; export ty_var_id; @@ -234,7 +234,8 @@ type fn_ty = {proto: ast::proto, enum region { re_named(def_id), re_caller(def_id), - re_block(node_id) + re_block(node_id), + re_inferred /* currently unresolved (for typedefs) */ } // NB: If you change this, you'll probably want to change the corresponding @@ -571,6 +572,7 @@ fn walk_ty(cx: ctxt, ty: t, f: fn(t)) { enum fold_mode { fm_var(fn@(int) -> t), fm_param(fn@(uint, def_id) -> t), + fm_rptr(fn@(region) -> region), fm_general(fn@(t) -> t), } @@ -581,6 +583,7 @@ fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t { alt fld { fm_var(_) { if !tb.has_vars { ret ty; } } fm_param(_) { if !tb.has_params { ret ty; } } + fm_rptr(_) { if !tb.has_rptrs { ret ty; } } fm_general(_) {/* no fast path */ } } @@ -597,9 +600,6 @@ fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t { ty_ptr(tm) { ty = mk_ptr(cx, {ty: fold_ty(cx, fld, tm.ty), mutbl: tm.mutbl}); } - ty_rptr(r, tm) { - ty = mk_rptr(cx, r, {ty: fold_ty(cx, fld, tm.ty), mutbl: tm.mutbl}); - } ty_vec(tm) { ty = mk_vec(cx, {ty: fold_ty(cx, fld, tm.ty), mutbl: tm.mutbl}); } @@ -647,6 +647,11 @@ fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t { ty_param(id, did) { alt fld { fm_param(folder) { ty = folder(id, did); } _ {} } } + ty_rptr(r, tm) { + let region = alt fld { fm_rptr(folder) { folder(r) } _ { r } }; + ty = mk_rptr(cx, region, + {ty: fold_ty(cx, fld, tm.ty), mutbl: tm.mutbl}); + } ty_constr(subty, cs) { ty = mk_constr(cx, fold_ty(cx, fld, subty), cs); } @@ -1161,6 +1166,7 @@ fn hash_type_structure(st: sty) -> uint { re_named(_) { 1u } re_caller(_) { 2u } re_block(_) { 3u } + re_inferred { 4u } } } alt st { diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index e8d478866651..dbd0baf5dfa5 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -247,10 +247,19 @@ enum mode { m_collect, m_check, m_check_tyvar(@fn_ctxt), } // internal notion of a type. `getter` is a function that returns the type // corresponding to a definition ID: fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t { - fn getter(tcx: ty::ctxt, _use_site: ast::node_id, mode: mode, + fn subst_inferred_regions(tcx: ty::ctxt, use_site: ast::node_id, + ty: ty::t) -> ty::t { + ret ty::fold_ty(tcx, ty::fm_rptr({|r| + if r == ty::re_inferred { + tcx.region_map.ast_type_to_inferred_region.get(use_site) + } else { + r + } + }), ty); + } + fn getter(tcx: ty::ctxt, use_site: ast::node_id, mode: mode, id: ast::def_id) -> ty::ty_param_bounds_and_ty { - // FIXME (pcwalton): Doesn't work with region inference. - alt mode { + let tpt = alt mode { m_check | m_check_tyvar(_) { ty::lookup_item_type(tcx, id) } m_collect { if id.crate != ast::local_crate { csearch::get_type(tcx, id) } @@ -268,7 +277,13 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t { } } } + }; + + if ty::type_has_rptrs(tpt.ty) { + ret {bounds: tpt.bounds, + ty: subst_inferred_regions(tcx, use_site, tpt.ty)}; } + ret tpt; } fn ast_mt_to_mt(tcx: ty::ctxt, use_site: ast::node_id, mode: mode, mt: ast::mt) -> ty::mt { @@ -327,7 +342,11 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t { ast::ty_rptr(region, mt) { let region = alt region.node { ast::re_inferred | ast::re_self { - tcx.region_map.ast_type_to_inferred_region.get(ast_ty.id) + let attir = tcx.region_map.ast_type_to_inferred_region; + alt attir.find(ast_ty.id) { + some(resolved_region) { resolved_region } + none { ty::re_inferred } + } } ast::re_named(_) { tcx.region_map.ast_type_to_region.get(region.id) diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs index 711b27327c27..0541c0d9d15f 100644 --- a/src/rustc/util/ppaux.rs +++ b/src/rustc/util/ppaux.rs @@ -73,6 +73,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> str { re_named(_) { "." } // TODO: include name re_caller(_) { "." } re_block(_) { "." } // TODO: include line number + re_inferred { "" } } }