1
Fork 0

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_, id: node_id, node: item_,
vis: visibility, span: span}; vis: visibility, span: span};
#[auto_serialize]
enum region_param {
rp_none,
rp_self
}
#[auto_serialize] #[auto_serialize]
enum item_ { enum item_ {
item_const(@ty, @expr), item_const(@ty, @expr),
item_fn(fn_decl, ~[ty_param], blk), item_fn(fn_decl, ~[ty_param], blk),
item_mod(_mod), item_mod(_mod),
item_foreign_mod(foreign_mod), item_foreign_mod(foreign_mod),
item_ty(@ty, ~[ty_param], region_param), item_ty(@ty, ~[ty_param]),
item_enum(~[variant], ~[ty_param], region_param), item_enum(~[variant], ~[ty_param]),
item_class(~[ty_param], /* ty params for class */ item_class(~[ty_param], /* ty params for class */
~[@trait_ref], /* traits this class implements */ ~[@trait_ref], /* traits this class implements */
~[@class_member], /* methods, etc. */ ~[@class_member], /* methods, etc. */
/* (not including ctor or dtor) */ /* (not including ctor or dtor) */
class_ctor, class_ctor,
/* dtor is optional */ /* dtor is optional */
option<class_dtor>, option<class_dtor>
region_param
), ),
item_trait(~[ty_param], region_param, ~[ty_method]), item_trait(~[ty_param], ~[ty_method]),
item_impl(~[ty_param], region_param, option<@trait_ref> /* trait */, item_impl(~[ty_param], option<@trait_ref> /* trait */,
@ty /* self */, ~[@method]), @ty /* self */, ~[@method]),
item_mac(mac), 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; let item_path = @/* FIXME (#2543) */ copy cx.path;
cx.map.insert(i.id, node_item(i, item_path)); cx.map.insert(i.id, node_item(i, item_path));
alt i.node { alt i.node {
item_impl(_, _, _, _, ms) { item_impl(_, _, _, ms) {
let impl_did = ast_util::local_def(i.id); let impl_did = ast_util::local_def(i.id);
for ms.each |m| { for ms.each |m| {
map_method(impl_did, extend(cx, i.ident), m, map_method(impl_did, extend(cx, i.ident), m,
cx); cx);
} }
} }
item_enum(vs, _, _) { item_enum(vs, _) {
for vs.each |v| { for vs.each |v| {
cx.map.insert(v.node.id, node_variant( cx.map.insert(v.node.id, node_variant(
/* FIXME (#2543) */ copy v, i, /* FIXME (#2543) */ copy v, i,
@ -214,7 +214,7 @@ fn map_item(i: @item, cx: ctx, v: vt) {
extend(cx, i.ident))); 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); let (_, ms) = ast_util::split_class_items(items);
// Map trait refs to their parent classes. This is // Map trait refs to their parent classes. This is
// so we can find the self_ty // 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| { for m.items.each |it| {
if it.ident == i { local = true; } if it.ident == i { local = true; }
alt it.node { alt it.node {
item_enum(variants, _, _) { item_enum(variants, _) {
for variants.each |v| { for variants.each |v| {
if v.node.name == i { if v.node.name == i {
local = true; local = true;
@ -428,7 +428,7 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
visit_item: fn@(i: @item) { visit_item: fn@(i: @item) {
vfn(i.id); vfn(i.id);
alt i.node { 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) { visit_class_item: fn@(c: @class_member) {
alt c.node { alt c.node {
instance_var(_, _, _, id,_) { instance_var(_, _, _, id,_) {

View file

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

View file

@ -128,8 +128,7 @@ impl ast_builder for ext_ctxt {
+ty_params: ~[ast::ty_param]) -> @ast::item { +ty_params: ~[ast::ty_param]) -> @ast::item {
self.item(name, self.item(name,
ast::item_enum(variants, ast::item_enum(variants,
ty_params, ty_params))
ast::rp_none))
} }
fn item_enum(name: ident, fn item_enum(name: ident,
@ -167,12 +166,10 @@ impl ast_builder for ext_ctxt {
fn item_ty_poly(name: ident, fn item_ty_poly(name: ident,
ty: @ast::ty, ty: @ast::ty,
+params: ~[ast::ty_param]) -> @ast::item { +params: ~[ast::ty_param]) -> @ast::item {
self.item(name, self.item(name, ast::item_ty(ty, params))
ast::item_ty(ty, params, ast::rp_none))
} }
fn item_ty(name: ident, fn item_ty(name: ident, ty: @ast::ty) -> @ast::item {
ty: @ast::ty) -> @ast::item {
self.item_ty_poly(name, ty, ~[]) 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_mod(m) { item_mod(fld.fold_mod(m)) }
item_foreign_mod(nm) { item_foreign_mod(fld.fold_foreign_mod(nm)) } item_foreign_mod(nm) { item_foreign_mod(fld.fold_foreign_mod(nm)) }
item_ty(t, typms, rp) { item_ty(fld.fold_ty(t), item_ty(t, typms) { item_ty(fld.fold_ty(t),
fold_ty_params(typms, fld), fold_ty_params(typms, fld)) }
rp) } item_enum(variants, typms) {
item_enum(variants, typms, r) {
item_enum(vec::map(variants, |x| fld.fold_variant(x)), item_enum(vec::map(variants, |x| fld.fold_variant(x)),
fold_ty_params(typms, fld), fold_ty_params(typms, fld))
r)
} }
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_body = fld.fold_block(ctor.node.body);
let ctor_decl = fold_fn_decl(ctor.node.dec, fld); let ctor_decl = fold_fn_decl(ctor.node.dec, fld);
let ctor_id = fld.new_id(ctor.node.id); 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, {node: {body: ctor_body,
dec: ctor_decl, dec: ctor_decl,
id: ctor_id with ctor.node} 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), item_impl(fold_ty_params(tps, fld),
rp,
ifce.map(|p| fold_trait_ref(p, fld)), ifce.map(|p| fold_trait_ref(p, fld)),
fld.fold_ty(ty), fld.fold_ty(ty),
vec::map(methods, |x| fld.fold_method(x))) vec::map(methods, |x| fld.fold_method(x)))
} }
item_trait(tps, rp, methods) { item_trait(tps, methods) {
item_trait(fold_ty_params(tps, fld), item_trait(fold_ty_params(tps, fld),
rp,
/* FIXME (#2543) */ copy methods) /* FIXME (#2543) */ copy methods)
} }
item_mac(m) { 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_box, pat_enum, pat_ident, pat_lit, pat_range, pat_rec,
pat_tup, pat_uniq, pat_wild, path, private, proto, proto_any, pat_tup, pat_uniq, pat_wild, path, private, proto, proto_any,
proto_bare, proto_block, proto_box, proto_uniq, public, pure_fn, proto_bare, proto_block, proto_box, proto_uniq, public, pure_fn,
purity, re_anon, re_named, region, region_param, rem, ret_style, purity, re_anon, re_named, region, rem, ret_style,
return_val, rp_none, rp_self, shl, shr, stmt, stmt_decl, return_val, shl, shr, stmt, stmt_decl,
stmt_expr, stmt_semi, subtract, token_tree, trait_ref, tt_delim, stmt_expr, stmt_semi, subtract, token_tree, trait_ref, tt_delim,
tt_dotdotdot, tt_flat, tt_interpolate, ty, ty_, ty_bot, ty_box, 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, 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 { fn parse_item_trait() -> item_info {
let ident = self.parse_ident(); let ident = self.parse_ident();
let rp = self.parse_region_param(); self.parse_region_param();
let tps = self.parse_ty_params(); let tps = self.parse_ty_params();
let meths = self.parse_ty_methods(); 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): // Parses three variants (with the region/type params always optional):
@ -2147,18 +2147,19 @@ class parser {
fn wrap_path(p: parser, pt: @path) -> @ty { fn wrap_path(p: parser, pt: @path) -> @ty {
@{id: p.get_id(), node: ty_path(pt, p.get_id()), span: pt.span} @{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 { 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) { } 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") { else if self.is_keyword("of") {
(none, rp_none, ~[]) (none, ~[])
} else { } else {
let id = self.parse_ident(); let id = self.parse_ident();
let rp = self.parse_region_param(); self.parse_region_param();
(some(id), rp, self.parse_ty_params()) (some(id), self.parse_ty_params())
} }
}; };
let ifce = if self.eat_keyword("of") { let ifce = if self.eat_keyword("of") {
@ -2179,25 +2180,18 @@ class parser {
while !self.eat(token::RBRACE) { while !self.eat(token::RBRACE) {
vec::push(meths, self.parse_method(public)); 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. // Instantiates ident <i> with references to <typarams> as arguments.
// Used to create a path that refers to a class which will be defined as // Used to create a path that refers to a class which will be defined as
// the return type of the ctor function. // the return type of the ctor function.
fn ident_to_path_tys(i: ident, fn ident_to_path_tys(i: ident,
rp: region_param,
typarams: ~[ty_param]) -> @path { typarams: ~[ty_param]) -> @path {
let s = self.last_span; 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], @{span: s, global: false, idents: ~[i],
rp: a_r, rp: none,
types: vec::map(typarams, |tp| { types: vec::map(typarams, |tp| {
@{id: self.get_id(), @{id: self.get_id(),
node: ty_path(ident_to_path(s, tp.ident), 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 { fn parse_item_class() -> item_info {
let class_name = self.parse_value_ident(); 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 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) let traits : ~[@trait_ref] = if self.eat(token::COLON)
{ self.parse_trait_ref_list() } { self.parse_trait_ref_list() }
else { ~[] }; else { ~[] };
@ -2255,7 +2249,7 @@ class parser {
self_id: self.get_id(), self_id: self.get_id(),
dec: ct_d, dec: ct_d,
body: ct_b}, body: ct_b},
span: ct_s}, actual_dtor, rp), span: ct_s}, actual_dtor),
none) none)
} }
/* /*
@ -2447,26 +2441,23 @@ class parser {
fn parse_item_type() -> item_info { fn parse_item_type() -> item_info {
let t = self.parse_type_decl(); let t = self.parse_type_decl();
let rp = self.parse_region_param(); self.parse_region_param();
let tps = self.parse_ty_params(); let tps = self.parse_ty_params();
self.expect(token::EQ); self.expect(token::EQ);
let ty = self.parse_ty(false); let ty = self.parse_ty(false);
self.expect(token::SEMI); 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)) { if self.eat(token::BINOP(token::SLASH)) {
self.expect(token::BINOP(token::AND)); self.expect(token::BINOP(token::AND));
rp_self
} else {
rp_none
} }
} }
fn parse_item_enum(default_vis: visibility) -> item_info { fn parse_item_enum(default_vis: visibility) -> item_info {
let id = self.parse_ident(); let id = self.parse_ident();
let rp = self.parse_region_param(); self.parse_region_param();
let ty_params = self.parse_ty_params(); let ty_params = self.parse_ty_params();
let mut variants: ~[variant] = ~[]; let mut variants: ~[variant] = ~[];
// Newtype syntax // Newtype syntax
@ -2483,7 +2474,7 @@ class parser {
id: self.get_id(), id: self.get_id(),
disr_expr: none, disr_expr: none,
vis: public}); vis: public});
ret (id, item_enum(~[variant], ty_params, rp), none); ret (id, item_enum(~[variant], ty_params), none);
} }
self.expect(token::LBRACE); self.expect(token::LBRACE);
@ -2521,7 +2512,7 @@ class parser {
self.fatal("discriminator values can only be used with a c-like \ self.fatal("discriminator values can only be used with a c-like \
enum"); enum");
} }
(id, item_enum(variants, ty_params, rp), none) (id, item_enum(variants, ty_params), none)
} }
fn parse_fn_ty_proto() -> proto { 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); print_foreign_mod(s, nmod, item.attrs);
bclose(s, item.span); bclose(s, item.span);
} }
ast::item_ty(ty, params, rp) { ast::item_ty(ty, params) {
ibox(s, indent_unit); ibox(s, indent_unit);
ibox(s, 0u); ibox(s, 0u);
word_nbsp(s, "type"); word_nbsp(s, "type");
word(s.s, *item.ident); word(s.s, *item.ident);
print_region_param(s, rp);
print_type_params(s, params); print_type_params(s, params);
end(s); // end the inner ibox end(s); // end the inner ibox
@ -473,7 +472,7 @@ fn print_item(s: ps, &&item: @ast::item) {
word(s.s, ";"); word(s.s, ";");
end(s); // end the outer ibox end(s); // end the outer ibox
} }
ast::item_enum(variants, params, rp) { ast::item_enum(variants, params) {
let newtype = let newtype =
vec::len(variants) == 1u && vec::len(variants) == 1u &&
str::eq(*item.ident, *variants[0].node.name) && str::eq(*item.ident, *variants[0].node.name) &&
@ -483,7 +482,6 @@ fn print_item(s: ps, &&item: @ast::item) {
word_space(s, "enum"); word_space(s, "enum");
} else { head(s, "enum"); } } else { head(s, "enum"); }
word(s.s, *item.ident); word(s.s, *item.ident);
print_region_param(s, rp);
print_type_params(s, params); print_type_params(s, params);
space(s.s); space(s.s);
if newtype { if newtype {
@ -506,10 +504,9 @@ fn print_item(s: ps, &&item: @ast::item) {
bclose(s, item.span); 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"); head(s, "class");
word_nbsp(s, *item.ident); word_nbsp(s, *item.ident);
print_region_param(s, rp);
print_type_params(s, tps); print_type_params(s, tps);
if vec::len(traits) != 0u { if vec::len(traits) != 0u {
word_space(s, ":"); word_space(s, ":");
@ -571,10 +568,9 @@ fn print_item(s: ps, &&item: @ast::item) {
} }
bclose(s, item.span); bclose(s, item.span);
} }
ast::item_impl(tps, rp, ifce, ty, methods) { ast::item_impl(tps, ifce, ty, methods) {
head(s, "impl"); head(s, "impl");
word(s.s, *item.ident); word(s.s, *item.ident);
print_region_param(s, rp);
print_type_params(s, tps); print_type_params(s, tps);
space(s.s); space(s.s);
option::iter(ifce, |p| { option::iter(ifce, |p| {
@ -591,10 +587,9 @@ fn print_item(s: ps, &&item: @ast::item) {
} }
bclose(s, item.span); bclose(s, item.span);
} }
ast::item_trait(tps, rp, methods) { ast::item_trait(tps, methods) {
head(s, "iface"); head(s, "iface");
word(s.s, *item.ident); word(s.s, *item.ident);
print_region_param(s, rp);
print_type_params(s, tps); print_type_params(s, tps);
word(s.s, " "); word(s.s, " ");
bopen(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]) { fn print_type_params(s: ps, &&params: ~[ast::ty_param]) {
if vec::len(params) > 0u { if vec::len(params) > 0u {
word(s.s, "<"); word(s.s, "<");

View file

@ -61,6 +61,7 @@ type visitor<E> =
visit_ty_params: fn@(~[ty_param], E, vt<E>), visit_ty_params: fn@(~[ty_param], E, vt<E>),
visit_constr: fn@(@path, span, node_id, 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_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>)}; visit_class_item: fn@(@class_member, E, vt<E>)};
fn default_visitor<E>() -> visitor<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_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_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_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)}; 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.view_items.each |vi| { v.visit_view_item(vi, e, v); }
for nm.items.each |ni| { v.visit_foreign_item(ni, 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(t, e, v);
v.visit_ty_params(tps, e, v); v.visit_ty_params(tps, e, v);
} }
item_enum(variants, tps, _) { item_enum(variants, tps) {
v.visit_ty_params(tps, e, v); v.visit_ty_params(tps, e, v);
for variants.each |vr| { for variants.each |vr| {
for vr.node.args.each |va| { v.visit_ty(va.ty, e, v); } 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); v.visit_ty_params(tps, e, v);
option::iter(ifce, |p| visit_path(p.path, e, v)); option::iter(ifce, |p| visit_path(p.path, e, v));
v.visit_ty(ty, 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) 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); v.visit_ty_params(tps, e, v);
for members.each |m| { for members.each |m| {
v.visit_class_item(m, e, v); 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, visit_class_dtor_helper(dtor, tps,
ast_util::local_def(i.id), e, v)}; ast_util::local_def(i.id), e, v)};
} }
item_trait(tps, _rp, methods) { item_trait(tps, methods) {
v.visit_ty_params(tps, e, v); v.visit_ty_params(tps, e, v);
for methods.each |m| { for methods.each |m| {
for m.decl.inputs.each |a| { v.visit_ty(a.ty, e, v); } v.visit_ty_method(m, e, v);
v.visit_ty_params(m.tps, e, v);
v.visit_ty(m.decl.output, e, v);
} }
} }
item_mac(m) { visit_mac(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); 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>) { 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.view_items.each |vi| { v.visit_view_item(vi, e, v); }
for b.node.stmts.each |s| { v.visit_stmt(s, 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_ty_params: fn@(~[ty_param]),
visit_constr: fn@(@path, span, node_id), visit_constr: fn@(@path, span, node_id),
visit_fn: fn@(fn_kind, fn_decl, blk, 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)}; visit_class_item: fn@(@class_member)};
fn simple_ignore_ty(_t: @ty) {} 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_constr: fn@(_p: @path, _sp: span, _id: node_id) { },
visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span, visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
_id: node_id) { }, _id: node_id) { },
visit_ty_method: fn@(_m: ty_method) { },
visit_class_item: fn@(_c: @class_member) {} visit_class_item: fn@(_c: @class_member) {}
}; };
} }
@ -534,6 +542,10 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
f(ty); f(ty);
visit_ty(ty, e, v); 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]), fn v_ty_params(f: fn@(~[ty_param]),
ps: ~[ty_param], ps: ~[ty_param],
&&e: (), v: vt<()>) { &&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), v_constr(v.visit_constr, a, b, c, d, e),
visit_fn: |a,b,c,d,e,f,g| visit_fn: |a,b,c,d,e,f,g|
v_fn(v.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| visit_class_item: |a,b,c|
v_class_item(v.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", || let region_map = time(time_passes, "region resolution", ||
middle::region::resolve_crate(sess, def_map, crate)); 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", || let (method_map, vtable_map) = time(time_passes, "typechecking", ||
typeck::check_crate(ty_cx, typeck::check_crate(ty_cx,

View file

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

View file

@ -17,6 +17,7 @@ export get_class_fields;
export get_class_method; export get_class_method;
export get_field_type; export get_field_type;
export get_type_param_count; export get_type_param_count;
export get_region_param;
export lookup_defs; export lookup_defs;
export lookup_method_purity; export lookup_method_purity;
export get_enum_variants; 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) 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, fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
def: ast::def_id) -> ty::ty_param_bounds_and_ty { def: ast::def_id) -> ty::ty_param_bounds_and_ty {
let cstore = tcx.cstore; let cstore = tcx.cstore;
@ -168,7 +175,7 @@ fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
class_id, def) ); class_id, def) );
#debug("got field data %?", the_field); #debug("got field data %?", the_field);
let ty = decoder::item_type(def, the_field, tcx, cdata); 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, // 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_symbol;
export get_enum_variants; export get_enum_variants;
export get_type; export get_type;
export get_region_param;
export get_type_param_count; export get_type_param_count;
export get_impl_trait; export get_impl_trait;
export get_class_method; export get_class_method;
@ -185,15 +186,10 @@ fn item_ty_param_bounds(item: ebml::doc, tcx: ty::ctxt, cdata: cmd)
@bounds @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) { alt ebml::maybe_get_doc(item, tag_region_param) {
some(rp_doc) { some(_) { true }
let dsr = ebml::ebml_deserializer(rp_doc); none { false }
ast::deserialize_region_param(dsr)
}
none { // not all families of items have region params
ast::rp_none
}
} }
} }
@ -325,6 +321,11 @@ fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
ret {bounds: tp_bounds, rp: rp, ty: t}; 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 { fn get_type_param_count(data: @~[u8], id: ast::node_id) -> uint {
item_ty_param_count(lookup_item(id, data)) 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)); encode_def_id(ebml_w, local_def(id));
} }
fn encode_region_param(ebml_w: ebml::writer, rp: region_param) { fn encode_region_param(ecx: @encode_ctxt, ebml_w: ebml::writer,
do ebml_w.wr_tag(tag_region_param) { it: @ast::item) {
serialize_region_param(ebml_w, rp) 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) { 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); vec::append_one(path, it.ident), index);
} }
} }
item_ty(_, tps, _) { item_ty(_, tps) {
do ebml_w.wr_tag(tag_paths_data_item) { do ebml_w.wr_tag(tag_paths_data_item) {
encode_name_and_def_id(ebml_w, it.ident, it.id); 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) { do ebml_w.wr_tag(tag_paths_data_item) {
encode_name_and_def_id(ebml_w, it.ident, it.id); 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); index);
} }
} }
item_enum(variants, _, _) { item_enum(variants, _) {
do ebml_w.wr_tag(tag_paths_data_item) { do ebml_w.wr_tag(tag_paths_data_item) {
encode_name_and_def_id(ebml_w, it.ident, it.id); 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 */ ref, we need to map it to its parent class */
ebml_w.wr_str(def_to_str(local_def(it.id))); 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),_,_),_},_)) { some(ifce),_,_),_},_)) {
ebml_w.wr_str(def_to_str(did)); 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 tcx = ecx.tcx;
let must_write = 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; } if !must_write && !reachable(ecx, item.id) { ret; }
fn add_to_index_(item: @item, ebml_w: ebml::writer, 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)); encode_path(ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag(); ebml_w.end_tag();
} }
item_ty(_, tps, rp) { item_ty(_, tps) {
add_to_index(); add_to_index();
ebml_w.start_tag(tag_items_data_item); ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id)); 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_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident); encode_name(ebml_w, item.ident);
encode_path(ebml_w, path, ast_map::path_name(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(); ebml_w.end_tag();
} }
item_enum(variants, tps, rp) { item_enum(variants, tps) {
add_to_index(); add_to_index();
do ebml_w.wr_tag(tag_items_data_item) { do ebml_w.wr_tag(tag_items_data_item) {
encode_def_id(ebml_w, local_def(item.id)); 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)); ecx.encode_inlined_item(ecx, ebml_w, path, ii_item(item));
encode_path(ebml_w, path, ast_map::path_name(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);
} }
encode_enum_variant_info(ecx, ebml_w, item.id, variants, encode_enum_variant_info(ecx, ebml_w, item.id, variants,
path, index, tps); 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 /* First, encode the fields and methods
These come first because we need to write them to make These come first because we need to write them to make
the index, and the index needs to be in the item for the 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_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident); encode_name(ebml_w, item.ident);
encode_path(ebml_w, path, ast_map::path_name(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| { for traits.each |t| {
encode_trait_ref(ebml_w, ecx, 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); encode_index(ebml_w, bkts, write_int);
ebml_w.end_tag(); ebml_w.end_tag();
} }
item_impl(tps, rp, ifce, _, methods) { item_impl(tps, ifce, _, methods) {
add_to_index(); add_to_index();
ebml_w.start_tag(tag_items_data_item); ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id)); encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'i'); 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_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident); 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)); vec::append(tps, m.tps));
} }
} }
item_trait(tps, rp, ms) { item_trait(tps, ms) {
add_to_index(); add_to_index();
ebml_w.start_tag(tag_items_data_item); ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id)); encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'I'); 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_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident); 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_info_for_item(ecx, ebml_w, i, index, *pt);
/* encode ctor, then encode items */ /* encode ctor, then encode items */
alt i.node { alt i.node {
item_class(tps, _, _, ctor, m_dtor, _) { item_class(tps, _, _, ctor, m_dtor) {
#debug("encoding info for ctor %s %d", *i.ident, #debug("encoding info for ctor %s %d", *i.ident,
ctor.node.id); ctor.node.id);
vec::push(*index, vec::push(*index,

View file

@ -554,11 +554,11 @@ impl helpers for ebml::writer {
do self.emit_rec { do self.emit_rec {
do self.emit_rec_field("bounds", 0u) { do self.emit_rec_field("bounds", 0u) {
do self.emit_from_vec(*tpbt.bounds) |bs| { 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) { 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) { do self.emit_rec_field("ty", 2u) {
self.emit_ty(ecx, tpbt.ty); self.emit_ty(ecx, tpbt.ty);
@ -759,7 +759,7 @@ impl decoder for ebml::ebml_deserializer {
@self.read_to_vec(|| self.read_bounds(xcx) ) @self.read_to_vec(|| self.read_bounds(xcx) )
}), }),
rp: self.read_rec_field("rp", 1u, || { rp: self.read_rec_field("rp", 1u, || {
ast::deserialize_region_param(self) self.read_bool()
}), }),
ty: self.read_rec_field("ty", 2u, || { ty: self.read_rec_field("ty", 2u, || {
self.read_ty(xcx) 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 { if req_mutbl == m_imm && cmt.mutbl != m_imm {
self.bccx.loaned_paths_imm += 1; self.bccx.loaned_paths_imm += 1;
if self.tcx().sess.borrowck_note_loan() {
self.bccx.span_note(
cmt.span,
#fmt["immutable loan required"]);
}
} else { } else {
self.bccx.loaned_paths_same += 1; 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); v.visit_expr(ex, true, v);
check_item_recursion(sess, ast_map, def_map, it); check_item_recursion(sess, ast_map, def_map, it);
} }
item_enum(vs, _, _) { item_enum(vs, _) {
for vs.each |var| { for vs.each |var| {
do option::iter(var.node.disr_expr) |ex| { do option::iter(var.node.disr_expr) |ex| {
v.visit_expr(ex, true, v); v.visit_expr(ex, true, v);

View file

@ -138,11 +138,13 @@ import syntax::{ast, visit};
import syntax::codemap::span; import syntax::codemap::span;
import syntax::print::pprust; import syntax::print::pprust;
import syntax::ast_util::new_def_hash; import syntax::ast_util::new_def_hash;
import syntax::ast_map;
import dvec::{dvec, extensions};
import metadata::csearch;
import std::list; import std::list;
import std::list::list; import std::list::list;
import std::map; import std::map::{hashmap, int_hash};
import std::map::hashmap;
type parent = option<ast::node_id>; 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 { -> region_map {
let cx: ctxt = {sess: sess, let cx: ctxt = {sess: sess,
def_map: def_map, def_map: def_map,
region_map: map::int_hash(), region_map: int_hash(),
parent: none}; parent: none};
let visitor = visit::mk_vt(@{ let visitor = visit::mk_vt(@{
visit_block: resolve_block, 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; 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 /* At this point, the code knows what traits the trait refs
refer to, so it's possible to resolve them. 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)) ifce.iter(|p| resolve_trait_ref(p, sc, e))
} }
ast::item_class(_, traits, _, _, _, _) { ast::item_class(_, traits, _, _, _) {
for traits.each |p| { for traits.each |p| {
resolve_trait_ref(p, sc, e); 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); let sc = @cons(scope_item(i), sc);
alt i.node { alt i.node {
ast::item_impl(tps, _, ifce, sty, methods) { ast::item_impl(tps, ifce, sty, methods) {
v.visit_ty_params(tps, sc, v); v.visit_ty_params(tps, sc, v);
option::iter(ifce, |p| visit::visit_path(p.path, sc, v)); option::iter(ifce, |p| visit::visit_path(p.path, sc, v));
v.visit_ty(sty, 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); 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); v.visit_ty_params(tps, sc, v);
let isc = @cons(scope_method(i.id, tps), sc); let isc = @cons(scope_method(i.id, tps), sc);
for methods.each |m| { 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); 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); v.visit_ty_params(tps, sc, v);
let class_scope = @cons(scope_item(i), sc); let class_scope = @cons(scope_item(i), sc);
/* visit the constructor... */ /* visit the constructor... */
@ -1042,13 +1042,13 @@ fn lookup_in_scope(e: env, &&sc: scopes, sp: span, name: ident, ns: namespace,
} }
scope_item(it) { scope_item(it) {
alt it.node { alt it.node {
ast::item_impl(tps, _, _, _, _) { ast::item_impl(tps, _, _, _) {
if ns == ns_type { ret lookup_in_ty_params(e, name, 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); } 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 ns == ns_type {
if *name == "self" { if *name == "self" {
ret some(def_self(it.id)); 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) { ast::item_foreign_mod(m) {
ret lookup_in_local_foreign_mod(e, it.id, sp, name, ns); 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 { if ns == ns_type {
ret lookup_in_ty_params(e, name, tps); 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) { ast::decl_item(it) {
alt it.node { alt it.node {
ast::item_enum(variants, _, _) { ast::item_enum(variants, _) {
if ns == ns_type { if ns == ns_type {
if str::eq(*it.ident, *name) { if str::eq(*it.ident, *name) {
ret some(ast::def_ty(local_def(it.id))); 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(*) { ast::item_ty(*) | item_trait(*) | item_enum(*) {
if ns == ns_type { ret some(ast::def_ty(local_def(i.id))); } 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 { alt ns {
ns_type { ns_type {
ret some(ast::def_class(local_def(i.id))); 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| { for md.items.each |it| {
alt it.node { alt it.node {
ast::item_const(_, _) | ast::item_fn(_, _, _) | ast::item_mod(_) | 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(*) { ast::item_impl(*) | ast::item_trait(*) {
add_to_index(index, it.ident, mie_item(it)); 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)); add_to_index(index, it.ident, mie_item(it));
let mut variant_idx: uint = 0u; let mut variant_idx: uint = 0u;
for variants.each |v| { for variants.each |v| {
@ -1655,7 +1655,7 @@ fn index_mod(md: ast::_mod) -> mod_index {
variant_idx += 1u; variant_idx += 1u;
} }
} }
ast::item_class(tps, _, items, ctor, _, _) { ast::item_class(tps, _, items, ctor, _) {
// add the class name itself // add the class name itself
add_to_index(index, it.ident, mie_item(it)); 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, ensure_unique(*e, i.span, ty_params, |tp| tp.ident,
"type parameter"); "type parameter");
} }
ast::item_enum(_, ty_params, _) { ast::item_enum(_, ty_params) {
ensure_unique(*e, i.span, ty_params, |tp| tp.ident, ensure_unique(*e, i.span, ty_params, |tp| tp.ident,
"type parameter"); "type parameter");
} }
ast::item_trait(_, _, methods) { ast::item_trait(_, methods) {
ensure_unique(*e, i.span, methods, |m| m.ident, ensure_unique(*e, i.span, methods, |m| m.ident,
"method"); "method");
} }
ast::item_impl(_, _, _, _, methods) { ast::item_impl(_, _, _, methods) {
ensure_unique(*e, i.span, methods, |m| m.ident, ensure_unique(*e, i.span, methods, |m| m.ident,
"method"); "method");
} }
@ -1854,7 +1854,7 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
} }
ast::decl_item(it) { ast::decl_item(it) {
alt it.node { alt it.node {
ast::item_enum(variants, _, _) { ast::item_enum(variants, _) {
add_name(types, it.span, it.ident); add_name(types, it.span, it.ident);
for variants.each |v| { for variants.each |v| {
add_name(values, v.span, v.node.name); add_name(values, v.span, v.node.name);
@ -2051,7 +2051,7 @@ fn check_exports(e: @env) {
some(ms) { some(ms) {
let maybe_id = do list_search(ms) |m| { let maybe_id = do list_search(ms) |m| {
alt m { alt m {
mie_item(@{node: item_enum(_, _, _), id, _}) { some(id) } mie_item(@{node: item_enum(_, _), id, _}) { some(id) }
_ { none } _ { none }
} }
}; };
@ -2242,7 +2242,7 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: ~[@_impl],
name: option<ident>, name: option<ident>,
ck_exports: option<@indexed_mod>) { ck_exports: option<@indexed_mod>) {
alt i.node { alt i.node {
ast::item_impl(_, _, ifce, _, mthds) { ast::item_impl(_, ifce, _, mthds) {
if alt name { some(n) { n == i.ident } _ { true } } && if alt name { some(n) { n == i.ident } _ { true } } &&
alt ck_exports { alt ck_exports {
some(m) { is_exported(e, i.ident, m) } 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 (_, mthds) = ast_util::split_class_items(items);
let n_tps = tps.len(); let n_tps = tps.len();
do vec::iter(ifces) |p| { do vec::iter(ifces) |p| {

View file

@ -847,7 +847,7 @@ class Resolver {
} }
// These items live in both the type and value namespaces. // 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))); (*name_bindings).define_type(def_ty(local_def(item.id)));
for variants.each |variant| { for variants.each |variant| {
@ -857,7 +857,7 @@ class Resolver {
visitor); visitor);
} }
} }
item_class(_, _, class_members, ctor, _, _) { item_class(_, _, class_members, ctor, _) {
(*name_bindings).define_type(def_ty(local_def(item.id))); (*name_bindings).define_type(def_ty(local_def(item.id)));
let purity = ctor.node.dec.purity; let purity = ctor.node.dec.purity;
@ -899,7 +899,7 @@ class Resolver {
visit_item(item, new_parent, visitor); visit_item(item, new_parent, visitor);
} }
item_impl(_, _, _, _, methods) { item_impl(_, _, _, methods) {
// Create the set of implementation information that the // Create the set of implementation information that the
// implementation scopes (ImplScopes) need and write it into // implementation scopes (ImplScopes) need and write it into
// the implementation definition list for this set of name // the implementation definition list for this set of name
@ -2884,8 +2884,8 @@ class Resolver {
} }
alt item.node { alt item.node {
item_enum(_, type_parameters, _) | item_enum(_, type_parameters) |
item_ty(_, type_parameters, _) { item_ty(_, type_parameters) {
do self.with_type_parameter_rib do self.with_type_parameter_rib
(HasTypeParameters(&type_parameters, item.id, 0u, (HasTypeParameters(&type_parameters, item.id, 0u,
NormalRibKind)) NormalRibKind))
@ -2895,7 +2895,7 @@ class Resolver {
} }
} }
item_impl(type_parameters, _, interface_reference, self_type, item_impl(type_parameters, interface_reference, self_type,
methods) { methods) {
self.resolve_implementation(item.id, self.resolve_implementation(item.id,
item.span, item.span,
@ -2906,7 +2906,7 @@ class Resolver {
visitor); visitor);
} }
item_trait(type_parameters, _, methods) { item_trait(type_parameters, methods) {
// Create a new rib for the self type. // Create a new rib for the self type.
let self_type_rib = @Rib(NormalRibKind); let self_type_rib = @Rib(NormalRibKind);
(*self.type_ribs).push(self_type_rib); (*self.type_ribs).push(self_type_rib);
@ -2948,7 +2948,7 @@ class Resolver {
} }
item_class(ty_params, interfaces, class_members, constructor, item_class(ty_params, interfaces, class_members, constructor,
optional_destructor, _) { optional_destructor) {
self.resolve_class(item.id, self.resolve_class(item.id,
@copy ty_params, @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)); ccx.external.insert(parent_id, some(item.id));
let mut my_id = 0; let mut my_id = 0;
alt check item.node { alt check item.node {
ast::item_enum(_, _, _) { ast::item_enum(_, _) {
let vs_here = ty::enum_variants(ccx.tcx, local_def(item.id)); let vs_here = ty::enum_variants(ccx.tcx, local_def(item.id));
let vs_there = ty::enum_variants(ccx.tcx, parent_id); let vs_there = ty::enum_variants(ccx.tcx, parent_id);
do vec::iter2(*vs_here, *vs_there) |here, there| { 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); impl::trans_impl(ccx, *path, item.ident, ms, tps);
} }
ast::item_mod(m) { ast::item_mod(m) {
trans_mod(ccx, m); trans_mod(ccx, m);
} }
ast::item_enum(variants, tps, _) { ast::item_enum(variants, tps) {
if tps.len() == 0u { if tps.len() == 0u {
let degen = variants.len() == 1u; let degen = variants.len() == 1u;
let vi = ty::enum_variants(ccx.tcx, local_def(item.id)); 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); 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 { if tps.len() == 0u {
let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps), let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps),
vtables: none, vtables: none,
@ -5199,7 +5199,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
~[path_name(enm.ident), ~[path_name(enm.ident),
path_name(v.node.name)]); path_name(v.node.name)]);
let llfn = alt check enm.node { let llfn = alt check enm.node {
ast::item_enum(_, _, _) { ast::item_enum(_, _) {
register_fn(ccx, v.span, pth, id) 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) { fn trans_constant(ccx: @crate_ctxt, it: @ast::item) {
let _icx = ccx.insn_ctxt("trans_constant"); let _icx = ccx.insn_ctxt("trans_constant");
alt it.node { alt it.node {
ast::item_enum(variants, _, _) { ast::item_enum(variants, _) {
let vi = ty::enum_variants(ccx.tcx, {crate: ast::local_crate, let vi = ty::enum_variants(ccx.tcx, {crate: ast::local_crate,
node: it.id}); node: it.id});
let mut i = 0; 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 { name: ast::ident) -> ast::def_id {
if impl_id.crate == ast::local_crate { if impl_id.crate == ast::local_crate {
alt check ccx.tcx.items.get(impl_id.node) { 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) method_from_methods(ms, name)
} }
ast_map::node_item(@{node: ast_map::node_item(@{node:
ast::item_class(_, _, items, _, _, _), _}, _) { ast::item_class(_, _, items, _, _), _}, _) {
let (_,ms) = split_class_items(items); let (_,ms) = split_class_items(items);
method_from_methods(ms, name) method_from_methods(ms, name)
} }

View file

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

View file

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

View file

@ -233,7 +233,9 @@ type ctxt =
cstore: metadata::cstore::cstore, cstore: metadata::cstore::cstore,
sess: session::session, sess: session::session,
def_map: resolve::def_map, def_map: resolve::def_map,
region_map: middle::region::region_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 // Stores the types for various nodes in the AST. Note that this table
// is not guaranteed to be populated until after typeck. See // 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], type ty_param_bounds_and_ty = {bounds: @~[param_bounds],
rp: ast::region_param, rp: bool,
ty: t}; ty: t};
type type_cache = hashmap<ast::def_id, ty_param_bounds_and_ty>; 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)) |&&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, 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| { let interner = map::hashmap(|&&k: intern_key| {
hash_type_structure(k.struct) + hash_type_structure(k.struct) +
option::map_default(k.o_def_id, 0u, ast_util::hash_def) 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, sess: s,
def_map: dm, def_map: dm,
region_map: region_map, region_map: region_map,
region_paramd_items: region_paramd_items,
node_types: @smallintmap::mk(), node_types: @smallintmap::mk(),
node_type_substs: map::int_hash(), node_type_substs: map::int_hash(),
items: amap, 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); #debug("(impl_trait) searching for trait impl %?", id);
alt cx.items.find(id.node) { alt cx.items.find(id.node) {
some(ast_map::node_item(@{node: ast::item_impl( some(ast_map::node_item(@{node: ast::item_impl(
_, _, some(@{id: id, _}), _, _), _}, _)) { _, some(@{id: id, _}), _, _), _}, _)) {
some(node_id_to_type(cx, 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) { alt cx.def_map.find(id.node) {
some(def_ty(trait_id)) { 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) { if is_local(class_id) {
alt cx.items.find(class_id.node) { alt cx.items.find(class_id.node) {
some(ast_map::node_item(@{node: ast::item_class(_, _, _, _, some(ast_map::node_item(@{node: ast::item_class(_, _, _, _,
some(dtor), _), _}, _)) some(dtor)), _}, _))
{ some(local_def(dtor.node.id)) } { some(local_def(dtor.node.id)) }
_ { none } _ { 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 expr, since check_enum_variants also updates the enum_var_cache
*/ */
alt cx.items.get(id.node) { 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; let mut disr_val = -1;
@vec::map(variants, |variant| { @vec::map(variants, |variant| {
let ctor_ty = node_id_to_type(cx, variant.node.id); 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) { alt cx.items.find(did.node) {
some(ast_map::node_item(i,_)) { some(ast_map::node_item(i,_)) {
alt i.node { alt i.node {
ast::item_class(_, _, items, _, _, _) { ast::item_class(_, _, items, _, _) {
class_field_tys(items) class_field_tys(items)
} }
_ { cx.sess.bug("class ID bound to non-class"); } _ { 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) fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
: is_local(did) -> ~[{name: ident, id: node_id, vis: visibility}] { : is_local(did) -> ~[{name: ident, id: node_id, vis: visibility}] {
alt cx.items.find(did.node) { 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); let (_,ms) = split_class_items(items);
vec::map(ms, |m| {name: m.ident, id: m.id, vec::map(ms, |m| {name: m.ident, id: m.id,
vis: m.vis}) 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 { 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( 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} = let {bounds: decl_bounds, rp: decl_rp, ty: decl_ty} =
self.get_item_ty(did); 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 // If the type is parameterized by the self region, then replace self
// region with the current anon region binding (in other words, // region with the current anon region binding (in other words,
// whatever & would get replaced with). // whatever & would get replaced with).
let self_r = alt (decl_rp, path.rp) { let self_r = alt (decl_rp, path.rp) {
(ast::rp_none, none) { (false, none) {
none none
} }
(ast::rp_none, some(_)) { (false, some(_)) {
tcx.sess.span_err( tcx.sess.span_err(
path.span, path.span,
#fmt["no region bound is permitted on %s, \ #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)]); ty::item_path_str(tcx, did)]);
none none
} }
(ast::rp_self, none) { (true, none) {
let res = rscope.anon_region(); let res = rscope.anon_region();
let r = get_region_reporting_err(self.tcx(), path.span, res); let r = get_region_reporting_err(self.tcx(), path.span, res);
some(r) some(r)
} }
(ast::rp_self, some(r)) { (true, some(r)) {
some(ast_region_to_region(self, rscope, path.span, 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 collect::{methods}; // ccx.to_ty()
import middle::ty::{tv_vid, vid}; import middle::ty::{tv_vid, vid};
import regionmanip::{replace_bound_regions_in_fn_ty, region_of}; 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) { fn check_item(ccx: @crate_ctxt, it: @ast::item) {
alt it.node { alt it.node {
ast::item_const(_, e) { check_const(ccx, it.span, e, it.id); } 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); check_enum_variants(ccx, it.span, vs, it.id);
} }
ast::item_fn(decl, tps, body) { ast::item_fn(decl, tps, body) {
check_bare_fn(ccx, decl, body, it.id, none); 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); let self_ty = ccx.to_ty(rscope::type_rscope(rp), ty);
for ms.each |m| { check_method(ccx, m, self_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 tcx = ccx.tcx;
let class_t = ty::node_id_to_type(tcx, it.id); let class_t = ty::node_id_to_type(tcx, it.id);
// typecheck the ctor // typecheck the ctor
@ -387,9 +390,9 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
// Check that the class is instantiable // Check that the class is instantiable
check_instantiable(ccx.tcx, it.span, it.id); 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); 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) { ast::item_foreign_mod(m) {
if syntax::attr::foreign_abi(it.attrs) == 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 tcx = fcx.ccx.tcx;
let {n_tps, rp, raw_ty} = if did.crate == ast::local_crate { 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) { 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(), {n_tps: ts.len(),
rp: rp, rp: rp,
raw_ty: fcx.ccx.to_ty(rscope::type_rscope(rp), st)} raw_ty: fcx.ccx.to_ty(rscope::type_rscope(rp), st)}
} }
some(ast_map::node_item(@{node: ast::item_class(ts, 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 /* 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, (doing a no-op subst for the ty params; in the next step,
we substitute in fresh vars for them) 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(), {n_tps: ts.len(),
rp: rp, rp: rp,
raw_ty: ty::mk_class(tcx, local_def(class_id), raw_ty: ty::mk_class(tcx, local_def(class_id),
{self_r: alt rp { {self_r: if rp {some(ty::re_bound(ty::br_self))}
ast::rp_self { some(fcx.infcx.next_region_var()) } else {none},
ast::rp_none { none }},
self_ty: none, self_ty: none,
tps: ty::ty_params_to_tys(tcx, ts)})} 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} raw_ty: ity.ty}
}; };
let self_r = alt rp { let self_r = if rp {some(fcx.infcx.next_region_var())} else {none};
ast::rp_none { none }
ast::rp_self { some(fcx.infcx.next_region_var()) }
};
let tps = fcx.infcx.next_ty_vars(n_tps); let tps = fcx.infcx.next_ty_vars(n_tps);
let substs = {self_r: self_r, self_ty: none, tps: 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 // extern functions are just u8 pointers
ret { ret {
bounds: @~[], bounds: @~[],
rp: ast::rp_none, rp: false,
ty: ty::mk_ptr( ty: ty::mk_ptr(
fcx.ccx.tcx, fcx.ccx.tcx,
{ {
@ -2109,13 +2109,27 @@ fn instantiate_path(fcx: @fn_ctxt,
let ty_param_count = vec::len(*tpt.bounds); let ty_param_count = vec::len(*tpt.bounds);
let ty_substs_len = vec::len(pth.types); let ty_substs_len = vec::len(pth.types);
// For now, there is no way to explicitly specify the region bound. // determine the region bound, using the value given by the user
// This will have to change eventually. // (if any) and otherwise using a fresh region variable
let self_r = alt tpt.rp { let self_r = alt pth.rp {
ast::rp_self { some(fcx.infcx.next_region_var()) } some(r) if !tpt.rp => {
ast::rp_none { none } 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 { let tps = if ty_substs_len == 0u {
fcx.infcx.next_ty_vars(ty_param_count) fcx.infcx.next_ty_vars(ty_param_count)
} else if ty_param_count == 0u { } 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, fn check_bounds_are_used(ccx: @crate_ctxt,
span: span, span: span,
tps: ~[ast::ty_param], tps: ~[ast::ty_param],
rp: ast::region_param,
ty: ty::t) { ty: ty::t) {
let mut r_used = alt rp { // make a vector of booleans initially false, set to true when used
ast::rp_self { false } if tps.len() == 0u { ret; }
ast::rp_none { true }
};
if tps.len() == 0u && r_used { ret; }
let tps_used = vec::to_mut(vec::from_elem(tps.len(), false)); let tps_used = vec::to_mut(vec::from_elem(tps.len(), false));
ty::walk_regions_and_ty( ty::walk_regions_and_ty(
ccx.tcx, ty, ccx.tcx, ty,
|r| { |_r| {},
alt r {
ty::re_bound(_) { r_used = true; }
_ { }
}
},
|t| { |t| {
alt ty::get(t).struct { alt ty::get(t).struct {
ty::ty_param(idx, _) { tps_used[idx] = true; } ty::ty_param(idx, _) { tps_used[idx] = true; }
@ -2229,12 +2233,6 @@ fn check_bounds_are_used(ccx: @crate_ctxt,
true true
}); });
if !r_used {
ccx.tcx.sess.span_err(
span, "lifetime `self` unused inside \
reference-parameterized type");
}
for tps_used.eachi |i, b| { for tps_used.eachi |i, b| {
if !b { if !b {
ccx.tcx.sess.span_err( 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::{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_fn, item_foreign_mod, item_impl, item_mac};
import syntax::ast::{item_mod, item_trait, item_ty, local_crate, method}; 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::ast_util::{def_id_of_def, new_def_hash};
import syntax::visit::{default_simple_visitor, default_visitor}; import syntax::visit::{default_simple_visitor, default_visitor};
import syntax::visit::{mk_simple_visitor, mk_vt, visit_crate, visit_item}; 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_crate(*crate, (), mk_simple_visitor(@{
visit_item: |item| { visit_item: |item| {
alt item.node { alt item.node {
item_impl(_, _, associated_trait, self_type, _) { item_impl(_, associated_trait, self_type, _) {
self.check_implementation(item, associated_trait); self.check_implementation(item, associated_trait);
} }
_ { _ {
@ -239,15 +239,9 @@ class CoherenceChecker {
// Converts a polytype to a monotype by replacing all parameters with // Converts a polytype to a monotype by replacing all parameters with
// type variables. // type variables.
fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t { fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t {
let self_region; let self_region =
alt polytype.rp { if polytype.rp {none}
rp_none { else {some(self.inference_context.next_region_var())};
self_region = none;
}
rp_self {
self_region = some(self.inference_context.next_region_var())
}
};
let bounds_count = polytype.bounds.len(); let bounds_count = polytype.bounds.len();
let type_parameters = let type_parameters =
@ -304,7 +298,7 @@ class CoherenceChecker {
self.privileged_types.remove(privileged_type); 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) { alt self.base_type_def_ids.find(item.id) {
none { none {
// Nothing to do. // Nothing to do.

View file

@ -39,13 +39,13 @@ fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) {
alt intrinsic_item.node { alt intrinsic_item.node {
ast::item_trait(_, _, _) { ast::item_trait(_, _) {
let ty = ty::mk_trait(ccx.tcx, def_id, substs); let ty = ty::mk_trait(ccx.tcx, def_id, substs);
ccx.tcx.intrinsic_defs.insert ccx.tcx.intrinsic_defs.insert
(intrinsic_item.ident, (def_id, ty)); (intrinsic_item.ident, (def_id, ty));
} }
ast::item_enum(_, _, _) { ast::item_enum(_, _) {
let ty = ty::mk_enum(ccx.tcx, def_id, substs); let ty = ty::mk_enum(ccx.tcx, def_id, substs);
ccx.tcx.intrinsic_defs.insert ccx.tcx.intrinsic_defs.insert
(intrinsic_item.ident, (def_id, ty)); (intrinsic_item.ident, (def_id, ty));
@ -107,7 +107,7 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
enum_ty: ty::t, enum_ty: ty::t,
variants: ~[ast::variant], variants: ~[ast::variant],
ty_params: ~[ast::ty_param], ty_params: ~[ast::ty_param],
rp: ast::region_param) { rp: bool) {
let tcx = ccx.tcx; let tcx = ccx.tcx;
// Create a set of parameter types shared among all the variants. // 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 tcx = ccx.tcx;
let rp = tcx.region_paramd_items.contains_key(id);
alt check tcx.items.get(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| { store_methods::<ast::ty_method>(ccx, id, ms, |m| {
ty_of_ty_method(ccx, m, rp) 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); let (_,ms) = split_class_items(its);
// All methods need to be stored, since lookup_method // All methods need to be stored, since lookup_method
// relies on the same method cache for self-calls // 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, fn check_methods_against_trait(ccx: @crate_ctxt,
tps: ~[ast::ty_param], tps: ~[ast::ty_param],
rp: ast::region_param, rp: bool,
selfty: ty::t, selfty: ty::t,
a_trait_ty: @ast::trait_ref, a_trait_ty: @ast::trait_ref,
ms: ~[converted_method]) { ms: ~[converted_method]) {
@ -267,7 +268,7 @@ fn check_methods_against_trait(ccx: @crate_ctxt,
} // fn } // fn
fn convert_class_item(ccx: @crate_ctxt, fn convert_class_item(ccx: @crate_ctxt,
rp: ast::region_param, rp: bool,
bounds: @~[ty::param_bounds], bounds: @~[ty::param_bounds],
v: ast_util::ivar) { v: ast_util::ivar) {
let tt = ccx.to_ty(type_rscope(rp), v.ty); 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, fn convert_methods(ccx: @crate_ctxt,
ms: ~[@ast::method], ms: ~[@ast::method],
rp: ast::region_param, rp: bool,
rcvr_bounds: @~[ty::param_bounds], rcvr_bounds: @~[ty::param_bounds],
self_ty: ty::t) -> ~[converted_method] { self_ty: ty::t) -> ~[converted_method] {
@ -303,16 +304,17 @@ fn convert_methods(ccx: @crate_ctxt,
fn convert(ccx: @crate_ctxt, it: @ast::item) { fn convert(ccx: @crate_ctxt, it: @ast::item) {
let tcx = ccx.tcx; 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 { alt it.node {
// These don't define types. // These don't define types.
ast::item_foreign_mod(_) | ast::item_mod(_) {} 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); let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty); write_ty_to_tcx(tcx, it.id, tpt.ty);
get_enum_variant_types(ccx, tpt.ty, variants, get_enum_variant_types(ccx, tpt.ty, variants, ty_params, rp);
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 i_bounds = ty_param_bounds(ccx, tps);
let selfty = ccx.to_ty(type_rscope(rp), selfty); let selfty = ccx.to_ty(type_rscope(rp), selfty);
write_ty_to_tcx(tcx, it.id, 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); write_ty_to_tcx(tcx, it.id, tpt.ty);
ensure_trait_methods(ccx, it.id); 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 // Write the class type
let tpt = ty_of_item(ccx, it); let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty); write_ty_to_tcx(tcx, it.id, tpt.ty);
@ -341,14 +343,13 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
// Write the ctor type // Write the ctor type
let t_args = ctor.node.dec.inputs.map( let t_args = ctor.node.dec.inputs.map(
|a| ty_of_arg(ccx, type_rscope(rp), a, none) ); |a| ty_of_arg(ccx, type_rscope(rp), a, none) );
let t_res = ty::mk_class(tcx, local_def(it.id), let t_res = ty::mk_class(
{self_r: alt rp { tcx, local_def(it.id),
ast::rp_none { none } {self_r: if rp {some(ty::re_bound(ty::br_self))} else {none},
ast::rp_self { some(ty::re_bound(ty::br_self)) }
},
self_ty: none, self_ty: none,
tps: ty::ty_params_to_tys(tcx, tps)}); tps: ty::ty_params_to_tys(tcx, tps)});
let t_ctor = ty::mk_fn(tcx, {purity: ast::impure_fn, let t_ctor = ty::mk_fn(
tcx, {purity: ast::impure_fn,
proto: ast::proto_any, proto: ast::proto_any,
inputs: t_args, inputs: t_args,
output: t_res, output: t_res,
@ -421,7 +422,7 @@ fn convert_foreign(ccx: @crate_ctxt, i: @ast::foreign_item) {
fn ty_of_method(ccx: @crate_ctxt, fn ty_of_method(ccx: @crate_ctxt,
m: @ast::method, m: @ast::method,
rp: ast::region_param) -> ty::method { rp: bool) -> ty::method {
{ident: m.ident, {ident: m.ident,
tps: ty_param_bounds(ccx, m.tps), tps: ty_param_bounds(ccx, m.tps),
fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare, fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare,
@ -432,7 +433,7 @@ fn ty_of_method(ccx: @crate_ctxt,
fn ty_of_ty_method(self: @crate_ctxt, fn ty_of_ty_method(self: @crate_ctxt,
m: ast::ty_method, m: ast::ty_method,
rp: ast::region_param) -> ty::method { rp: bool) -> ty::method {
{ident: m.ident, {ident: m.ident,
tps: ty_param_bounds(self, m.tps), tps: ty_param_bounds(self, m.tps),
fty: ty_of_fn_decl(self, type_rscope(rp), ast::proto_bare, 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 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. trait. Fails if the type is a type other than an trait type.
*/ */
fn instantiate_trait_ref(ccx: @crate_ctxt, t: @ast::trait_ref, fn instantiate_trait_ref(ccx: @crate_ctxt, t: @ast::trait_ref, rp: bool)
rp: ast::region_param)
-> (ast::def_id, ty_param_substs_and_ty) { -> (ast::def_id, ty_param_substs_and_ty) {
let sp = t.path.span, err = "can only implement interface types", 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; } some(tpt) { ret tpt; }
_ {} _ {}
} }
let rp = tcx.region_paramd_items.contains_key(it.id);
alt it.node { alt it.node {
ast::item_const(t, _) { ast::item_const(t, _) {
let typ = ccx.to_ty(empty_rscope, 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, let tofd = ty_of_fn_decl(ccx, empty_rscope, ast::proto_bare,
decl, none); decl, none);
let tpt = {bounds: bounds, 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)}; ty: ty::mk_fn(ccx.tcx, tofd)};
#debug["type of %s (id %d) is %s", #debug["type of %s (id %d) is %s",
*it.ident, it.id, ty_to_str(tcx, tpt.ty)]; *it.ident, it.id, ty_to_str(tcx, tpt.ty)];
ccx.tcx.tcache.insert(local_def(it.id), tpt); ccx.tcx.tcache.insert(local_def(it.id), tpt);
ret tpt; ret tpt;
} }
ast::item_ty(t, tps, rp) { ast::item_ty(t, tps) {
alt tcx.tcache.find(local_def(it.id)) { alt tcx.tcache.find(local_def(it.id)) {
some(tpt) { ret tpt; } some(tpt) { ret tpt; }
none { } none { }
} }
let rp = tcx.region_paramd_items.contains_key(it.id);
let tpt = { let tpt = {
let ty = { let ty = {
let t0 = ccx.to_ty(type_rscope(rp), t); 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); tcx.tcache.insert(local_def(it.id), tpt);
ret tpt; ret tpt;
} }
ast::item_enum(_, tps, rp) { ast::item_enum(_, tps) {
// Create a new generic polytype. // Create a new generic polytype.
let {bounds, substs} = mk_substs(ccx, tps, rp); let {bounds, substs} = mk_substs(ccx, tps, rp);
let t = ty::mk_enum(tcx, local_def(it.id), substs); 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); tcx.tcache.insert(local_def(it.id), tpt);
ret tpt; ret tpt;
} }
ast::item_trait(tps, rp, ms) { ast::item_trait(tps, ms) {
let {bounds, substs} = mk_substs(ccx, tps, rp); let {bounds, substs} = mk_substs(ccx, tps, rp);
let t = ty::mk_trait(tcx, local_def(it.id), substs); let t = ty::mk_trait(tcx, local_def(it.id), substs);
let tpt = {bounds: bounds, rp: rp, ty: t}; let tpt = {bounds: bounds, rp: rp, ty: t};
tcx.tcache.insert(local_def(it.id), tpt); tcx.tcache.insert(local_def(it.id), tpt);
ret tpt; ret tpt;
} }
ast::item_class(tps, _, _, _, _, rp) { ast::item_class(tps, _, _, _, _) {
let {bounds,substs} = mk_substs(ccx, tps, rp); let {bounds,substs} = mk_substs(ccx, tps, rp);
let t = ty::mk_class(tcx, local_def(it.id), substs); let t = ty::mk_class(tcx, local_def(it.id), substs);
let tpt = {bounds: bounds, rp: rp, ty: t}; let tpt = {bounds: bounds, rp: rp, ty: t};
@ -615,7 +617,7 @@ fn ty_of_foreign_fn_decl(ccx: @crate_ctxt,
output: output_ty, output: output_ty,
ret_style: ast::return_val, ret_style: ast::return_val,
constraints: ~[]}); 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); ccx.tcx.tcache.insert(def_id, tpt);
ret 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} { -> {bounds: @~[ty::param_bounds], substs: ty::substs} {
let {bounds, params} = mk_ty_params(ccx, atps); let {bounds, params} = mk_ty_params(ccx, atps);
let self_r = alt rp { let self_r = if rp {some(ty::re_bound(ty::br_self))} else {none};
ast::rp_self { some(ty::re_bound(ty::br_self)) }
ast::rp_none { none }
};
{bounds: bounds, substs: {self_r: self_r, self_ty: none, tps: params}} {bounds: bounds, substs: {self_r: self_r, self_ty: none, tps: params}}
} }

View file

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

View file

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

View file

@ -78,22 +78,22 @@ fn moddoc_from_mod(
constdoc_from_const(itemdoc) constdoc_from_const(itemdoc)
)) ))
} }
ast::item_enum(variants, _, _) { ast::item_enum(variants, _) {
some(doc::enumtag( some(doc::enumtag(
enumdoc_from_enum(itemdoc, variants) enumdoc_from_enum(itemdoc, variants)
)) ))
} }
ast::item_trait(_, _, methods) { ast::item_trait(_, methods) {
some(doc::traittag( some(doc::traittag(
traitdoc_from_trait(itemdoc, methods) traitdoc_from_trait(itemdoc, methods)
)) ))
} }
ast::item_impl(_, _, _, _, methods) { ast::item_impl(_, _, _, methods) {
some(doc::impltag( some(doc::impltag(
impldoc_from_impl(itemdoc, methods) impldoc_from_impl(itemdoc, methods)
)) ))
} }
ast::item_ty(_, _, _) { ast::item_ty(_, _) {
some(doc::tytag( some(doc::tytag(
tydoc_from_ty(itemdoc) 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(); let all_impls = ast_util::new_def_hash();
for m.items.each |item| { for m.items.each |item| {
alt item.node { alt item.node {
ast::item_impl(_, _, _, _, _) { ast::item_impl(_, _, _, _) {
all_impls.insert(ast_util::local_def(item.id), ()); 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| { let sig = do astsrv::exec(srv) |ctxt| {
alt check ctxt.ast_map.get(doc_id) { alt check ctxt.ast_map.get(doc_id) {
ast_map::node_item(@{ ast_map::node_item(@{
node: ast::item_enum(ast_variants, _, _), _ node: ast::item_enum(ast_variants, _), _
}, _) { }, _) {
let ast_variant = option::get( let ast_variant = option::get(
do vec::find(ast_variants) |v| { do vec::find(ast_variants) |v| {
@ -168,7 +168,7 @@ fn get_method_sig(
do astsrv::exec(srv) |ctxt| { do astsrv::exec(srv) |ctxt| {
alt check ctxt.ast_map.get(item_id) { alt check ctxt.ast_map.get(item_id) {
ast_map::node_item(@{ ast_map::node_item(@{
node: ast::item_trait(_, _, methods), _ node: ast::item_trait(_, methods), _
}, _) { }, _) {
alt check vec::find(methods, |method| { alt check vec::find(methods, |method| {
*method.ident == method_name *method.ident == method_name
@ -183,7 +183,7 @@ fn get_method_sig(
} }
} }
ast_map::node_item(@{ ast_map::node_item(@{
node: ast::item_impl(_, _, _, _, methods), _ node: ast::item_impl(_, _, _, methods), _
}, _) { }, _) {
alt check vec::find(methods, |method| { alt check vec::find(methods, |method| {
*method.ident == method_name *method.ident == method_name
@ -218,7 +218,7 @@ fn fold_impl(
let (trait_ty, self_ty) = do astsrv::exec(srv) |ctxt| { let (trait_ty, self_ty) = do astsrv::exec(srv) |ctxt| {
alt ctxt.ast_map.get(doc.id()) { alt ctxt.ast_map.get(doc.id()) {
ast_map::node_item(@{ 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| { let trait_ty = option::map(trait_ty, |p| {
pprust::path_to_str(p.path) pprust::path_to_str(p.path)
@ -274,7 +274,7 @@ fn fold_type(
alt ctxt.ast_map.get(doc.id()) { alt ctxt.ast_map.get(doc.id()) {
ast_map::node_item(@{ ast_map::node_item(@{
ident: ident, ident: ident,
node: ast::item_ty(ty, params, ast::rp_none), _ node: ast::item_ty(ty, params), _
}, _) { }, _) {
some(#fmt( some(#fmt(
"type %s%s = %s", "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 // nominal types (but not on other types) and that they are type
// checked. // checked.
enum an_enum/& { } enum an_enum = &int;
iface an_iface/& { } iface an_iface { fn foo() -> &self.int; }
class a_class/& { let x:int; new(x:int) { self.x = x; } } class a_class { let x:&self.int; new(x:&self.int) { self.x = x; } }
fn a_fn1(e: an_enum/&a) -> an_enum/&b { fn a_fn1(e: an_enum/&a) -> an_enum/&b {
ret e; //~ ERROR mismatched types: expected `an_enum/&b` but found `an_enum/&a` 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), num(uint),
add(&ast, &ast) add(&ast, &ast)
} }

View file

@ -1,13 +1,13 @@
type ctxt = { v: uint }; type ctxt = { v: uint };
iface get_ctxt/& { iface get_ctxt {
// Here the `&` is bound in the method definition: // Here the `&` is bound in the method definition:
fn get_ctxt() -> &ctxt; 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 // Here an error occurs because we used `&self` but
// the definition used `&`: // the definition used `&`:

View file

@ -1,12 +1,12 @@
type ctxt = { v: uint }; type ctxt = { v: uint };
iface get_ctxt/& { iface get_ctxt {
fn get_ctxt() -> &self.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 } fn get_ctxt() -> &self.ctxt { self.c }
} }

View file

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

View file

@ -1,24 +1,12 @@
enum no0 { enum yes0 {
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/& {
x3(&uint) x3(&uint)
} }
enum yes1/& { enum yes1 {
x4(&self.uint) 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 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 { class yes0 {
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/& {
let x: &uint; let x: &uint;
new(x: &uint) { self.x = x; } new(x: &uint) { self.x = x; }
drop {} drop {}
} }
class yes1/& { class yes1 {
let x: &self.uint; let x: &self.uint;
new(x: &self.uint) { self.x = x; } new(x: &self.uint) { self.x = x; }
drop {} drop {}
} }
class yes2/& { class yes2 {
let x: &foo.uint; //~ ERROR named regions other than `self` are not allowed as part of a type declaration 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 new(x: &foo.uint) { self.x = x; } //~ ERROR named regions other than `self` are not allowed as part of a type declaration
drop {} drop {}

View file

@ -1,24 +1,12 @@
type item_ty_no0 = { type item_ty_yes0 = {
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/& = {
x: &uint x: &uint
}; };
type item_ty_yes1/& = { type item_ty_yes1 = {
x: &self.uint 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 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); 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) { fn iterate(f: fn(A) -> bool) {
vec::each(self, f); vec::each(self, f);
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,12 +1,12 @@
type ctxt = { v: uint }; type ctxt = { v: uint };
iface get_ctxt/& { iface get_ctxt {
fn get_ctxt() -> &self.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 { fn get_ctxt() -> &self.ctxt {
self.c self.c
} }

View file

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

View file

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

View file

@ -1,4 +1,4 @@
enum roption/& { enum roption {
a, b(&uint) 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; } fn get_chowder() -> &self.int { ret self.chowder; }
} }

View file

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