infer when types are region parameterized rather than requiring /&

- removes various fields from various variants in the AST
- also update tests not to use this notation
This commit is contained in:
Niko Matsakis 2012-07-11 10:28:30 -07:00
parent 9b094c0baf
commit b9aa9def85
59 changed files with 602 additions and 387 deletions

View File

@ -678,31 +678,24 @@ type item = {ident: ident, attrs: ~[attribute],
id: node_id, node: item_,
vis: visibility, span: span};
#[auto_serialize]
enum region_param {
rp_none,
rp_self
}
#[auto_serialize]
enum item_ {
item_const(@ty, @expr),
item_fn(fn_decl, ~[ty_param], blk),
item_mod(_mod),
item_foreign_mod(foreign_mod),
item_ty(@ty, ~[ty_param], region_param),
item_enum(~[variant], ~[ty_param], region_param),
item_ty(@ty, ~[ty_param]),
item_enum(~[variant], ~[ty_param]),
item_class(~[ty_param], /* ty params for class */
~[@trait_ref], /* traits this class implements */
~[@class_member], /* methods, etc. */
/* (not including ctor or dtor) */
class_ctor,
/* dtor is optional */
option<class_dtor>,
region_param
option<class_dtor>
),
item_trait(~[ty_param], region_param, ~[ty_method]),
item_impl(~[ty_param], region_param, option<@trait_ref> /* trait */,
item_trait(~[ty_param], ~[ty_method]),
item_impl(~[ty_param], option<@trait_ref> /* trait */,
@ty /* self */, ~[@method]),
item_mac(mac),
}

View File

@ -188,14 +188,14 @@ fn map_item(i: @item, cx: ctx, v: vt) {
let item_path = @/* FIXME (#2543) */ copy cx.path;
cx.map.insert(i.id, node_item(i, item_path));
alt i.node {
item_impl(_, _, _, _, ms) {
item_impl(_, _, _, ms) {
let impl_did = ast_util::local_def(i.id);
for ms.each |m| {
map_method(impl_did, extend(cx, i.ident), m,
cx);
}
}
item_enum(vs, _, _) {
item_enum(vs, _) {
for vs.each |v| {
cx.map.insert(v.node.id, node_variant(
/* FIXME (#2543) */ copy v, i,
@ -214,7 +214,7 @@ fn map_item(i: @item, cx: ctx, v: vt) {
extend(cx, i.ident)));
}
}
item_class(tps, traits, items, ctor, dtor, _) {
item_class(tps, traits, items, ctor, dtor) {
let (_, ms) = ast_util::split_class_items(items);
// Map trait refs to their parent classes. This is
// so we can find the self_ty

View File

@ -155,7 +155,7 @@ fn is_exported(i: ident, m: _mod) -> bool {
for m.items.each |it| {
if it.ident == i { local = true; }
alt it.node {
item_enum(variants, _, _) {
item_enum(variants, _) {
for variants.each |v| {
if v.node.name == i {
local = true;
@ -428,7 +428,7 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
visit_item: fn@(i: @item) {
vfn(i.id);
alt i.node {
item_enum(vs, _, _) { for vs.each |v| { vfn(v.node.id); } }
item_enum(vs, _) { for vs.each |v| { vfn(v.node.id); } }
_ {}
}
},
@ -519,6 +519,9 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
}
},
visit_ty_method: fn@(_ty_m: ty_method) {
},
visit_class_item: fn@(c: @class_member) {
alt c.node {
instance_var(_, _, _, id,_) {

View File

@ -102,12 +102,12 @@ fn expand(cx: ext_ctxt,
do vec::flat_map(in_items) |in_item| {
alt in_item.node {
ast::item_ty(ty, tps, _) {
ast::item_ty(ty, tps) {
vec::append(~[filter_attrs(in_item)],
ty_fns(cx, in_item.ident, ty, tps))
}
ast::item_enum(variants, tps, _) {
ast::item_enum(variants, tps) {
vec::append(~[filter_attrs(in_item)],
enum_fns(cx, in_item.ident,
in_item.span, variants, tps))

View File

@ -128,8 +128,7 @@ impl ast_builder for ext_ctxt {
+ty_params: ~[ast::ty_param]) -> @ast::item {
self.item(name,
ast::item_enum(variants,
ty_params,
ast::rp_none))
ty_params))
}
fn item_enum(name: ident,
@ -167,12 +166,10 @@ impl ast_builder for ext_ctxt {
fn item_ty_poly(name: ident,
ty: @ast::ty,
+params: ~[ast::ty_param]) -> @ast::item {
self.item(name,
ast::item_ty(ty, params, ast::rp_none))
self.item(name, ast::item_ty(ty, params))
}
fn item_ty(name: ident,
ty: @ast::ty) -> @ast::item {
fn item_ty(name: ident, ty: @ast::ty) -> @ast::item {
self.item_ty_poly(name, ty, ~[])
}

View File

@ -244,15 +244,13 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
}
item_mod(m) { item_mod(fld.fold_mod(m)) }
item_foreign_mod(nm) { item_foreign_mod(fld.fold_foreign_mod(nm)) }
item_ty(t, typms, rp) { item_ty(fld.fold_ty(t),
fold_ty_params(typms, fld),
rp) }
item_enum(variants, typms, r) {
item_ty(t, typms) { item_ty(fld.fold_ty(t),
fold_ty_params(typms, fld)) }
item_enum(variants, typms) {
item_enum(vec::map(variants, |x| fld.fold_variant(x)),
fold_ty_params(typms, fld),
r)
fold_ty_params(typms, fld))
}
item_class(typms, traits, items, ctor, m_dtor, rp) {
item_class(typms, traits, items, ctor, m_dtor) {
let ctor_body = fld.fold_block(ctor.node.body);
let ctor_decl = fold_fn_decl(ctor.node.dec, fld);
let ctor_id = fld.new_id(ctor.node.id);
@ -269,18 +267,16 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
{node: {body: ctor_body,
dec: ctor_decl,
id: ctor_id with ctor.node}
with ctor}, dtor, rp)
with ctor}, dtor)
}
item_impl(tps, rp, ifce, ty, methods) {
item_impl(tps, ifce, ty, methods) {
item_impl(fold_ty_params(tps, fld),
rp,
ifce.map(|p| fold_trait_ref(p, fld)),
fld.fold_ty(ty),
vec::map(methods, |x| fld.fold_method(x)))
}
item_trait(tps, rp, methods) {
item_trait(tps, methods) {
item_trait(fold_ty_params(tps, fld),
rp,
/* FIXME (#2543) */ copy methods)
}
item_mac(m) {

View File

@ -41,8 +41,8 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
pat_box, pat_enum, pat_ident, pat_lit, pat_range, pat_rec,
pat_tup, pat_uniq, pat_wild, path, private, proto, proto_any,
proto_bare, proto_block, proto_box, proto_uniq, public, pure_fn,
purity, re_anon, re_named, region, region_param, rem, ret_style,
return_val, rp_none, rp_self, shl, shr, stmt, stmt_decl,
purity, re_anon, re_named, region, rem, ret_style,
return_val, shl, shr, stmt, stmt_decl,
stmt_expr, stmt_semi, subtract, token_tree, trait_ref, tt_delim,
tt_dotdotdot, tt_flat, tt_interpolate, ty, ty_, ty_bot, ty_box,
ty_constr, ty_constr_, ty_constr_arg, ty_field, ty_fn, ty_infer,
@ -2133,10 +2133,10 @@ class parser {
fn parse_item_trait() -> item_info {
let ident = self.parse_ident();
let rp = self.parse_region_param();
self.parse_region_param();
let tps = self.parse_ty_params();
let meths = self.parse_ty_methods();
(ident, item_trait(tps, rp, meths), none)
(ident, item_trait(tps, meths), none)
}
// Parses three variants (with the region/type params always optional):
@ -2147,18 +2147,19 @@ class parser {
fn wrap_path(p: parser, pt: @path) -> @ty {
@{id: p.get_id(), node: ty_path(pt, p.get_id()), span: pt.span}
}
let mut (ident, rp, tps) = {
let mut (ident, tps) = {
if self.token == token::LT {
(none, rp_none, self.parse_ty_params())
(none, self.parse_ty_params())
} else if self.token == token::BINOP(token::SLASH) {
(none, self.parse_region_param(), self.parse_ty_params())
self.parse_region_param();
(none, self.parse_ty_params())
}
else if self.is_keyword("of") {
(none, rp_none, ~[])
(none, ~[])
} else {
let id = self.parse_ident();
let rp = self.parse_region_param();
(some(id), rp, self.parse_ty_params())
self.parse_region_param();
(some(id), self.parse_ty_params())
}
};
let ifce = if self.eat_keyword("of") {
@ -2179,25 +2180,18 @@ class parser {
while !self.eat(token::RBRACE) {
vec::push(meths, self.parse_method(public));
}
(ident, item_impl(tps, rp, ifce, ty, meths), none)
(ident, item_impl(tps, ifce, ty, meths), none)
}
// Instantiates ident <i> with references to <typarams> as arguments.
// Used to create a path that refers to a class which will be defined as
// the return type of the ctor function.
fn ident_to_path_tys(i: ident,
rp: region_param,
typarams: ~[ty_param]) -> @path {
let s = self.last_span;
// Hack. But then, this whole function is in service of a hack.
let a_r = alt rp {
rp_none { none }
rp_self { some(self.region_from_name(some(@"self"))) }
};
@{span: s, global: false, idents: ~[i],
rp: a_r,
rp: none,
types: vec::map(typarams, |tp| {
@{id: self.get_id(),
node: ty_path(ident_to_path(s, tp.ident), self.get_id()),
@ -2218,9 +2212,9 @@ class parser {
fn parse_item_class() -> item_info {
let class_name = self.parse_value_ident();
let rp = self.parse_region_param();
self.parse_region_param();
let ty_params = self.parse_ty_params();
let class_path = self.ident_to_path_tys(class_name, rp, ty_params);
let class_path = self.ident_to_path_tys(class_name, ty_params);
let traits : ~[@trait_ref] = if self.eat(token::COLON)
{ self.parse_trait_ref_list() }
else { ~[] };
@ -2255,7 +2249,7 @@ class parser {
self_id: self.get_id(),
dec: ct_d,
body: ct_b},
span: ct_s}, actual_dtor, rp),
span: ct_s}, actual_dtor),
none)
}
/*
@ -2447,26 +2441,23 @@ class parser {
fn parse_item_type() -> item_info {
let t = self.parse_type_decl();
let rp = self.parse_region_param();
self.parse_region_param();
let tps = self.parse_ty_params();
self.expect(token::EQ);
let ty = self.parse_ty(false);
self.expect(token::SEMI);
(t.ident, item_ty(ty, tps, rp), none)
(t.ident, item_ty(ty, tps), none)
}
fn parse_region_param() -> region_param {
fn parse_region_param() {
if self.eat(token::BINOP(token::SLASH)) {
self.expect(token::BINOP(token::AND));
rp_self
} else {
rp_none
}
}
fn parse_item_enum(default_vis: visibility) -> item_info {
let id = self.parse_ident();
let rp = self.parse_region_param();
self.parse_region_param();
let ty_params = self.parse_ty_params();
let mut variants: ~[variant] = ~[];
// Newtype syntax
@ -2483,7 +2474,7 @@ class parser {
id: self.get_id(),
disr_expr: none,
vis: public});
ret (id, item_enum(~[variant], ty_params, rp), none);
ret (id, item_enum(~[variant], ty_params), none);
}
self.expect(token::LBRACE);
@ -2521,7 +2512,7 @@ class parser {
self.fatal("discriminator values can only be used with a c-like \
enum");
}
(id, item_enum(variants, ty_params, rp), none)
(id, item_enum(variants, ty_params), none)
}
fn parse_fn_ty_proto() -> proto {

View File

@ -458,12 +458,11 @@ fn print_item(s: ps, &&item: @ast::item) {
print_foreign_mod(s, nmod, item.attrs);
bclose(s, item.span);
}
ast::item_ty(ty, params, rp) {
ast::item_ty(ty, params) {
ibox(s, indent_unit);
ibox(s, 0u);
word_nbsp(s, "type");
word(s.s, *item.ident);
print_region_param(s, rp);
print_type_params(s, params);
end(s); // end the inner ibox
@ -473,7 +472,7 @@ fn print_item(s: ps, &&item: @ast::item) {
word(s.s, ";");
end(s); // end the outer ibox
}
ast::item_enum(variants, params, rp) {
ast::item_enum(variants, params) {
let newtype =
vec::len(variants) == 1u &&
str::eq(*item.ident, *variants[0].node.name) &&
@ -483,7 +482,6 @@ fn print_item(s: ps, &&item: @ast::item) {
word_space(s, "enum");
} else { head(s, "enum"); }
word(s.s, *item.ident);
print_region_param(s, rp);
print_type_params(s, params);
space(s.s);
if newtype {
@ -506,10 +504,9 @@ fn print_item(s: ps, &&item: @ast::item) {
bclose(s, item.span);
}
}
ast::item_class(tps, traits, items, ctor, m_dtor, rp) {
ast::item_class(tps, traits, items, ctor, m_dtor) {
head(s, "class");
word_nbsp(s, *item.ident);
print_region_param(s, rp);
print_type_params(s, tps);
if vec::len(traits) != 0u {
word_space(s, ":");
@ -571,10 +568,9 @@ fn print_item(s: ps, &&item: @ast::item) {
}
bclose(s, item.span);
}
ast::item_impl(tps, rp, ifce, ty, methods) {
ast::item_impl(tps, ifce, ty, methods) {
head(s, "impl");
word(s.s, *item.ident);
print_region_param(s, rp);
print_type_params(s, tps);
space(s.s);
option::iter(ifce, |p| {
@ -591,10 +587,9 @@ fn print_item(s: ps, &&item: @ast::item) {
}
bclose(s, item.span);
}
ast::item_trait(tps, rp, methods) {
ast::item_trait(tps, methods) {
head(s, "iface");
word(s.s, *item.ident);
print_region_param(s, rp);
print_type_params(s, tps);
word(s.s, " ");
bopen(s);
@ -1406,13 +1401,6 @@ fn print_bounds(s: ps, bounds: @~[ast::ty_param_bound]) {
}
}
fn print_region_param(s: ps, rp: ast::region_param) {
alt rp {
ast::rp_self { word(s.s, "/&") }
ast::rp_none { }
}
}
fn print_type_params(s: ps, &&params: ~[ast::ty_param]) {
if vec::len(params) > 0u {
word(s.s, "<");

View File

@ -61,6 +61,7 @@ type visitor<E> =
visit_ty_params: fn@(~[ty_param], E, vt<E>),
visit_constr: fn@(@path, span, node_id, E, vt<E>),
visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
visit_ty_method: fn@(ty_method, E, vt<E>),
visit_class_item: fn@(@class_member, E, vt<E>)};
fn default_visitor<E>() -> visitor<E> {
@ -79,6 +80,7 @@ fn default_visitor<E>() -> visitor<E> {
visit_ty_params: |a,b,c|visit_ty_params::<E>(a, b, c),
visit_constr: |a,b,c,d,e|visit_constr::<E>(a, b, c, d, e),
visit_fn: |a,b,c,d,e,f,g|visit_fn::<E>(a, b, c, d, e, f, g),
visit_ty_method: |a,b,c|visit_ty_method::<E>(a, b, c),
visit_class_item: |a,b,c|visit_class_item::<E>(a, b, c)};
}
@ -125,17 +127,17 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
for nm.view_items.each |vi| { v.visit_view_item(vi, e, v); }
for nm.items.each |ni| { v.visit_foreign_item(ni, e, v); }
}
item_ty(t, tps, rp) {
item_ty(t, tps) {
v.visit_ty(t, e, v);
v.visit_ty_params(tps, e, v);
}
item_enum(variants, tps, _) {
item_enum(variants, tps) {
v.visit_ty_params(tps, e, v);
for variants.each |vr| {
for vr.node.args.each |va| { v.visit_ty(va.ty, e, v); }
}
}
item_impl(tps, _rp, ifce, ty, methods) {
item_impl(tps, ifce, ty, methods) {
v.visit_ty_params(tps, e, v);
option::iter(ifce, |p| visit_path(p.path, e, v));
v.visit_ty(ty, e, v);
@ -143,7 +145,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
visit_method_helper(m, e, v)
}
}
item_class(tps, traits, members, ctor, m_dtor, _) {
item_class(tps, traits, members, ctor, m_dtor) {
v.visit_ty_params(tps, e, v);
for members.each |m| {
v.visit_class_item(m, e, v);
@ -155,12 +157,10 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
visit_class_dtor_helper(dtor, tps,
ast_util::local_def(i.id), e, v)};
}
item_trait(tps, _rp, methods) {
item_trait(tps, methods) {
v.visit_ty_params(tps, e, v);
for methods.each |m| {
for m.decl.inputs.each |a| { v.visit_ty(a.ty, e, v); }
v.visit_ty_params(m.tps, e, v);
v.visit_ty(m.decl.output, e, v);
v.visit_ty_method(m, e, v);
}
}
item_mac(m) { visit_mac(m, e, v) }
@ -311,6 +311,12 @@ fn visit_fn<E>(fk: fn_kind, decl: fn_decl, body: blk, _sp: span,
v.visit_block(body, e, v);
}
fn visit_ty_method<E>(m: ty_method, e: E, v: vt<E>) {
for m.decl.inputs.each |a| { v.visit_ty(a.ty, e, v); }
v.visit_ty_params(m.tps, e, v);
v.visit_ty(m.decl.output, e, v);
}
fn visit_block<E>(b: ast::blk, e: E, v: vt<E>) {
for b.node.view_items.each |vi| { v.visit_view_item(vi, e, v); }
for b.node.stmts.each |s| { v.visit_stmt(s, e, v); }
@ -458,6 +464,7 @@ type simple_visitor =
visit_ty_params: fn@(~[ty_param]),
visit_constr: fn@(@path, span, node_id),
visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
visit_ty_method: fn@(ty_method),
visit_class_item: fn@(@class_member)};
fn simple_ignore_ty(_t: @ty) {}
@ -479,6 +486,7 @@ fn default_simple_visitor() -> simple_visitor {
visit_constr: fn@(_p: @path, _sp: span, _id: node_id) { },
visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
_id: node_id) { },
visit_ty_method: fn@(_m: ty_method) { },
visit_class_item: fn@(_c: @class_member) {}
};
}
@ -534,6 +542,10 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
f(ty);
visit_ty(ty, e, v);
}
fn v_ty_method(f: fn@(ty_method), ty: ty_method, &&e: (), v: vt<()>) {
f(ty);
visit_ty_method(ty, e, v);
}
fn v_ty_params(f: fn@(~[ty_param]),
ps: ~[ty_param],
&&e: (), v: vt<()>) {
@ -582,6 +594,8 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
v_constr(v.visit_constr, a, b, c, d, e),
visit_fn: |a,b,c,d,e,f,g|
v_fn(v.visit_fn, a, b, c, d, e, f, g),
visit_ty_method: |a,b,c|
v_ty_method(v.visit_ty_method, a, b, c),
visit_class_item: |a,b,c|
v_class_item(v.visit_class_item, a, b, c)
});

View File

@ -178,7 +178,11 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
let region_map = time(time_passes, "region resolution", ||
middle::region::resolve_crate(sess, def_map, crate));
let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars, region_map);
let rp_set = time(time_passes, "region paramerization inference", ||
middle::region::determine_rp_in_crate(sess, ast_map, def_map, crate));
let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
region_map, rp_set);
let (method_map, vtable_map) = time(time_passes, "typechecking", ||
typeck::check_crate(ty_cx,

View File

@ -38,6 +38,7 @@ const no_rt: uint = 256u;
const coherence: uint = 512u;
const borrowck_stats: uint = 1024u;
const borrowck_note_pure: uint = 2048;
const borrowck_note_loan: uint = 4096;
fn debugging_opts_map() -> ~[(str, str, uint)] {
~[("ppregions", "prettyprint regions with \
@ -46,7 +47,7 @@ fn debugging_opts_map() -> ~[(str, str, uint)] {
("count-llvm-insns", "count where LLVM \
instrs originate", count_llvm_insns),
("time-llvm-passes", "measure time of each LLVM pass", time_llvm_passes),
("stats", "gather trans statistics", stats),
("trans-stats", "gather trans statistics", trans_stats),
("no-asm-comments", "omit comments when using -S", no_asm_comments),
("no-verify", "skip LLVM verification", no_verify),
("trace", "emit trace logs", trace),
@ -54,7 +55,9 @@ fn debugging_opts_map() -> ~[(str, str, uint)] {
("coherence", "perform coherence checking", coherence),
("borrowck-stats", "gather borrowck statistics", borrowck_stats),
("borrowck-note-pure", "note where purity is req'd",
borrowck_note_pure)
borrowck_note_pure),
("borrowck-note-loan", "note where loans are req'd",
borrowck_note_loan)
]
}
@ -172,6 +175,7 @@ impl session for session {
fn coherence() -> bool { self.debugging_opt(coherence) }
fn borrowck_stats() -> bool { self.debugging_opt(borrowck_stats) }
fn borrowck_note_pure() -> bool { self.debugging_opt(borrowck_note_pure) }
fn borrowck_note_loan() -> bool { self.debugging_opt(borrowck_note_loan) }
}
/// Some reasonable defaults

View File

@ -17,6 +17,7 @@ export get_class_fields;
export get_class_method;
export get_field_type;
export get_type_param_count;
export get_region_param;
export lookup_defs;
export lookup_method_purity;
export get_enum_variants;
@ -151,6 +152,12 @@ fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
decoder::get_type(cdata, def.node, tcx)
}
fn get_region_param(cstore: metadata::cstore::cstore,
def: ast::def_id) -> bool {
let cdata = cstore::get_crate_data(cstore, def.crate);
ret decoder::get_region_param(cdata, def.node);
}
fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
def: ast::def_id) -> ty::ty_param_bounds_and_ty {
let cstore = tcx.cstore;
@ -168,7 +175,7 @@ fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
class_id, def) );
#debug("got field data %?", the_field);
let ty = decoder::item_type(def, the_field, tcx, cdata);
ret {bounds: @~[], rp: ast::rp_none, ty: ty};
ret {bounds: @~[], rp: false, ty: ty};
}
// Given a def_id for an impl or class, return the trait it implements,

View File

@ -21,6 +21,7 @@ export get_class_fields;
export get_symbol;
export get_enum_variants;
export get_type;
export get_region_param;
export get_type_param_count;
export get_impl_trait;
export get_class_method;
@ -185,15 +186,10 @@ fn item_ty_param_bounds(item: ebml::doc, tcx: ty::ctxt, cdata: cmd)
@bounds
}
fn item_ty_region_param(item: ebml::doc) -> ast::region_param {
fn item_ty_region_param(item: ebml::doc) -> bool {
alt ebml::maybe_get_doc(item, tag_region_param) {
some(rp_doc) {
let dsr = ebml::ebml_deserializer(rp_doc);
ast::deserialize_region_param(dsr)
}
none { // not all families of items have region params
ast::rp_none
}
some(_) { true }
none { false }
}
}
@ -325,6 +321,11 @@ fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
ret {bounds: tp_bounds, rp: rp, ty: t};
}
fn get_region_param(cdata: cmd, id: ast::node_id) -> bool {
let item = lookup_item(id, cdata.data);
ret item_ty_region_param(item);
}
fn get_type_param_count(data: @~[u8], id: ast::node_id) -> uint {
item_ty_param_count(lookup_item(id, data))
}

View File

@ -86,10 +86,10 @@ fn encode_name_and_def_id(ebml_w: ebml::writer, nm: ident,
encode_def_id(ebml_w, local_def(id));
}
fn encode_region_param(ebml_w: ebml::writer, rp: region_param) {
do ebml_w.wr_tag(tag_region_param) {
serialize_region_param(ebml_w, rp)
}
fn encode_region_param(ecx: @encode_ctxt, ebml_w: ebml::writer,
it: @ast::item) {
let rp = ecx.tcx.region_paramd_items.contains_key(it.id);
if rp { do ebml_w.wr_tag(tag_region_param) { } }
}
fn encode_named_def_id(ebml_w: ebml::writer, name: ident, id: def_id) {
@ -188,12 +188,12 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
vec::append_one(path, it.ident), index);
}
}
item_ty(_, tps, _) {
item_ty(_, tps) {
do ebml_w.wr_tag(tag_paths_data_item) {
encode_name_and_def_id(ebml_w, it.ident, it.id);
}
}
item_class(_, _, items, ctor, m_dtor, _) {
item_class(_, _, items, ctor, m_dtor) {
do ebml_w.wr_tag(tag_paths_data_item) {
encode_name_and_def_id(ebml_w, it.ident, it.id);
}
@ -208,7 +208,7 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
index);
}
}
item_enum(variants, _, _) {
item_enum(variants, _) {
do ebml_w.wr_tag(tag_paths_data_item) {
encode_name_and_def_id(ebml_w, it.ident, it.id);
}
@ -406,7 +406,7 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
ref, we need to map it to its parent class */
ebml_w.wr_str(def_to_str(local_def(it.id)));
}
some(ast_map::node_item(@{node: item_impl(_,_,
some(ast_map::node_item(@{node: item_impl(_,
some(ifce),_,_),_},_)) {
ebml_w.wr_str(def_to_str(did));
}
@ -550,7 +550,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
let tcx = ecx.tcx;
let must_write =
alt item.node { item_enum(_, _, _) { true } _ { false } };
alt item.node { item_enum(_, _) { true } _ { false } };
if !must_write && !reachable(ecx, item.id) { ret; }
fn add_to_index_(item: @item, ebml_w: ebml::writer,
@ -598,7 +598,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_path(ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag();
}
item_ty(_, tps, rp) {
item_ty(_, tps) {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
@ -607,10 +607,10 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
encode_path(ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ebml_w, rp);
encode_region_param(ecx, ebml_w, item);
ebml_w.end_tag();
}
item_enum(variants, tps, rp) {
item_enum(variants, tps) {
add_to_index();
do ebml_w.wr_tag(tag_items_data_item) {
encode_def_id(ebml_w, local_def(item.id));
@ -623,12 +623,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
}
ecx.encode_inlined_item(ecx, ebml_w, path, ii_item(item));
encode_path(ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ebml_w, rp);
encode_region_param(ecx, ebml_w, item);
}
encode_enum_variant_info(ecx, ebml_w, item.id, variants,
path, index, tps);
}
item_class(tps, traits, items, ctor, m_dtor, rp) {
item_class(tps, traits, items, ctor, m_dtor) {
/* First, encode the fields and methods
These come first because we need to write them to make
the index, and the index needs to be in the item for the
@ -655,7 +655,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
encode_path(ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ebml_w, rp);
encode_region_param(ecx, ebml_w, item);
for traits.each |t| {
encode_trait_ref(ebml_w, ecx, t);
}
@ -704,12 +704,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_index(ebml_w, bkts, write_int);
ebml_w.end_tag();
}
item_impl(tps, rp, ifce, _, methods) {
item_impl(tps, ifce, _, methods) {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'i');
encode_region_param(ebml_w, rp);
encode_region_param(ecx, ebml_w, item);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
@ -733,12 +733,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
vec::append(tps, m.tps));
}
}
item_trait(tps, rp, ms) {
item_trait(tps, ms) {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'I');
encode_region_param(ebml_w, rp);
encode_region_param(ecx, ebml_w, item);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
@ -801,7 +801,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
encode_info_for_item(ecx, ebml_w, i, index, *pt);
/* encode ctor, then encode items */
alt i.node {
item_class(tps, _, _, ctor, m_dtor, _) {
item_class(tps, _, _, ctor, m_dtor) {
#debug("encoding info for ctor %s %d", *i.ident,
ctor.node.id);
vec::push(*index,

View File

@ -554,11 +554,11 @@ impl helpers for ebml::writer {
do self.emit_rec {
do self.emit_rec_field("bounds", 0u) {
do self.emit_from_vec(*tpbt.bounds) |bs| {
self.emit_bounds(ecx, bs)
self.emit_bounds(ecx, bs);
}
}
do self.emit_rec_field("rp", 1u) {
ast::serialize_region_param(self, tpbt.rp)
self.emit_bool(tpbt.rp);
}
do self.emit_rec_field("ty", 2u) {
self.emit_ty(ecx, tpbt.ty);
@ -759,7 +759,7 @@ impl decoder for ebml::ebml_deserializer {
@self.read_to_vec(|| self.read_bounds(xcx) )
}),
rp: self.read_rec_field("rp", 1u, || {
ast::deserialize_region_param(self)
self.read_bool()
}),
ty: self.read_rec_field("ty", 2u, || {
self.read_ty(xcx)

View File

@ -199,6 +199,12 @@ impl methods for gather_loan_ctxt {
if req_mutbl == m_imm && cmt.mutbl != m_imm {
self.bccx.loaned_paths_imm += 1;
if self.tcx().sess.borrowck_note_loan() {
self.bccx.span_note(
cmt.span,
#fmt["immutable loan required"]);
}
} else {
self.bccx.loaned_paths_same += 1;
}

View File

@ -24,7 +24,7 @@ fn check_item(sess: session, ast_map: ast_map::map, def_map: resolve::def_map,
v.visit_expr(ex, true, v);
check_item_recursion(sess, ast_map, def_map, it);
}
item_enum(vs, _, _) {
item_enum(vs, _) {
for vs.each |var| {
do option::iter(var.node.disr_expr) |ex| {
v.visit_expr(ex, true, v);

View File

@ -138,11 +138,13 @@ import syntax::{ast, visit};
import syntax::codemap::span;
import syntax::print::pprust;
import syntax::ast_util::new_def_hash;
import syntax::ast_map;
import dvec::{dvec, extensions};
import metadata::csearch;
import std::list;
import std::list::list;
import std::map;
import std::map::hashmap;
import std::map::{hashmap, int_hash};
type parent = option<ast::node_id>;
@ -386,7 +388,7 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
-> region_map {
let cx: ctxt = {sess: sess,
def_map: def_map,
region_map: map::int_hash(),
region_map: int_hash(),
parent: none};
let visitor = visit::mk_vt(@{
visit_block: resolve_block,
@ -402,3 +404,208 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
ret cx.region_map;
}
// ___________________________________________________________________________
// Determining region parameterization
//
// Infers which type defns must be region parameterized---this is done
// by scanning their contents to see whether they reference a region
// type, directly or indirectly. This is a fixed-point computation.
//
// We do it in two passes. First we walk the AST and construct a map
// from each type defn T1 to other defns which make use of it. For example,
// if we have a type like:
//
// type S = *int;
// type T = S;
//
// Then there would be a map entry from S to T. During the same walk,
// we also construct add any types that reference regions to a set and
// a worklist. We can then process the worklist, propagating indirect
// dependencies until a fixed point is reached.
type region_paramd_items = hashmap<ast::node_id, ()>;
type dep_map = hashmap<ast::node_id, @dvec<ast::node_id>>;
type determine_rp_ctxt = @{
sess: session,
ast_map: ast_map::map,
def_map: resolve::def_map,
region_paramd_items: region_paramd_items,
dep_map: dep_map,
worklist: dvec<ast::node_id>,
mut item_id: ast::node_id,
mut anon_implies_rp: bool
};
impl methods for determine_rp_ctxt {
fn add_rp(id: ast::node_id) {
assert id != 0;
if self.region_paramd_items.insert(id, ()) {
#debug["add region-parameterized item: %d (%s)",
id, ast_map::node_id_to_str(self.ast_map, id)];
self.worklist.push(id);
} else {
#debug["item %d already region-parameterized", id];
}
}
fn add_dep(from: ast::node_id, to: ast::node_id) {
#debug["add dependency from %d -> %d (%s -> %s)",
from, to,
ast_map::node_id_to_str(self.ast_map, from),
ast_map::node_id_to_str(self.ast_map, to)];
let vec = alt self.dep_map.find(from) {
some(vec) => {vec}
none => {
let vec = @dvec();
self.dep_map.insert(from, vec);
vec
}
};
if !vec.contains(to) { vec.push(to); }
}
fn region_is_relevant(r: @ast::region) -> bool {
alt r.node {
ast::re_anon {self.anon_implies_rp}
ast::re_named(@"self") {true}
ast::re_named(_) {false}
}
}
fn with(item_id: ast::node_id, anon_implies_rp: bool, f: fn()) {
let old_item_id = self.item_id;
let old_anon_implies_rp = self.anon_implies_rp;
self.item_id = item_id;
self.anon_implies_rp = anon_implies_rp;
#debug["with_item_id(%d, %b)", item_id, anon_implies_rp];
let _i = util::common::indenter();
f();
self.item_id = old_item_id;
self.anon_implies_rp = old_anon_implies_rp;
}
}
fn determine_rp_in_item(item: @ast::item,
&&cx: determine_rp_ctxt,
visitor: visit::vt<determine_rp_ctxt>) {
do cx.with(item.id, true) {
visit::visit_item(item, cx, visitor);
}
}
fn determine_rp_in_fn(fk: visit::fn_kind,
decl: ast::fn_decl,
body: ast::blk,
sp: span,
id: ast::node_id,
&&cx: determine_rp_ctxt,
visitor: visit::vt<determine_rp_ctxt>) {
do cx.with(cx.item_id, false) {
visit::visit_fn(fk, decl, body, sp, id, cx, visitor);
}
}
fn determine_rp_in_ty_method(ty_m: ast::ty_method,
&&cx: determine_rp_ctxt,
visitor: visit::vt<determine_rp_ctxt>) {
do cx.with(cx.item_id, false) {
visit::visit_ty_method(ty_m, cx, visitor);
}
}
fn determine_rp_in_ty(ty: @ast::ty,
&&cx: determine_rp_ctxt,
visitor: visit::vt<determine_rp_ctxt>) {
// we are only interesting in types that will require an item to
// be region-parameterized. if cx.item_id is zero, then this type
// is not a member of a type defn nor is it a constitutent of an
// impl etc. So we can ignore it and its components.
if cx.item_id == 0 { ret; }
// if this type directly references a region, either via a
// region pointer like &r.ty or a region-parameterized path
// like path/r, add to the worklist/set
alt ty.node {
ast::ty_rptr(r, _) |
ast::ty_path(@{rp: some(r), _}, _) |
ast::ty_vstore(_, ast::vstore_slice(r)) => {
#debug["referenced type with regions %s", pprust::ty_to_str(ty)];
if cx.region_is_relevant(r) {
cx.add_rp(cx.item_id);
}
}
_ => {}
}
// if this references another named type, add the dependency
// to the dep_map. If the type is not defined in this crate,
// then check whether it is region-parameterized and consider
// that as a direct dependency.
alt ty.node {
ast::ty_path(_, id) {
alt cx.def_map.get(id) {
ast::def_ty(did) | ast::def_class(did) {
if did.crate == ast::local_crate {
cx.add_dep(did.node, cx.item_id);
} else {
let cstore = cx.sess.cstore;
if csearch::get_region_param(cstore, did) {
#debug["reference to external, rp'd type %s",
pprust::ty_to_str(ty)];
cx.add_rp(cx.item_id);
}
}
}
_ {}
}
}
_ {}
}
visit::visit_ty(ty, cx, visitor);
}
fn determine_rp_in_crate(sess: session,
ast_map: ast_map::map,
def_map: resolve::def_map,
crate: @ast::crate) -> region_paramd_items {
let cx = @{sess: sess,
ast_map: ast_map,
def_map: def_map,
region_paramd_items: int_hash(),
dep_map: int_hash(),
worklist: dvec(),
mut item_id: 0,
mut anon_implies_rp: false};
// gather up the base set, worklist and dep_map:
let visitor = visit::mk_vt(@{
visit_fn: determine_rp_in_fn,
visit_item: determine_rp_in_item,
visit_ty: determine_rp_in_ty,
visit_ty_method: determine_rp_in_ty_method,
with *visit::default_visitor()
});
visit::visit_crate(*crate, cx, visitor);
// propagate indirect dependencies
while cx.worklist.len() != 0 {
let id = cx.worklist.pop();
#debug["popped %d from worklist", id];
alt cx.dep_map.find(id) {
none {}
some(vec) {
for vec.each |to_id| {
cx.add_rp(to_id);
}
}
}
}
// return final set
ret cx.region_paramd_items;
}

View File

@ -439,10 +439,10 @@ fn resolve_names(e: @env, c: @ast::crate) {
/* At this point, the code knows what traits the trait refs
refer to, so it's possible to resolve them.
*/
ast::item_impl(_, _, ifce, _, _) {
ast::item_impl(_, ifce, _, _) {
ifce.iter(|p| resolve_trait_ref(p, sc, e))
}
ast::item_class(_, traits, _, _, _, _) {
ast::item_class(_, traits, _, _, _) {
for traits.each |p| {
resolve_trait_ref(p, sc, e);
}
@ -552,7 +552,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
let sc = @cons(scope_item(i), sc);
alt i.node {
ast::item_impl(tps, _, ifce, sty, methods) {
ast::item_impl(tps, ifce, sty, methods) {
v.visit_ty_params(tps, sc, v);
option::iter(ifce, |p| visit::visit_path(p.path, sc, v));
v.visit_ty(sty, sc, v);
@ -564,7 +564,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
m.decl, m.body, m.span, m.id, msc, v);
}
}
ast::item_trait(tps, _, methods) {
ast::item_trait(tps, methods) {
v.visit_ty_params(tps, sc, v);
let isc = @cons(scope_method(i.id, tps), sc);
for methods.each |m| {
@ -574,7 +574,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
v.visit_ty(m.decl.output, msc, v);
}
}
ast::item_class(tps, traits, members, ctor, m_dtor, _) {
ast::item_class(tps, traits, members, ctor, m_dtor) {
v.visit_ty_params(tps, sc, v);
let class_scope = @cons(scope_item(i), sc);
/* visit the constructor... */
@ -1042,13 +1042,13 @@ fn lookup_in_scope(e: env, &&sc: scopes, sp: span, name: ident, ns: namespace,
}
scope_item(it) {
alt it.node {
ast::item_impl(tps, _, _, _, _) {
ast::item_impl(tps, _, _, _) {
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
}
ast::item_enum(_, tps, _) | ast::item_ty(_, tps, _) {
ast::item_enum(_, tps) | ast::item_ty(_, tps) {
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
}
ast::item_trait(tps, _, _) {
ast::item_trait(tps, _) {
if ns == ns_type {
if *name == "self" {
ret some(def_self(it.id));
@ -1062,7 +1062,7 @@ fn lookup_in_scope(e: env, &&sc: scopes, sp: span, name: ident, ns: namespace,
ast::item_foreign_mod(m) {
ret lookup_in_local_foreign_mod(e, it.id, sp, name, ns);
}
ast::item_class(tps, _, members, ctor, _, _) {
ast::item_class(tps, _, members, ctor, _) {
if ns == ns_type {
ret lookup_in_ty_params(e, name, tps);
}
@ -1234,7 +1234,7 @@ fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint,
}
ast::decl_item(it) {
alt it.node {
ast::item_enum(variants, _, _) {
ast::item_enum(variants, _) {
if ns == ns_type {
if str::eq(*it.ident, *name) {
ret some(ast::def_ty(local_def(it.id)));
@ -1339,7 +1339,7 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
ast::item_ty(*) | item_trait(*) | item_enum(*) {
if ns == ns_type { ret some(ast::def_ty(local_def(i.id))); }
}
ast::item_class(_, _, _members, ct, _, _) {
ast::item_class(_, _, _members, ct, _) {
alt ns {
ns_type {
ret some(ast::def_class(local_def(i.id)));
@ -1641,11 +1641,11 @@ fn index_mod(md: ast::_mod) -> mod_index {
for md.items.each |it| {
alt it.node {
ast::item_const(_, _) | ast::item_fn(_, _, _) | ast::item_mod(_) |
ast::item_foreign_mod(_) | ast::item_ty(_, _, _) |
ast::item_foreign_mod(_) | ast::item_ty(_, _) |
ast::item_impl(*) | ast::item_trait(*) {
add_to_index(index, it.ident, mie_item(it));
}
ast::item_enum(variants, _, _) {
ast::item_enum(variants, _) {
add_to_index(index, it.ident, mie_item(it));
let mut variant_idx: uint = 0u;
for variants.each |v| {
@ -1655,7 +1655,7 @@ fn index_mod(md: ast::_mod) -> mod_index {
variant_idx += 1u;
}
}
ast::item_class(tps, _, items, ctor, _, _) {
ast::item_class(tps, _, items, ctor, _) {
// add the class name itself
add_to_index(index, it.ident, mie_item(it));
}
@ -1780,15 +1780,15 @@ fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) {
ensure_unique(*e, i.span, ty_params, |tp| tp.ident,
"type parameter");
}
ast::item_enum(_, ty_params, _) {
ast::item_enum(_, ty_params) {
ensure_unique(*e, i.span, ty_params, |tp| tp.ident,
"type parameter");
}
ast::item_trait(_, _, methods) {
ast::item_trait(_, methods) {
ensure_unique(*e, i.span, methods, |m| m.ident,
"method");
}
ast::item_impl(_, _, _, _, methods) {
ast::item_impl(_, _, _, methods) {
ensure_unique(*e, i.span, methods, |m| m.ident,
"method");
}
@ -1854,7 +1854,7 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
}
ast::decl_item(it) {
alt it.node {
ast::item_enum(variants, _, _) {
ast::item_enum(variants, _) {
add_name(types, it.span, it.ident);
for variants.each |v| {
add_name(values, v.span, v.node.name);
@ -2051,7 +2051,7 @@ fn check_exports(e: @env) {
some(ms) {
let maybe_id = do list_search(ms) |m| {
alt m {
mie_item(@{node: item_enum(_, _, _), id, _}) { some(id) }
mie_item(@{node: item_enum(_, _), id, _}) { some(id) }
_ { none }
}
};
@ -2242,7 +2242,7 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: ~[@_impl],
name: option<ident>,
ck_exports: option<@indexed_mod>) {
alt i.node {
ast::item_impl(_, _, ifce, _, mthds) {
ast::item_impl(_, ifce, _, mthds) {
if alt name { some(n) { n == i.ident } _ { true } } &&
alt ck_exports {
some(m) { is_exported(e, i.ident, m) }
@ -2257,7 +2257,7 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: ~[@_impl],
})});
}
}
ast::item_class(tps, ifces, items, _, _, _) {
ast::item_class(tps, ifces, items, _, _) {
let (_, mthds) = ast_util::split_class_items(items);
let n_tps = tps.len();
do vec::iter(ifces) |p| {

View File

@ -847,7 +847,7 @@ class Resolver {
}
// These items live in both the type and value namespaces.
item_enum(variants, _, _) {
item_enum(variants, _) {
(*name_bindings).define_type(def_ty(local_def(item.id)));
for variants.each |variant| {
@ -857,7 +857,7 @@ class Resolver {
visitor);
}
}
item_class(_, _, class_members, ctor, _, _) {
item_class(_, _, class_members, ctor, _) {
(*name_bindings).define_type(def_ty(local_def(item.id)));
let purity = ctor.node.dec.purity;
@ -899,7 +899,7 @@ class Resolver {
visit_item(item, new_parent, visitor);
}
item_impl(_, _, _, _, methods) {
item_impl(_, _, _, methods) {
// Create the set of implementation information that the
// implementation scopes (ImplScopes) need and write it into
// the implementation definition list for this set of name
@ -2884,8 +2884,8 @@ class Resolver {
}
alt item.node {
item_enum(_, type_parameters, _) |
item_ty(_, type_parameters, _) {
item_enum(_, type_parameters) |
item_ty(_, type_parameters) {
do self.with_type_parameter_rib
(HasTypeParameters(&type_parameters, item.id, 0u,
NormalRibKind))
@ -2895,7 +2895,7 @@ class Resolver {
}
}
item_impl(type_parameters, _, interface_reference, self_type,
item_impl(type_parameters, interface_reference, self_type,
methods) {
self.resolve_implementation(item.id,
item.span,
@ -2906,7 +2906,7 @@ class Resolver {
visitor);
}
item_trait(type_parameters, _, methods) {
item_trait(type_parameters, methods) {
// Create a new rib for the self type.
let self_type_rib = @Rib(NormalRibKind);
(*self.type_ribs).push(self_type_rib);
@ -2948,7 +2948,7 @@ class Resolver {
}
item_class(ty_params, interfaces, class_members, constructor,
optional_destructor, _) {
optional_destructor) {
self.resolve_class(item.id,
@copy ty_params,

View File

@ -2291,7 +2291,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
ccx.external.insert(parent_id, some(item.id));
let mut my_id = 0;
alt check item.node {
ast::item_enum(_, _, _) {
ast::item_enum(_, _) {
let vs_here = ty::enum_variants(ccx.tcx, local_def(item.id));
let vs_there = ty::enum_variants(ccx.tcx, parent_id);
do vec::iter2(*vs_here, *vs_there) |here, there| {
@ -4886,13 +4886,13 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
}
}
}
ast::item_impl(tps, _rp, _, _, ms) {
ast::item_impl(tps, _, _, ms) {
impl::trans_impl(ccx, *path, item.ident, ms, tps);
}
ast::item_mod(m) {
trans_mod(ccx, m);
}
ast::item_enum(variants, tps, _) {
ast::item_enum(variants, tps) {
if tps.len() == 0u {
let degen = variants.len() == 1u;
let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
@ -4916,7 +4916,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
};
foreign::trans_foreign_mod(ccx, foreign_mod, abi);
}
ast::item_class(tps, _traits, items, ctor, m_dtor, _) {
ast::item_class(tps, _traits, items, ctor, m_dtor) {
if tps.len() == 0u {
let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps),
vtables: none,
@ -5199,7 +5199,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
~[path_name(enm.ident),
path_name(v.node.name)]);
let llfn = alt check enm.node {
ast::item_enum(_, _, _) {
ast::item_enum(_, _) {
register_fn(ccx, v.span, pth, id)
}
};
@ -5220,7 +5220,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
fn trans_constant(ccx: @crate_ctxt, it: @ast::item) {
let _icx = ccx.insn_ctxt("trans_constant");
alt it.node {
ast::item_enum(variants, _, _) {
ast::item_enum(variants, _) {
let vi = ty::enum_variants(ccx.tcx, {crate: ast::local_crate,
node: it.id});
let mut i = 0;

View File

@ -84,11 +84,11 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
name: ast::ident) -> ast::def_id {
if impl_id.crate == ast::local_crate {
alt check ccx.tcx.items.get(impl_id.node) {
ast_map::node_item(@{node: ast::item_impl(_, _, _, _, ms), _}, _) {
ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) {
method_from_methods(ms, name)
}
ast_map::node_item(@{node:
ast::item_class(_, _, items, _, _, _), _}, _) {
ast::item_class(_, _, items, _, _), _}, _) {
let (_,ms) = split_class_items(items);
method_from_methods(ms, name)
}

View File

@ -112,7 +112,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
traverse_inline_body(cx, blk);
}
}
item_impl(tps, _, _, _, ms) {
item_impl(tps, _, _, ms) {
for vec::each(ms) |m| {
if tps.len() > 0u || m.tps.len() > 0u ||
attr::find_inline_attr(m.attrs) != attr::ia_none {
@ -121,7 +121,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
}
}
}
item_class(tps, _traits, items, ctor, m_dtor, _) {
item_class(tps, _traits, items, ctor, m_dtor) {
cx.rmap.insert(ctor.node.id, ());
do option::iter(m_dtor) |dtor| {
cx.rmap.insert(dtor.node.id, ());
@ -143,7 +143,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
}
}
}
item_ty(t, _, _) {
item_ty(t, _) {
traverse_ty(t, cx, mk_ty_visitor());
}
item_const(*) |
@ -218,7 +218,7 @@ fn traverse_all_resources(cx: ctx, crate_mod: _mod) {
visit_item: |i, cx, v| {
visit::visit_item(i, cx, v);
alt i.node {
item_class(_, _, _, _, some(_), _) {
item_class(_, _, _, _, some(_)) {
traverse_public_item(cx, i);
}
_ {}

View File

@ -52,7 +52,7 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
item_class(*) {
fail "find_pre_post_item: shouldn't be called on item_class";
}
item_impl(_, _, _, _, ms) {
item_impl(_, _, _, ms) {
for ms.each |m| { find_pre_post_method(ccx, m); }
}
item_mac(*) { fail "item macros unimplemented" }

View File

@ -233,7 +233,9 @@ type ctxt =
cstore: metadata::cstore::cstore,
sess: session::session,
def_map: resolve::def_map,
region_map: middle::region::region_map,
region_paramd_items: middle::region::region_paramd_items,
// Stores the types for various nodes in the AST. Note that this table
// is not guaranteed to be populated until after typeck. See
@ -482,7 +484,7 @@ fn param_bounds_to_kind(bounds: param_bounds) -> kind {
}
type ty_param_bounds_and_ty = {bounds: @~[param_bounds],
rp: ast::region_param,
rp: bool,
ty: t};
type type_cache = hashmap<ast::def_id, ty_param_bounds_and_ty>;
@ -505,9 +507,12 @@ fn new_ty_hash<V: copy>() -> map::hashmap<t, V> {
|&&a: t, &&b: t| type_id(a) == type_id(b))
}
fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
fn mk_ctxt(s: session::session,
dm: resolve::def_map,
amap: ast_map::map,
freevars: freevars::freevar_map,
region_map: middle::region::region_map) -> ctxt {
region_map: middle::region::region_map,
region_paramd_items: middle::region::region_paramd_items) -> ctxt {
let interner = map::hashmap(|&&k: intern_key| {
hash_type_structure(k.struct) +
option::map_default(k.o_def_id, 0u, ast_util::hash_def)
@ -523,6 +528,7 @@ fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
sess: s,
def_map: dm,
region_map: region_map,
region_paramd_items: region_paramd_items,
node_types: @smallintmap::mk(),
node_type_substs: map::int_hash(),
items: amap,
@ -2543,10 +2549,10 @@ fn impl_trait(cx: ctxt, id: ast::def_id) -> option<t> {
#debug("(impl_trait) searching for trait impl %?", id);
alt cx.items.find(id.node) {
some(ast_map::node_item(@{node: ast::item_impl(
_, _, some(@{id: id, _}), _, _), _}, _)) {
_, some(@{id: id, _}), _, _), _}, _)) {
some(node_id_to_type(cx, id))
}
some(ast_map::node_item(@{node: ast::item_class(_, _, _, _, _, _),
some(ast_map::node_item(@{node: ast::item_class(*),
_},_)) {
alt cx.def_map.find(id.node) {
some(def_ty(trait_id)) {
@ -2606,7 +2612,7 @@ fn ty_dtor(cx: ctxt, class_id: def_id) -> option<def_id> {
if is_local(class_id) {
alt cx.items.find(class_id.node) {
some(ast_map::node_item(@{node: ast::item_class(_, _, _, _,
some(dtor), _), _}, _))
some(dtor)), _}, _))
{ some(local_def(dtor.node.id)) }
_ { none }
}
@ -2687,7 +2693,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[variant_info] {
expr, since check_enum_variants also updates the enum_var_cache
*/
alt cx.items.get(id.node) {
ast_map::node_item(@{node: ast::item_enum(variants, _, _), _}, _) {
ast_map::node_item(@{node: ast::item_enum(variants, _), _}, _) {
let mut disr_val = -1;
@vec::map(variants, |variant| {
let ctor_ty = node_id_to_type(cx, variant.node.id);
@ -2780,7 +2786,7 @@ fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
alt cx.items.find(did.node) {
some(ast_map::node_item(i,_)) {
alt i.node {
ast::item_class(_, _, items, _, _, _) {
ast::item_class(_, _, items, _, _) {
class_field_tys(items)
}
_ { cx.sess.bug("class ID bound to non-class"); }
@ -2822,7 +2828,7 @@ pure fn is_public(f: field_ty) -> bool {
fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
: is_local(did) -> ~[{name: ident, id: node_id, vis: visibility}] {
alt cx.items.find(did.node) {
some(ast_map::node_item(@{node: item_class(_,_,items,_,_,_), _}, _)) {
some(ast_map::node_item(@{node: item_class(_,_,items,_,_), _}, _)) {
let (_,ms) = split_class_items(items);
vec::map(ms, |m| {name: m.ident, id: m.id,
vis: m.vis})

View File

@ -185,7 +185,7 @@ fn lookup_def_ccx(ccx: @crate_ctxt, sp: span, id: ast::node_id) -> ast::def {
}
fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty {
{bounds: @~[], rp: ast::rp_none, ty: t}
{bounds: @~[], rp: false, ty: t}
}
fn require_same_types(

View File

@ -87,14 +87,17 @@ fn ast_path_to_substs_and_ty<AC: ast_conv, RS: region_scope copy>(
let {bounds: decl_bounds, rp: decl_rp, ty: decl_ty} =
self.get_item_ty(did);
#debug["ast_path_to_substs_and_ty: did=%? decl_rp=%b",
did, decl_rp];
// If the type is parameterized by the self region, then replace self
// region with the current anon region binding (in other words,
// whatever & would get replaced with).
let self_r = alt (decl_rp, path.rp) {
(ast::rp_none, none) {
(false, none) {
none
}
(ast::rp_none, some(_)) {
(false, some(_)) {
tcx.sess.span_err(
path.span,
#fmt["no region bound is permitted on %s, \
@ -102,12 +105,12 @@ fn ast_path_to_substs_and_ty<AC: ast_conv, RS: region_scope copy>(
ty::item_path_str(tcx, did)]);
none
}
(ast::rp_self, none) {
(true, none) {
let res = rscope.anon_region();
let r = get_region_reporting_err(self.tcx(), path.span, res);
some(r)
}
(ast::rp_self, some(r)) {
(true, some(r)) {
some(ast_region_to_region(self, rscope, path.span, r))
}
};

View File

@ -66,7 +66,7 @@ type parameter).
*/
import astconv::{ast_conv, ast_ty_to_ty};
import astconv::{ast_conv, ast_ty_to_ty, ast_region_to_region};
import collect::{methods}; // ccx.to_ty()
import middle::ty::{tv_vid, vid};
import regionmanip::{replace_bound_regions_in_fn_ty, region_of};
@ -348,17 +348,20 @@ fn check_class_member(ccx: @crate_ctxt, class_t: ty::t,
fn check_item(ccx: @crate_ctxt, it: @ast::item) {
alt it.node {
ast::item_const(_, e) { check_const(ccx, it.span, e, it.id); }
ast::item_enum(vs, _, _) {
ast::item_enum(vs, _) {
check_enum_variants(ccx, it.span, vs, it.id);
}
ast::item_fn(decl, tps, body) {
check_bare_fn(ccx, decl, body, it.id, none);
}
ast::item_impl(tps, rp, _, ty, ms) {
ast::item_impl(tps, _, ty, ms) {
let rp = ccx.tcx.region_paramd_items.contains_key(it.id);
#debug["item_impl %s with id %d rp %b",
*it.ident, it.id, rp];
let self_ty = ccx.to_ty(rscope::type_rscope(rp), ty);
for ms.each |m| { check_method(ccx, m, self_ty);}
}
ast::item_class(tps, traits, members, ctor, m_dtor, rp) {
ast::item_class(tps, traits, members, ctor, m_dtor) {
let tcx = ccx.tcx;
let class_t = ty::node_id_to_type(tcx, it.id);
// typecheck the ctor
@ -387,9 +390,9 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
// Check that the class is instantiable
check_instantiable(ccx.tcx, it.span, it.id);
}
ast::item_ty(t, tps, rp) {
ast::item_ty(t, tps) {
let tpt_ty = ty::node_id_to_type(ccx.tcx, it.id);
check_bounds_are_used(ccx, t.span, tps, rp, tpt_ty);
check_bounds_are_used(ccx, t.span, tps, tpt_ty);
}
ast::item_foreign_mod(m) {
if syntax::attr::foreign_abi(it.attrs) ==
@ -647,15 +650,16 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
let tcx = fcx.ccx.tcx;
let {n_tps, rp, raw_ty} = if did.crate == ast::local_crate {
let rp = fcx.tcx().region_paramd_items.contains_key(did.node);
alt check tcx.items.find(did.node) {
some(ast_map::node_item(@{node: ast::item_impl(ts, rp, _, st, _),
some(ast_map::node_item(@{node: ast::item_impl(ts, _, st, _),
_}, _)) {
{n_tps: ts.len(),
rp: rp,
raw_ty: fcx.ccx.to_ty(rscope::type_rscope(rp), st)}
}
some(ast_map::node_item(@{node: ast::item_class(ts,
_,_,_,_,rp), id: class_id, _},_)) {
_,_,_,_), id: class_id, _},_)) {
/* If the impl is a class, the self ty is just the class ty
(doing a no-op subst for the ty params; in the next step,
we substitute in fresh vars for them)
@ -663,9 +667,8 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
{n_tps: ts.len(),
rp: rp,
raw_ty: ty::mk_class(tcx, local_def(class_id),
{self_r: alt rp {
ast::rp_self { some(fcx.infcx.next_region_var()) }
ast::rp_none { none }},
{self_r: if rp {some(ty::re_bound(ty::br_self))}
else {none},
self_ty: none,
tps: ty::ty_params_to_tys(tcx, ts)})}
}
@ -679,10 +682,7 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
raw_ty: ity.ty}
};
let self_r = alt rp {
ast::rp_none { none }
ast::rp_self { some(fcx.infcx.next_region_var()) }
};
let self_r = if rp {some(fcx.infcx.next_region_var())} else {none};
let tps = fcx.infcx.next_ty_vars(n_tps);
let substs = {self_r: self_r, self_ty: none, tps: tps};
@ -2053,7 +2053,7 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
// extern functions are just u8 pointers
ret {
bounds: @~[],
rp: ast::rp_none,
rp: false,
ty: ty::mk_ptr(
fcx.ccx.tcx,
{
@ -2109,13 +2109,27 @@ fn instantiate_path(fcx: @fn_ctxt,
let ty_param_count = vec::len(*tpt.bounds);
let ty_substs_len = vec::len(pth.types);
// For now, there is no way to explicitly specify the region bound.
// This will have to change eventually.
let self_r = alt tpt.rp {
ast::rp_self { some(fcx.infcx.next_region_var()) }
ast::rp_none { none }
// determine the region bound, using the value given by the user
// (if any) and otherwise using a fresh region variable
let self_r = alt pth.rp {
some(r) if !tpt.rp => {
fcx.ccx.tcx.sess.span_err
(sp, "this item is not region-parameterized");
none
}
some(r) => {
some(ast_region_to_region(fcx, fcx, sp, r))
}
none if tpt.rp => {
some(fcx.infcx.next_region_var())
}
none => {
none
}
};
// determine values for type parameters, using the values given by
// the user (if any) and otherwise using fresh type variables
let tps = if ty_substs_len == 0u {
fcx.infcx.next_ty_vars(ty_param_count)
} else if ty_param_count == 0u {
@ -2203,24 +2217,14 @@ fn ast_expr_vstore_to_vstore(fcx: @fn_ctxt, e: @ast::expr, n: uint,
fn check_bounds_are_used(ccx: @crate_ctxt,
span: span,
tps: ~[ast::ty_param],
rp: ast::region_param,
ty: ty::t) {
let mut r_used = alt rp {
ast::rp_self { false }
ast::rp_none { true }
};
if tps.len() == 0u && r_used { ret; }
// make a vector of booleans initially false, set to true when used
if tps.len() == 0u { ret; }
let tps_used = vec::to_mut(vec::from_elem(tps.len(), false));
ty::walk_regions_and_ty(
ccx.tcx, ty,
|r| {
alt r {
ty::re_bound(_) { r_used = true; }
_ { }
}
},
|_r| {},
|t| {
alt ty::get(t).struct {
ty::ty_param(idx, _) { tps_used[idx] = true; }
@ -2229,12 +2233,6 @@ fn check_bounds_are_used(ccx: @crate_ctxt,
true
});
if !r_used {
ccx.tcx.sess.span_err(
span, "lifetime `self` unused inside \
reference-parameterized type");
}
for tps_used.eachi |i, b| {
if !b {
ccx.tcx.sess.span_err(

View File

@ -15,7 +15,7 @@ import middle::typeck::infer::{infer_ctxt, mk_subty, new_infer_ctxt};
import syntax::ast::{crate, def_id, item, item_class, item_const, item_enum};
import syntax::ast::{item_fn, item_foreign_mod, item_impl, item_mac};
import syntax::ast::{item_mod, item_trait, item_ty, local_crate, method};
import syntax::ast::{node_id, region_param, rp_none, rp_self, trait_ref};
import syntax::ast::{node_id, trait_ref};
import syntax::ast_util::{def_id_of_def, new_def_hash};
import syntax::visit::{default_simple_visitor, default_visitor};
import syntax::visit::{mk_simple_visitor, mk_vt, visit_crate, visit_item};
@ -76,7 +76,7 @@ class CoherenceChecker {
visit_crate(*crate, (), mk_simple_visitor(@{
visit_item: |item| {
alt item.node {
item_impl(_, _, associated_trait, self_type, _) {
item_impl(_, associated_trait, self_type, _) {
self.check_implementation(item, associated_trait);
}
_ {
@ -239,15 +239,9 @@ class CoherenceChecker {
// Converts a polytype to a monotype by replacing all parameters with
// type variables.
fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t {
let self_region;
alt polytype.rp {
rp_none {
self_region = none;
}
rp_self {
self_region = some(self.inference_context.next_region_var())
}
};
let self_region =
if polytype.rp {none}
else {some(self.inference_context.next_region_var())};
let bounds_count = polytype.bounds.len();
let type_parameters =
@ -304,7 +298,7 @@ class CoherenceChecker {
self.privileged_types.remove(privileged_type);
}
}
item_impl(_, _, optional_trait_ref, _, _) {
item_impl(_, optional_trait_ref, _, _) {
alt self.base_type_def_ids.find(item.id) {
none {
// Nothing to do.

View File

@ -39,13 +39,13 @@ fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) {
alt intrinsic_item.node {
ast::item_trait(_, _, _) {
ast::item_trait(_, _) {
let ty = ty::mk_trait(ccx.tcx, def_id, substs);
ccx.tcx.intrinsic_defs.insert
(intrinsic_item.ident, (def_id, ty));
}
ast::item_enum(_, _, _) {
ast::item_enum(_, _) {
let ty = ty::mk_enum(ccx.tcx, def_id, substs);
ccx.tcx.intrinsic_defs.insert
(intrinsic_item.ident, (def_id, ty));
@ -107,7 +107,7 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
enum_ty: ty::t,
variants: ~[ast::variant],
ty_params: ~[ast::ty_param],
rp: ast::region_param) {
rp: bool) {
let tcx = ccx.tcx;
// Create a set of parameter types shared among all the variants.
@ -144,13 +144,14 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id) {
}
let tcx = ccx.tcx;
let rp = tcx.region_paramd_items.contains_key(id);
alt check tcx.items.get(id) {
ast_map::node_item(@{node: ast::item_trait(_, rp, ms), _}, _) {
ast_map::node_item(@{node: ast::item_trait(_, ms), _}, _) {
store_methods::<ast::ty_method>(ccx, id, ms, |m| {
ty_of_ty_method(ccx, m, rp)
});
}
ast_map::node_item(@{node: ast::item_class(_,_,its,_,_,rp), _}, _) {
ast_map::node_item(@{node: ast::item_class(_,_,its,_,_), _}, _) {
let (_,ms) = split_class_items(its);
// All methods need to be stored, since lookup_method
// relies on the same method cache for self-calls
@ -234,7 +235,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span,
fn check_methods_against_trait(ccx: @crate_ctxt,
tps: ~[ast::ty_param],
rp: ast::region_param,
rp: bool,
selfty: ty::t,
a_trait_ty: @ast::trait_ref,
ms: ~[converted_method]) {
@ -267,7 +268,7 @@ fn check_methods_against_trait(ccx: @crate_ctxt,
} // fn
fn convert_class_item(ccx: @crate_ctxt,
rp: ast::region_param,
rp: bool,
bounds: @~[ty::param_bounds],
v: ast_util::ivar) {
let tt = ccx.to_ty(type_rscope(rp), v.ty);
@ -280,7 +281,7 @@ type converted_method = {mty: ty::method, id: ast::node_id, span: span};
fn convert_methods(ccx: @crate_ctxt,
ms: ~[@ast::method],
rp: ast::region_param,
rp: bool,
rcvr_bounds: @~[ty::param_bounds],
self_ty: ty::t) -> ~[converted_method] {
@ -303,16 +304,17 @@ fn convert_methods(ccx: @crate_ctxt,
fn convert(ccx: @crate_ctxt, it: @ast::item) {
let tcx = ccx.tcx;
let rp = tcx.region_paramd_items.contains_key(it.id);
#debug["convert: item %s with id %d rp %b", *it.ident, it.id, rp];
alt it.node {
// These don't define types.
ast::item_foreign_mod(_) | ast::item_mod(_) {}
ast::item_enum(variants, ty_params, rp) {
ast::item_enum(variants, ty_params) {
let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty);
get_enum_variant_types(ccx, tpt.ty, variants,
ty_params, rp);
get_enum_variant_types(ccx, tpt.ty, variants, ty_params, rp);
}
ast::item_impl(tps, rp, ifce, selfty, ms) {
ast::item_impl(tps, ifce, selfty, ms) {
let i_bounds = ty_param_bounds(ccx, tps);
let selfty = ccx.to_ty(type_rscope(rp), selfty);
write_ty_to_tcx(tcx, it.id, selfty);
@ -333,7 +335,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
write_ty_to_tcx(tcx, it.id, tpt.ty);
ensure_trait_methods(ccx, it.id);
}
ast::item_class(tps, traits, members, ctor, m_dtor, rp) {
ast::item_class(tps, traits, members, ctor, m_dtor) {
// Write the class type
let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty);
@ -341,20 +343,19 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
// Write the ctor type
let t_args = ctor.node.dec.inputs.map(
|a| ty_of_arg(ccx, type_rscope(rp), a, none) );
let t_res = ty::mk_class(tcx, local_def(it.id),
{self_r: alt rp {
ast::rp_none { none }
ast::rp_self { some(ty::re_bound(ty::br_self)) }
},
self_ty: none,
tps: ty::ty_params_to_tys(tcx, tps)});
let t_ctor = ty::mk_fn(tcx, {purity: ast::impure_fn,
proto: ast::proto_any,
inputs: t_args,
output: t_res,
ret_style: ast::return_val,
constraints: ~[]}); // FIXME (#2813): allow ctors to have
// constraints, or remove constraints from the language
let t_res = ty::mk_class(
tcx, local_def(it.id),
{self_r: if rp {some(ty::re_bound(ty::br_self))} else {none},
self_ty: none,
tps: ty::ty_params_to_tys(tcx, tps)});
let t_ctor = ty::mk_fn(
tcx, {purity: ast::impure_fn,
proto: ast::proto_any,
inputs: t_args,
output: t_res,
ret_style: ast::return_val,
constraints: ~[]}); // FIXME (#2813): allow ctors to have
// constraints, or remove constraints from the language
write_ty_to_tcx(tcx, ctor.node.id, t_ctor);
tcx.tcache.insert(local_def(ctor.node.id),
{bounds: tpt.bounds,
@ -421,18 +422,18 @@ fn convert_foreign(ccx: @crate_ctxt, i: @ast::foreign_item) {
fn ty_of_method(ccx: @crate_ctxt,
m: @ast::method,
rp: ast::region_param) -> ty::method {
rp: bool) -> ty::method {
{ident: m.ident,
tps: ty_param_bounds(ccx, m.tps),
fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare,
m.decl, none),
m.decl, none),
purity: m.decl.purity,
vis: m.vis}
}
fn ty_of_ty_method(self: @crate_ctxt,
m: ast::ty_method,
rp: ast::region_param) -> ty::method {
rp: bool) -> ty::method {
{ident: m.ident,
tps: ty_param_bounds(self, m.tps),
fty: ty_of_fn_decl(self, type_rscope(rp), ast::proto_bare,
@ -446,8 +447,7 @@ fn ty_of_ty_method(self: @crate_ctxt,
it's bound to a valid trait type. Returns the def_id for the defining
trait. Fails if the type is a type other than an trait type.
*/
fn instantiate_trait_ref(ccx: @crate_ctxt, t: @ast::trait_ref,
rp: ast::region_param)
fn instantiate_trait_ref(ccx: @crate_ctxt, t: @ast::trait_ref, rp: bool)
-> (ast::def_id, ty_param_substs_and_ty) {
let sp = t.path.span, err = "can only implement interface types",
@ -480,6 +480,7 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
some(tpt) { ret tpt; }
_ {}
}
let rp = tcx.region_paramd_items.contains_key(it.id);
alt it.node {
ast::item_const(t, _) {
let typ = ccx.to_ty(empty_rscope, t);
@ -492,19 +493,20 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
let tofd = ty_of_fn_decl(ccx, empty_rscope, ast::proto_bare,
decl, none);
let tpt = {bounds: bounds,
rp: ast::rp_none, // functions do not have a self
rp: false, // functions do not have a self
ty: ty::mk_fn(ccx.tcx, tofd)};
#debug["type of %s (id %d) is %s",
*it.ident, it.id, ty_to_str(tcx, tpt.ty)];
ccx.tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_ty(t, tps, rp) {
ast::item_ty(t, tps) {
alt tcx.tcache.find(local_def(it.id)) {
some(tpt) { ret tpt; }
none { }
}
let rp = tcx.region_paramd_items.contains_key(it.id);
let tpt = {
let ty = {
let t0 = ccx.to_ty(type_rscope(rp), t);
@ -522,7 +524,7 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_enum(_, tps, rp) {
ast::item_enum(_, tps) {
// Create a new generic polytype.
let {bounds, substs} = mk_substs(ccx, tps, rp);
let t = ty::mk_enum(tcx, local_def(it.id), substs);
@ -530,14 +532,14 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_trait(tps, rp, ms) {
ast::item_trait(tps, ms) {
let {bounds, substs} = mk_substs(ccx, tps, rp);
let t = ty::mk_trait(tcx, local_def(it.id), substs);
let tpt = {bounds: bounds, rp: rp, ty: t};
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
ast::item_class(tps, _, _, _, _, rp) {
ast::item_class(tps, _, _, _, _) {
let {bounds,substs} = mk_substs(ccx, tps, rp);
let t = ty::mk_class(tcx, local_def(it.id), substs);
let tpt = {bounds: bounds, rp: rp, ty: t};
@ -555,7 +557,7 @@ fn ty_of_foreign_item(ccx: @crate_ctxt, it: @ast::foreign_item)
alt it.node {
ast::foreign_item_fn(fn_decl, params) {
ret ty_of_foreign_fn_decl(ccx, fn_decl, params,
local_def(it.id));
local_def(it.id));
}
}
}
@ -615,7 +617,7 @@ fn ty_of_foreign_fn_decl(ccx: @crate_ctxt,
output: output_ty,
ret_style: ast::return_val,
constraints: ~[]});
let tpt = {bounds: bounds, rp: ast::rp_none, ty: t_fn};
let tpt = {bounds: bounds, rp: false, ty: t_fn};
ccx.tcx.tcache.insert(def_id, tpt);
ret tpt;
}
@ -633,13 +635,10 @@ fn mk_ty_params(ccx: @crate_ctxt, atps: ~[ast::ty_param])
})}
}
fn mk_substs(ccx: @crate_ctxt, atps: ~[ast::ty_param], rp: ast::region_param)
fn mk_substs(ccx: @crate_ctxt, atps: ~[ast::ty_param], rp: bool)
-> {bounds: @~[ty::param_bounds], substs: ty::substs} {
let {bounds, params} = mk_ty_params(ccx, atps);
let self_r = alt rp {
ast::rp_self { some(ty::re_bound(ty::br_self)) }
ast::rp_none { none }
};
let self_r = if rp {some(ty::re_bound(ty::br_self))} else {none};
{bounds: bounds, substs: {self_r: self_r, self_ty: none, tps: params}}
}

View File

@ -16,15 +16,14 @@ impl of region_scope for empty_rscope {
}
}
enum type_rscope = ast::region_param;
enum type_rscope = bool;
impl of region_scope for type_rscope {
fn anon_region() -> result<ty::region, str> {
alt *self {
ast::rp_self { result::ok(ty::re_bound(ty::br_self)) }
ast::rp_none {
if *self {
result::ok(ty::re_bound(ty::br_self))
} else {
result::err("to use region types here, the containing type \
must be declared with a region bound")
}
}
}
fn named_region(id: ast::ident) -> result<ty::region, str> {

View File

@ -147,7 +147,7 @@ fn fold_enum(
let desc = do astsrv::exec(srv) |ctxt| {
alt check ctxt.ast_map.get(doc_id) {
ast_map::node_item(@{
node: ast::item_enum(ast_variants, _, _), _
node: ast::item_enum(ast_variants, _), _
}, _) {
let ast_variant = option::get(
vec::find(ast_variants, |v| {
@ -204,14 +204,14 @@ fn merge_method_attrs(
let attrs: ~[(str, option<str>)] = do astsrv::exec(srv) |ctxt| {
alt ctxt.ast_map.get(item_id) {
ast_map::node_item(@{
node: ast::item_trait(_, _, methods), _
node: ast::item_trait(_, methods), _
}, _) {
par::seqmap(methods, |method| {
(*method.ident, attr_parser::parse_desc(method.attrs))
})
}
ast_map::node_item(@{
node: ast::item_impl(_, _, _, _, methods), _
node: ast::item_impl(_, _, _, methods), _
}, _) {
par::seqmap(methods, |method| {
(*method.ident, attr_parser::parse_desc(method.attrs))

View File

@ -78,22 +78,22 @@ fn moddoc_from_mod(
constdoc_from_const(itemdoc)
))
}
ast::item_enum(variants, _, _) {
ast::item_enum(variants, _) {
some(doc::enumtag(
enumdoc_from_enum(itemdoc, variants)
))
}
ast::item_trait(_, _, methods) {
ast::item_trait(_, methods) {
some(doc::traittag(
traitdoc_from_trait(itemdoc, methods)
))
}
ast::item_impl(_, _, _, _, methods) {
ast::item_impl(_, _, _, methods) {
some(doc::impltag(
impldoc_from_impl(itemdoc, methods)
))
}
ast::item_ty(_, _, _) {
ast::item_ty(_, _) {
some(doc::tytag(
tydoc_from_ty(itemdoc)
))

View File

@ -291,7 +291,7 @@ fn all_impls(m: ast::_mod) -> map::set<ast::def_id> {
let all_impls = ast_util::new_def_hash();
for m.items.each |item| {
alt item.node {
ast::item_impl(_, _, _, _, _) {
ast::item_impl(_, _, _, _) {
all_impls.insert(ast_util::local_def(item.id), ());
}
_ { }

View File

@ -110,7 +110,7 @@ fn fold_enum(
let sig = do astsrv::exec(srv) |ctxt| {
alt check ctxt.ast_map.get(doc_id) {
ast_map::node_item(@{
node: ast::item_enum(ast_variants, _, _), _
node: ast::item_enum(ast_variants, _), _
}, _) {
let ast_variant = option::get(
do vec::find(ast_variants) |v| {
@ -168,7 +168,7 @@ fn get_method_sig(
do astsrv::exec(srv) |ctxt| {
alt check ctxt.ast_map.get(item_id) {
ast_map::node_item(@{
node: ast::item_trait(_, _, methods), _
node: ast::item_trait(_, methods), _
}, _) {
alt check vec::find(methods, |method| {
*method.ident == method_name
@ -183,7 +183,7 @@ fn get_method_sig(
}
}
ast_map::node_item(@{
node: ast::item_impl(_, _, _, _, methods), _
node: ast::item_impl(_, _, _, methods), _
}, _) {
alt check vec::find(methods, |method| {
*method.ident == method_name
@ -218,7 +218,7 @@ fn fold_impl(
let (trait_ty, self_ty) = do astsrv::exec(srv) |ctxt| {
alt ctxt.ast_map.get(doc.id()) {
ast_map::node_item(@{
node: ast::item_impl(_, _, trait_ty, self_ty, _), _
node: ast::item_impl(_, trait_ty, self_ty, _), _
}, _) {
let trait_ty = option::map(trait_ty, |p| {
pprust::path_to_str(p.path)
@ -274,7 +274,7 @@ fn fold_type(
alt ctxt.ast_map.get(doc.id()) {
ast_map::node_item(@{
ident: ident,
node: ast::item_ty(ty, params, ast::rp_none), _
node: ast::item_ty(ty, params), _
}, _) {
some(#fmt(
"type %s%s = %s",

View File

@ -1,3 +0,0 @@
type foo/& = {f: int}; //~ ERROR lifetime `self` unused
fn main() {}

View File

@ -2,9 +2,9 @@
// nominal types (but not on other types) and that they are type
// checked.
enum an_enum/& { }
iface an_iface/& { }
class a_class/& { let x:int; new(x:int) { self.x = x; } }
enum an_enum = &int;
iface an_iface { fn foo() -> &self.int; }
class a_class { let x:&self.int; new(x:&self.int) { self.x = x; } }
fn a_fn1(e: an_enum/&a) -> an_enum/&b {
ret e; //~ ERROR mismatched types: expected `an_enum/&b` but found `an_enum/&a`

View File

@ -1,4 +1,4 @@
enum ast/& {
enum ast {
num(uint),
add(&ast, &ast)
}

View File

@ -1,13 +1,13 @@
type ctxt = { v: uint };
iface get_ctxt/& {
iface get_ctxt {
// Here the `&` is bound in the method definition:
fn get_ctxt() -> &ctxt;
}
type has_ctxt/& = { c: &ctxt };
type has_ctxt = { c: &ctxt };
impl/& of get_ctxt for has_ctxt {
impl of get_ctxt for has_ctxt {
// Here an error occurs because we used `&self` but
// the definition used `&`:

View File

@ -1,12 +1,12 @@
type ctxt = { v: uint };
iface get_ctxt/& {
iface get_ctxt {
fn get_ctxt() -> &self.ctxt;
}
type has_ctxt/& = { c: &ctxt };
type has_ctxt = { c: &ctxt };
impl/& of get_ctxt for has_ctxt {
impl of get_ctxt for has_ctxt {
fn get_ctxt() -> &self.ctxt { self.c }
}

View File

@ -1,4 +1,4 @@
iface get_ctxt/& {
iface get_ctxt {
fn get_ctxt() -> &self.uint;
}

View File

@ -1,24 +1,12 @@
enum no0 {
x0(&uint) //~ ERROR to use region types here, the containing type must be declared with a region bound
}
enum no1 {
x1(&self.uint) //~ ERROR to use region types here, the containing type must be declared with a region bound
}
enum no2 {
x2(&foo.uint) //~ ERROR named regions other than `self` are not allowed as part of a type declaration
}
enum yes0/& {
enum yes0 {
x3(&uint)
}
enum yes1/& {
enum yes1 {
x4(&self.uint)
}
enum yes2/& {
enum yes2 {
x5(&foo.uint) //~ ERROR named regions other than `self` are not allowed as part of a type declaration
}

View File

@ -1,34 +1,16 @@
class no0 {
let x: &uint; //~ ERROR to use region types here, the containing type must be declared with a region bound
new(x: &uint) { self.x = x; } //~ ERROR to use region types here, the containing type must be declared with a region bound
drop {}
}
class no1 {
let x: &self.uint; //~ ERROR to use region types here, the containing type must be declared with a region bound
new(x: &self.uint) { self.x = x; } //~ ERROR to use region types here, the containing type must be declared with a region bound
drop {}
}
class no2 {
let x: &foo.uint; //~ ERROR named regions other than `self` are not allowed as part of a type declaration
new(x: &foo.uint) { self.x = x; } //~ ERROR named regions other than `self` are not allowed as part of a type declaration
drop {}
}
class yes0/& {
class yes0 {
let x: &uint;
new(x: &uint) { self.x = x; }
drop {}
}
class yes1/& {
class yes1 {
let x: &self.uint;
new(x: &self.uint) { self.x = x; }
drop {}
}
class yes2/& {
class yes2 {
let x: &foo.uint; //~ ERROR named regions other than `self` are not allowed as part of a type declaration
new(x: &foo.uint) { self.x = x; } //~ ERROR named regions other than `self` are not allowed as part of a type declaration
drop {}

View File

@ -1,24 +1,12 @@
type item_ty_no0 = {
x: &uint //~ ERROR to use region types here, the containing type must be declared with a region bound
};
type item_ty_no1 = {
x: &self.uint //~ ERROR to use region types here, the containing type must be declared with a region bound
};
type item_ty_no2 = {
x: &foo.uint //~ ERROR named regions other than `self` are not allowed as part of a type declaration
};
type item_ty_yes0/& = {
type item_ty_yes0 = {
x: &uint
};
type item_ty_yes1/& = {
type item_ty_yes1 = {
x: &self.uint
};
type item_ty_yes2/& = { //~ ERROR lifetime `self` unused inside reference-parameterized type
type item_ty_yes2 = {
x: &foo.uint //~ ERROR named regions other than `self` are not allowed as part of a type declaration
};

View File

@ -0,0 +1,18 @@
// Check that we correctly infer that b and c must be region
// parameterized because they reference a which requires a region.
type a = &int;
type b = @a;
type c = {f: @b};
impl methods for c {
fn set_f_ok(b: @b/&self) {
self.f = b;
}
fn set_f_bad(b: @b) {
self.f = b; //~ ERROR mismatched types: expected `@@&self.int` but found `@@&int`
}
}
fn main() {}

View File

@ -0,0 +1,32 @@
// Here: foo is parameterized because it contains a method that
// refers to self.
iface foo {
fn self_int() -> &self.int;
fn any_int() -> &int;
}
type with_foo = {mut f: foo};
impl methods for with_foo {
fn set_foo(f: foo) {
self.f = f; //~ ERROR mismatched types: expected `foo/&self` but found `foo/&`
}
}
// Bar is not region parameterized.
iface bar {
fn any_int() -> &int;
}
type with_bar = {mut f: bar};
impl methods for with_bar {
fn set_foo(f: bar) {
self.f = f;
}
}
fn main() {}

View File

@ -6,7 +6,7 @@ iface iterable<A> {
fn iterate(blk: fn(A) -> bool);
}
impl vec/&<A> of iterable<A> for &[const A] {
impl vec<A> of iterable<A> for &[const A] {
fn iterate(f: fn(A) -> bool) {
vec::each(self, f);
}

View File

@ -1,4 +1,4 @@
class font/& {
class font {
let fontbuf: &self.~[u8];
new(fontbuf: &self.~[u8]) {

View File

@ -1,7 +1,7 @@
class CMap/& {
let buf: [u8]/&;
class CMap {
let buf: &[u8];
new(buf: [u8]/&) {
new(buf: &self.[u8]) {
self.buf = buf;
}
}

View File

@ -1,5 +1,5 @@
// Note: impl on a slice
impl foo/& for &int {
impl foo for &int {
fn get() -> int {
ret *self;
}

View File

@ -1,5 +1,5 @@
// Note: impl on a slice
impl foo/& for &[int] {
impl foo for &[int] {
fn sum() -> int {
let mut sum = 0;
for vec::each(self) |e| { sum += e; }

View File

@ -1,4 +1,4 @@
enum ast/& {
enum ast {
num(uint),
add(&ast, &ast)
}

View File

@ -1,4 +1,4 @@
enum ast/& {
enum ast {
num(uint),
add(&ast, &ast)
}

View File

@ -1,12 +1,12 @@
type ctxt = { v: uint };
iface get_ctxt/& {
iface get_ctxt {
fn get_ctxt() -> &self.ctxt;
}
type has_ctxt/& = { c: &ctxt };
type has_ctxt = { c: &ctxt };
impl/& of get_ctxt for has_ctxt {
impl of get_ctxt for has_ctxt {
fn get_ctxt() -> &self.ctxt {
self.c
}

View File

@ -2,11 +2,11 @@ import libc, sys, unsafe;
enum arena = ();
type bcx/& = {
type bcx = {
fcx: &fcx
};
type fcx/& = {
type fcx = {
arena: &arena,
ccx: &ccx
};

View File

@ -2,11 +2,11 @@ import libc, sys, unsafe;
enum arena = ();
type bcx/& = {
type bcx = {
fcx: &fcx
};
type fcx/& = {
type fcx = {
arena: &arena,
ccx: &ccx
};

View File

@ -1,4 +1,4 @@
enum roption/& {
enum roption {
a, b(&uint)
}

View File

@ -1,6 +1,6 @@
type clam/& = { chowder: &int };
type clam = { chowder: &int };
impl clam/& for clam {
impl clam for clam {
fn get_chowder() -> &self.int { ret self.chowder; }
}

View File

@ -1,4 +1,4 @@
enum int_wrapper/& {
enum int_wrapper {
int_wrapper_ctor(&int)
}