mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-23 04:14:28 +00:00
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:
parent
9b094c0baf
commit
b9aa9def85
@ -678,31 +678,24 @@ type item = {ident: ident, attrs: ~[attribute],
|
||||
id: node_id, node: item_,
|
||||
vis: visibility, span: span};
|
||||
|
||||
#[auto_serialize]
|
||||
enum region_param {
|
||||
rp_none,
|
||||
rp_self
|
||||
}
|
||||
|
||||
#[auto_serialize]
|
||||
enum item_ {
|
||||
item_const(@ty, @expr),
|
||||
item_fn(fn_decl, ~[ty_param], blk),
|
||||
item_mod(_mod),
|
||||
item_foreign_mod(foreign_mod),
|
||||
item_ty(@ty, ~[ty_param], region_param),
|
||||
item_enum(~[variant], ~[ty_param], region_param),
|
||||
item_ty(@ty, ~[ty_param]),
|
||||
item_enum(~[variant], ~[ty_param]),
|
||||
item_class(~[ty_param], /* ty params for class */
|
||||
~[@trait_ref], /* traits this class implements */
|
||||
~[@class_member], /* methods, etc. */
|
||||
/* (not including ctor or dtor) */
|
||||
class_ctor,
|
||||
/* dtor is optional */
|
||||
option<class_dtor>,
|
||||
region_param
|
||||
option<class_dtor>
|
||||
),
|
||||
item_trait(~[ty_param], region_param, ~[ty_method]),
|
||||
item_impl(~[ty_param], region_param, option<@trait_ref> /* trait */,
|
||||
item_trait(~[ty_param], ~[ty_method]),
|
||||
item_impl(~[ty_param], option<@trait_ref> /* trait */,
|
||||
@ty /* self */, ~[@method]),
|
||||
item_mac(mac),
|
||||
}
|
||||
|
@ -188,14 +188,14 @@ fn map_item(i: @item, cx: ctx, v: vt) {
|
||||
let item_path = @/* FIXME (#2543) */ copy cx.path;
|
||||
cx.map.insert(i.id, node_item(i, item_path));
|
||||
alt i.node {
|
||||
item_impl(_, _, _, _, ms) {
|
||||
item_impl(_, _, _, ms) {
|
||||
let impl_did = ast_util::local_def(i.id);
|
||||
for ms.each |m| {
|
||||
map_method(impl_did, extend(cx, i.ident), m,
|
||||
cx);
|
||||
}
|
||||
}
|
||||
item_enum(vs, _, _) {
|
||||
item_enum(vs, _) {
|
||||
for vs.each |v| {
|
||||
cx.map.insert(v.node.id, node_variant(
|
||||
/* FIXME (#2543) */ copy v, i,
|
||||
@ -214,7 +214,7 @@ fn map_item(i: @item, cx: ctx, v: vt) {
|
||||
extend(cx, i.ident)));
|
||||
}
|
||||
}
|
||||
item_class(tps, traits, items, ctor, dtor, _) {
|
||||
item_class(tps, traits, items, ctor, dtor) {
|
||||
let (_, ms) = ast_util::split_class_items(items);
|
||||
// Map trait refs to their parent classes. This is
|
||||
// so we can find the self_ty
|
||||
|
@ -155,7 +155,7 @@ fn is_exported(i: ident, m: _mod) -> bool {
|
||||
for m.items.each |it| {
|
||||
if it.ident == i { local = true; }
|
||||
alt it.node {
|
||||
item_enum(variants, _, _) {
|
||||
item_enum(variants, _) {
|
||||
for variants.each |v| {
|
||||
if v.node.name == i {
|
||||
local = true;
|
||||
@ -428,7 +428,7 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
|
||||
visit_item: fn@(i: @item) {
|
||||
vfn(i.id);
|
||||
alt i.node {
|
||||
item_enum(vs, _, _) { for vs.each |v| { vfn(v.node.id); } }
|
||||
item_enum(vs, _) { for vs.each |v| { vfn(v.node.id); } }
|
||||
_ {}
|
||||
}
|
||||
},
|
||||
@ -519,6 +519,9 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
|
||||
}
|
||||
},
|
||||
|
||||
visit_ty_method: fn@(_ty_m: ty_method) {
|
||||
},
|
||||
|
||||
visit_class_item: fn@(c: @class_member) {
|
||||
alt c.node {
|
||||
instance_var(_, _, _, id,_) {
|
||||
|
@ -102,12 +102,12 @@ fn expand(cx: ext_ctxt,
|
||||
|
||||
do vec::flat_map(in_items) |in_item| {
|
||||
alt in_item.node {
|
||||
ast::item_ty(ty, tps, _) {
|
||||
ast::item_ty(ty, tps) {
|
||||
vec::append(~[filter_attrs(in_item)],
|
||||
ty_fns(cx, in_item.ident, ty, tps))
|
||||
}
|
||||
|
||||
ast::item_enum(variants, tps, _) {
|
||||
ast::item_enum(variants, tps) {
|
||||
vec::append(~[filter_attrs(in_item)],
|
||||
enum_fns(cx, in_item.ident,
|
||||
in_item.span, variants, tps))
|
||||
|
@ -128,8 +128,7 @@ impl ast_builder for ext_ctxt {
|
||||
+ty_params: ~[ast::ty_param]) -> @ast::item {
|
||||
self.item(name,
|
||||
ast::item_enum(variants,
|
||||
ty_params,
|
||||
ast::rp_none))
|
||||
ty_params))
|
||||
}
|
||||
|
||||
fn item_enum(name: ident,
|
||||
@ -167,12 +166,10 @@ impl ast_builder for ext_ctxt {
|
||||
fn item_ty_poly(name: ident,
|
||||
ty: @ast::ty,
|
||||
+params: ~[ast::ty_param]) -> @ast::item {
|
||||
self.item(name,
|
||||
ast::item_ty(ty, params, ast::rp_none))
|
||||
self.item(name, ast::item_ty(ty, params))
|
||||
}
|
||||
|
||||
fn item_ty(name: ident,
|
||||
ty: @ast::ty) -> @ast::item {
|
||||
fn item_ty(name: ident, ty: @ast::ty) -> @ast::item {
|
||||
self.item_ty_poly(name, ty, ~[])
|
||||
}
|
||||
|
||||
|
@ -244,15 +244,13 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
|
||||
}
|
||||
item_mod(m) { item_mod(fld.fold_mod(m)) }
|
||||
item_foreign_mod(nm) { item_foreign_mod(fld.fold_foreign_mod(nm)) }
|
||||
item_ty(t, typms, rp) { item_ty(fld.fold_ty(t),
|
||||
fold_ty_params(typms, fld),
|
||||
rp) }
|
||||
item_enum(variants, typms, r) {
|
||||
item_ty(t, typms) { item_ty(fld.fold_ty(t),
|
||||
fold_ty_params(typms, fld)) }
|
||||
item_enum(variants, typms) {
|
||||
item_enum(vec::map(variants, |x| fld.fold_variant(x)),
|
||||
fold_ty_params(typms, fld),
|
||||
r)
|
||||
fold_ty_params(typms, fld))
|
||||
}
|
||||
item_class(typms, traits, items, ctor, m_dtor, rp) {
|
||||
item_class(typms, traits, items, ctor, m_dtor) {
|
||||
let ctor_body = fld.fold_block(ctor.node.body);
|
||||
let ctor_decl = fold_fn_decl(ctor.node.dec, fld);
|
||||
let ctor_id = fld.new_id(ctor.node.id);
|
||||
@ -269,18 +267,16 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
|
||||
{node: {body: ctor_body,
|
||||
dec: ctor_decl,
|
||||
id: ctor_id with ctor.node}
|
||||
with ctor}, dtor, rp)
|
||||
with ctor}, dtor)
|
||||
}
|
||||
item_impl(tps, rp, ifce, ty, methods) {
|
||||
item_impl(tps, ifce, ty, methods) {
|
||||
item_impl(fold_ty_params(tps, fld),
|
||||
rp,
|
||||
ifce.map(|p| fold_trait_ref(p, fld)),
|
||||
fld.fold_ty(ty),
|
||||
vec::map(methods, |x| fld.fold_method(x)))
|
||||
}
|
||||
item_trait(tps, rp, methods) {
|
||||
item_trait(tps, methods) {
|
||||
item_trait(fold_ty_params(tps, fld),
|
||||
rp,
|
||||
/* FIXME (#2543) */ copy methods)
|
||||
}
|
||||
item_mac(m) {
|
||||
|
@ -41,8 +41,8 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
|
||||
pat_box, pat_enum, pat_ident, pat_lit, pat_range, pat_rec,
|
||||
pat_tup, pat_uniq, pat_wild, path, private, proto, proto_any,
|
||||
proto_bare, proto_block, proto_box, proto_uniq, public, pure_fn,
|
||||
purity, re_anon, re_named, region, region_param, rem, ret_style,
|
||||
return_val, rp_none, rp_self, shl, shr, stmt, stmt_decl,
|
||||
purity, re_anon, re_named, region, rem, ret_style,
|
||||
return_val, shl, shr, stmt, stmt_decl,
|
||||
stmt_expr, stmt_semi, subtract, token_tree, trait_ref, tt_delim,
|
||||
tt_dotdotdot, tt_flat, tt_interpolate, ty, ty_, ty_bot, ty_box,
|
||||
ty_constr, ty_constr_, ty_constr_arg, ty_field, ty_fn, ty_infer,
|
||||
@ -2133,10 +2133,10 @@ class parser {
|
||||
|
||||
fn parse_item_trait() -> item_info {
|
||||
let ident = self.parse_ident();
|
||||
let rp = self.parse_region_param();
|
||||
self.parse_region_param();
|
||||
let tps = self.parse_ty_params();
|
||||
let meths = self.parse_ty_methods();
|
||||
(ident, item_trait(tps, rp, meths), none)
|
||||
(ident, item_trait(tps, meths), none)
|
||||
}
|
||||
|
||||
// Parses three variants (with the region/type params always optional):
|
||||
@ -2147,18 +2147,19 @@ class parser {
|
||||
fn wrap_path(p: parser, pt: @path) -> @ty {
|
||||
@{id: p.get_id(), node: ty_path(pt, p.get_id()), span: pt.span}
|
||||
}
|
||||
let mut (ident, rp, tps) = {
|
||||
let mut (ident, tps) = {
|
||||
if self.token == token::LT {
|
||||
(none, rp_none, self.parse_ty_params())
|
||||
(none, self.parse_ty_params())
|
||||
} else if self.token == token::BINOP(token::SLASH) {
|
||||
(none, self.parse_region_param(), self.parse_ty_params())
|
||||
self.parse_region_param();
|
||||
(none, self.parse_ty_params())
|
||||
}
|
||||
else if self.is_keyword("of") {
|
||||
(none, rp_none, ~[])
|
||||
(none, ~[])
|
||||
} else {
|
||||
let id = self.parse_ident();
|
||||
let rp = self.parse_region_param();
|
||||
(some(id), rp, self.parse_ty_params())
|
||||
self.parse_region_param();
|
||||
(some(id), self.parse_ty_params())
|
||||
}
|
||||
};
|
||||
let ifce = if self.eat_keyword("of") {
|
||||
@ -2179,25 +2180,18 @@ class parser {
|
||||
while !self.eat(token::RBRACE) {
|
||||
vec::push(meths, self.parse_method(public));
|
||||
}
|
||||
(ident, item_impl(tps, rp, ifce, ty, meths), none)
|
||||
(ident, item_impl(tps, ifce, ty, meths), none)
|
||||
}
|
||||
|
||||
// Instantiates ident <i> with references to <typarams> as arguments.
|
||||
// Used to create a path that refers to a class which will be defined as
|
||||
// the return type of the ctor function.
|
||||
fn ident_to_path_tys(i: ident,
|
||||
rp: region_param,
|
||||
typarams: ~[ty_param]) -> @path {
|
||||
let s = self.last_span;
|
||||
|
||||
// Hack. But then, this whole function is in service of a hack.
|
||||
let a_r = alt rp {
|
||||
rp_none { none }
|
||||
rp_self { some(self.region_from_name(some(@"self"))) }
|
||||
};
|
||||
|
||||
@{span: s, global: false, idents: ~[i],
|
||||
rp: a_r,
|
||||
rp: none,
|
||||
types: vec::map(typarams, |tp| {
|
||||
@{id: self.get_id(),
|
||||
node: ty_path(ident_to_path(s, tp.ident), self.get_id()),
|
||||
@ -2218,9 +2212,9 @@ class parser {
|
||||
|
||||
fn parse_item_class() -> item_info {
|
||||
let class_name = self.parse_value_ident();
|
||||
let rp = self.parse_region_param();
|
||||
self.parse_region_param();
|
||||
let ty_params = self.parse_ty_params();
|
||||
let class_path = self.ident_to_path_tys(class_name, rp, ty_params);
|
||||
let class_path = self.ident_to_path_tys(class_name, ty_params);
|
||||
let traits : ~[@trait_ref] = if self.eat(token::COLON)
|
||||
{ self.parse_trait_ref_list() }
|
||||
else { ~[] };
|
||||
@ -2255,7 +2249,7 @@ class parser {
|
||||
self_id: self.get_id(),
|
||||
dec: ct_d,
|
||||
body: ct_b},
|
||||
span: ct_s}, actual_dtor, rp),
|
||||
span: ct_s}, actual_dtor),
|
||||
none)
|
||||
}
|
||||
/*
|
||||
@ -2447,26 +2441,23 @@ class parser {
|
||||
|
||||
fn parse_item_type() -> item_info {
|
||||
let t = self.parse_type_decl();
|
||||
let rp = self.parse_region_param();
|
||||
self.parse_region_param();
|
||||
let tps = self.parse_ty_params();
|
||||
self.expect(token::EQ);
|
||||
let ty = self.parse_ty(false);
|
||||
self.expect(token::SEMI);
|
||||
(t.ident, item_ty(ty, tps, rp), none)
|
||||
(t.ident, item_ty(ty, tps), none)
|
||||
}
|
||||
|
||||
fn parse_region_param() -> region_param {
|
||||
fn parse_region_param() {
|
||||
if self.eat(token::BINOP(token::SLASH)) {
|
||||
self.expect(token::BINOP(token::AND));
|
||||
rp_self
|
||||
} else {
|
||||
rp_none
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_item_enum(default_vis: visibility) -> item_info {
|
||||
let id = self.parse_ident();
|
||||
let rp = self.parse_region_param();
|
||||
self.parse_region_param();
|
||||
let ty_params = self.parse_ty_params();
|
||||
let mut variants: ~[variant] = ~[];
|
||||
// Newtype syntax
|
||||
@ -2483,7 +2474,7 @@ class parser {
|
||||
id: self.get_id(),
|
||||
disr_expr: none,
|
||||
vis: public});
|
||||
ret (id, item_enum(~[variant], ty_params, rp), none);
|
||||
ret (id, item_enum(~[variant], ty_params), none);
|
||||
}
|
||||
self.expect(token::LBRACE);
|
||||
|
||||
@ -2521,7 +2512,7 @@ class parser {
|
||||
self.fatal("discriminator values can only be used with a c-like \
|
||||
enum");
|
||||
}
|
||||
(id, item_enum(variants, ty_params, rp), none)
|
||||
(id, item_enum(variants, ty_params), none)
|
||||
}
|
||||
|
||||
fn parse_fn_ty_proto() -> proto {
|
||||
|
@ -458,12 +458,11 @@ fn print_item(s: ps, &&item: @ast::item) {
|
||||
print_foreign_mod(s, nmod, item.attrs);
|
||||
bclose(s, item.span);
|
||||
}
|
||||
ast::item_ty(ty, params, rp) {
|
||||
ast::item_ty(ty, params) {
|
||||
ibox(s, indent_unit);
|
||||
ibox(s, 0u);
|
||||
word_nbsp(s, "type");
|
||||
word(s.s, *item.ident);
|
||||
print_region_param(s, rp);
|
||||
print_type_params(s, params);
|
||||
end(s); // end the inner ibox
|
||||
|
||||
@ -473,7 +472,7 @@ fn print_item(s: ps, &&item: @ast::item) {
|
||||
word(s.s, ";");
|
||||
end(s); // end the outer ibox
|
||||
}
|
||||
ast::item_enum(variants, params, rp) {
|
||||
ast::item_enum(variants, params) {
|
||||
let newtype =
|
||||
vec::len(variants) == 1u &&
|
||||
str::eq(*item.ident, *variants[0].node.name) &&
|
||||
@ -483,7 +482,6 @@ fn print_item(s: ps, &&item: @ast::item) {
|
||||
word_space(s, "enum");
|
||||
} else { head(s, "enum"); }
|
||||
word(s.s, *item.ident);
|
||||
print_region_param(s, rp);
|
||||
print_type_params(s, params);
|
||||
space(s.s);
|
||||
if newtype {
|
||||
@ -506,10 +504,9 @@ fn print_item(s: ps, &&item: @ast::item) {
|
||||
bclose(s, item.span);
|
||||
}
|
||||
}
|
||||
ast::item_class(tps, traits, items, ctor, m_dtor, rp) {
|
||||
ast::item_class(tps, traits, items, ctor, m_dtor) {
|
||||
head(s, "class");
|
||||
word_nbsp(s, *item.ident);
|
||||
print_region_param(s, rp);
|
||||
print_type_params(s, tps);
|
||||
if vec::len(traits) != 0u {
|
||||
word_space(s, ":");
|
||||
@ -571,10 +568,9 @@ fn print_item(s: ps, &&item: @ast::item) {
|
||||
}
|
||||
bclose(s, item.span);
|
||||
}
|
||||
ast::item_impl(tps, rp, ifce, ty, methods) {
|
||||
ast::item_impl(tps, ifce, ty, methods) {
|
||||
head(s, "impl");
|
||||
word(s.s, *item.ident);
|
||||
print_region_param(s, rp);
|
||||
print_type_params(s, tps);
|
||||
space(s.s);
|
||||
option::iter(ifce, |p| {
|
||||
@ -591,10 +587,9 @@ fn print_item(s: ps, &&item: @ast::item) {
|
||||
}
|
||||
bclose(s, item.span);
|
||||
}
|
||||
ast::item_trait(tps, rp, methods) {
|
||||
ast::item_trait(tps, methods) {
|
||||
head(s, "iface");
|
||||
word(s.s, *item.ident);
|
||||
print_region_param(s, rp);
|
||||
print_type_params(s, tps);
|
||||
word(s.s, " ");
|
||||
bopen(s);
|
||||
@ -1406,13 +1401,6 @@ fn print_bounds(s: ps, bounds: @~[ast::ty_param_bound]) {
|
||||
}
|
||||
}
|
||||
|
||||
fn print_region_param(s: ps, rp: ast::region_param) {
|
||||
alt rp {
|
||||
ast::rp_self { word(s.s, "/&") }
|
||||
ast::rp_none { }
|
||||
}
|
||||
}
|
||||
|
||||
fn print_type_params(s: ps, &¶ms: ~[ast::ty_param]) {
|
||||
if vec::len(params) > 0u {
|
||||
word(s.s, "<");
|
||||
|
@ -61,6 +61,7 @@ type visitor<E> =
|
||||
visit_ty_params: fn@(~[ty_param], E, vt<E>),
|
||||
visit_constr: fn@(@path, span, node_id, E, vt<E>),
|
||||
visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
|
||||
visit_ty_method: fn@(ty_method, E, vt<E>),
|
||||
visit_class_item: fn@(@class_member, E, vt<E>)};
|
||||
|
||||
fn default_visitor<E>() -> visitor<E> {
|
||||
@ -79,6 +80,7 @@ fn default_visitor<E>() -> visitor<E> {
|
||||
visit_ty_params: |a,b,c|visit_ty_params::<E>(a, b, c),
|
||||
visit_constr: |a,b,c,d,e|visit_constr::<E>(a, b, c, d, e),
|
||||
visit_fn: |a,b,c,d,e,f,g|visit_fn::<E>(a, b, c, d, e, f, g),
|
||||
visit_ty_method: |a,b,c|visit_ty_method::<E>(a, b, c),
|
||||
visit_class_item: |a,b,c|visit_class_item::<E>(a, b, c)};
|
||||
}
|
||||
|
||||
@ -125,17 +127,17 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
|
||||
for nm.view_items.each |vi| { v.visit_view_item(vi, e, v); }
|
||||
for nm.items.each |ni| { v.visit_foreign_item(ni, e, v); }
|
||||
}
|
||||
item_ty(t, tps, rp) {
|
||||
item_ty(t, tps) {
|
||||
v.visit_ty(t, e, v);
|
||||
v.visit_ty_params(tps, e, v);
|
||||
}
|
||||
item_enum(variants, tps, _) {
|
||||
item_enum(variants, tps) {
|
||||
v.visit_ty_params(tps, e, v);
|
||||
for variants.each |vr| {
|
||||
for vr.node.args.each |va| { v.visit_ty(va.ty, e, v); }
|
||||
}
|
||||
}
|
||||
item_impl(tps, _rp, ifce, ty, methods) {
|
||||
item_impl(tps, ifce, ty, methods) {
|
||||
v.visit_ty_params(tps, e, v);
|
||||
option::iter(ifce, |p| visit_path(p.path, e, v));
|
||||
v.visit_ty(ty, e, v);
|
||||
@ -143,7 +145,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
|
||||
visit_method_helper(m, e, v)
|
||||
}
|
||||
}
|
||||
item_class(tps, traits, members, ctor, m_dtor, _) {
|
||||
item_class(tps, traits, members, ctor, m_dtor) {
|
||||
v.visit_ty_params(tps, e, v);
|
||||
for members.each |m| {
|
||||
v.visit_class_item(m, e, v);
|
||||
@ -155,12 +157,10 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
|
||||
visit_class_dtor_helper(dtor, tps,
|
||||
ast_util::local_def(i.id), e, v)};
|
||||
}
|
||||
item_trait(tps, _rp, methods) {
|
||||
item_trait(tps, methods) {
|
||||
v.visit_ty_params(tps, e, v);
|
||||
for methods.each |m| {
|
||||
for m.decl.inputs.each |a| { v.visit_ty(a.ty, e, v); }
|
||||
v.visit_ty_params(m.tps, e, v);
|
||||
v.visit_ty(m.decl.output, e, v);
|
||||
v.visit_ty_method(m, e, v);
|
||||
}
|
||||
}
|
||||
item_mac(m) { visit_mac(m, e, v) }
|
||||
@ -311,6 +311,12 @@ fn visit_fn<E>(fk: fn_kind, decl: fn_decl, body: blk, _sp: span,
|
||||
v.visit_block(body, e, v);
|
||||
}
|
||||
|
||||
fn visit_ty_method<E>(m: ty_method, e: E, v: vt<E>) {
|
||||
for m.decl.inputs.each |a| { v.visit_ty(a.ty, e, v); }
|
||||
v.visit_ty_params(m.tps, e, v);
|
||||
v.visit_ty(m.decl.output, e, v);
|
||||
}
|
||||
|
||||
fn visit_block<E>(b: ast::blk, e: E, v: vt<E>) {
|
||||
for b.node.view_items.each |vi| { v.visit_view_item(vi, e, v); }
|
||||
for b.node.stmts.each |s| { v.visit_stmt(s, e, v); }
|
||||
@ -458,6 +464,7 @@ type simple_visitor =
|
||||
visit_ty_params: fn@(~[ty_param]),
|
||||
visit_constr: fn@(@path, span, node_id),
|
||||
visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
|
||||
visit_ty_method: fn@(ty_method),
|
||||
visit_class_item: fn@(@class_member)};
|
||||
|
||||
fn simple_ignore_ty(_t: @ty) {}
|
||||
@ -479,6 +486,7 @@ fn default_simple_visitor() -> simple_visitor {
|
||||
visit_constr: fn@(_p: @path, _sp: span, _id: node_id) { },
|
||||
visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
|
||||
_id: node_id) { },
|
||||
visit_ty_method: fn@(_m: ty_method) { },
|
||||
visit_class_item: fn@(_c: @class_member) {}
|
||||
};
|
||||
}
|
||||
@ -534,6 +542,10 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
|
||||
f(ty);
|
||||
visit_ty(ty, e, v);
|
||||
}
|
||||
fn v_ty_method(f: fn@(ty_method), ty: ty_method, &&e: (), v: vt<()>) {
|
||||
f(ty);
|
||||
visit_ty_method(ty, e, v);
|
||||
}
|
||||
fn v_ty_params(f: fn@(~[ty_param]),
|
||||
ps: ~[ty_param],
|
||||
&&e: (), v: vt<()>) {
|
||||
@ -582,6 +594,8 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
|
||||
v_constr(v.visit_constr, a, b, c, d, e),
|
||||
visit_fn: |a,b,c,d,e,f,g|
|
||||
v_fn(v.visit_fn, a, b, c, d, e, f, g),
|
||||
visit_ty_method: |a,b,c|
|
||||
v_ty_method(v.visit_ty_method, a, b, c),
|
||||
visit_class_item: |a,b,c|
|
||||
v_class_item(v.visit_class_item, a, b, c)
|
||||
});
|
||||
|
@ -178,7 +178,11 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
|
||||
let region_map = time(time_passes, "region resolution", ||
|
||||
middle::region::resolve_crate(sess, def_map, crate));
|
||||
|
||||
let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars, region_map);
|
||||
let rp_set = time(time_passes, "region paramerization inference", ||
|
||||
middle::region::determine_rp_in_crate(sess, ast_map, def_map, crate));
|
||||
|
||||
let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
|
||||
region_map, rp_set);
|
||||
|
||||
let (method_map, vtable_map) = time(time_passes, "typechecking", ||
|
||||
typeck::check_crate(ty_cx,
|
||||
|
@ -38,6 +38,7 @@ const no_rt: uint = 256u;
|
||||
const coherence: uint = 512u;
|
||||
const borrowck_stats: uint = 1024u;
|
||||
const borrowck_note_pure: uint = 2048;
|
||||
const borrowck_note_loan: uint = 4096;
|
||||
|
||||
fn debugging_opts_map() -> ~[(str, str, uint)] {
|
||||
~[("ppregions", "prettyprint regions with \
|
||||
@ -46,7 +47,7 @@ fn debugging_opts_map() -> ~[(str, str, uint)] {
|
||||
("count-llvm-insns", "count where LLVM \
|
||||
instrs originate", count_llvm_insns),
|
||||
("time-llvm-passes", "measure time of each LLVM pass", time_llvm_passes),
|
||||
("stats", "gather trans statistics", stats),
|
||||
("trans-stats", "gather trans statistics", trans_stats),
|
||||
("no-asm-comments", "omit comments when using -S", no_asm_comments),
|
||||
("no-verify", "skip LLVM verification", no_verify),
|
||||
("trace", "emit trace logs", trace),
|
||||
@ -54,7 +55,9 @@ fn debugging_opts_map() -> ~[(str, str, uint)] {
|
||||
("coherence", "perform coherence checking", coherence),
|
||||
("borrowck-stats", "gather borrowck statistics", borrowck_stats),
|
||||
("borrowck-note-pure", "note where purity is req'd",
|
||||
borrowck_note_pure)
|
||||
borrowck_note_pure),
|
||||
("borrowck-note-loan", "note where loans are req'd",
|
||||
borrowck_note_loan)
|
||||
]
|
||||
}
|
||||
|
||||
@ -172,6 +175,7 @@ impl session for session {
|
||||
fn coherence() -> bool { self.debugging_opt(coherence) }
|
||||
fn borrowck_stats() -> bool { self.debugging_opt(borrowck_stats) }
|
||||
fn borrowck_note_pure() -> bool { self.debugging_opt(borrowck_note_pure) }
|
||||
fn borrowck_note_loan() -> bool { self.debugging_opt(borrowck_note_loan) }
|
||||
}
|
||||
|
||||
/// Some reasonable defaults
|
||||
|
@ -17,6 +17,7 @@ export get_class_fields;
|
||||
export get_class_method;
|
||||
export get_field_type;
|
||||
export get_type_param_count;
|
||||
export get_region_param;
|
||||
export lookup_defs;
|
||||
export lookup_method_purity;
|
||||
export get_enum_variants;
|
||||
@ -151,6 +152,12 @@ fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
|
||||
decoder::get_type(cdata, def.node, tcx)
|
||||
}
|
||||
|
||||
fn get_region_param(cstore: metadata::cstore::cstore,
|
||||
def: ast::def_id) -> bool {
|
||||
let cdata = cstore::get_crate_data(cstore, def.crate);
|
||||
ret decoder::get_region_param(cdata, def.node);
|
||||
}
|
||||
|
||||
fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
|
||||
def: ast::def_id) -> ty::ty_param_bounds_and_ty {
|
||||
let cstore = tcx.cstore;
|
||||
@ -168,7 +175,7 @@ fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
|
||||
class_id, def) );
|
||||
#debug("got field data %?", the_field);
|
||||
let ty = decoder::item_type(def, the_field, tcx, cdata);
|
||||
ret {bounds: @~[], rp: ast::rp_none, ty: ty};
|
||||
ret {bounds: @~[], rp: false, ty: ty};
|
||||
}
|
||||
|
||||
// Given a def_id for an impl or class, return the trait it implements,
|
||||
|
@ -21,6 +21,7 @@ export get_class_fields;
|
||||
export get_symbol;
|
||||
export get_enum_variants;
|
||||
export get_type;
|
||||
export get_region_param;
|
||||
export get_type_param_count;
|
||||
export get_impl_trait;
|
||||
export get_class_method;
|
||||
@ -185,15 +186,10 @@ fn item_ty_param_bounds(item: ebml::doc, tcx: ty::ctxt, cdata: cmd)
|
||||
@bounds
|
||||
}
|
||||
|
||||
fn item_ty_region_param(item: ebml::doc) -> ast::region_param {
|
||||
fn item_ty_region_param(item: ebml::doc) -> bool {
|
||||
alt ebml::maybe_get_doc(item, tag_region_param) {
|
||||
some(rp_doc) {
|
||||
let dsr = ebml::ebml_deserializer(rp_doc);
|
||||
ast::deserialize_region_param(dsr)
|
||||
}
|
||||
none { // not all families of items have region params
|
||||
ast::rp_none
|
||||
}
|
||||
some(_) { true }
|
||||
none { false }
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,6 +321,11 @@ fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
|
||||
ret {bounds: tp_bounds, rp: rp, ty: t};
|
||||
}
|
||||
|
||||
fn get_region_param(cdata: cmd, id: ast::node_id) -> bool {
|
||||
let item = lookup_item(id, cdata.data);
|
||||
ret item_ty_region_param(item);
|
||||
}
|
||||
|
||||
fn get_type_param_count(data: @~[u8], id: ast::node_id) -> uint {
|
||||
item_ty_param_count(lookup_item(id, data))
|
||||
}
|
||||
|
@ -86,10 +86,10 @@ fn encode_name_and_def_id(ebml_w: ebml::writer, nm: ident,
|
||||
encode_def_id(ebml_w, local_def(id));
|
||||
}
|
||||
|
||||
fn encode_region_param(ebml_w: ebml::writer, rp: region_param) {
|
||||
do ebml_w.wr_tag(tag_region_param) {
|
||||
serialize_region_param(ebml_w, rp)
|
||||
}
|
||||
fn encode_region_param(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
||||
it: @ast::item) {
|
||||
let rp = ecx.tcx.region_paramd_items.contains_key(it.id);
|
||||
if rp { do ebml_w.wr_tag(tag_region_param) { } }
|
||||
}
|
||||
|
||||
fn encode_named_def_id(ebml_w: ebml::writer, name: ident, id: def_id) {
|
||||
@ -188,12 +188,12 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
|
||||
vec::append_one(path, it.ident), index);
|
||||
}
|
||||
}
|
||||
item_ty(_, tps, _) {
|
||||
item_ty(_, tps) {
|
||||
do ebml_w.wr_tag(tag_paths_data_item) {
|
||||
encode_name_and_def_id(ebml_w, it.ident, it.id);
|
||||
}
|
||||
}
|
||||
item_class(_, _, items, ctor, m_dtor, _) {
|
||||
item_class(_, _, items, ctor, m_dtor) {
|
||||
do ebml_w.wr_tag(tag_paths_data_item) {
|
||||
encode_name_and_def_id(ebml_w, it.ident, it.id);
|
||||
}
|
||||
@ -208,7 +208,7 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
|
||||
index);
|
||||
}
|
||||
}
|
||||
item_enum(variants, _, _) {
|
||||
item_enum(variants, _) {
|
||||
do ebml_w.wr_tag(tag_paths_data_item) {
|
||||
encode_name_and_def_id(ebml_w, it.ident, it.id);
|
||||
}
|
||||
@ -406,7 +406,7 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
|
||||
ref, we need to map it to its parent class */
|
||||
ebml_w.wr_str(def_to_str(local_def(it.id)));
|
||||
}
|
||||
some(ast_map::node_item(@{node: item_impl(_,_,
|
||||
some(ast_map::node_item(@{node: item_impl(_,
|
||||
some(ifce),_,_),_},_)) {
|
||||
ebml_w.wr_str(def_to_str(did));
|
||||
}
|
||||
@ -550,7 +550,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
||||
|
||||
let tcx = ecx.tcx;
|
||||
let must_write =
|
||||
alt item.node { item_enum(_, _, _) { true } _ { false } };
|
||||
alt item.node { item_enum(_, _) { true } _ { false } };
|
||||
if !must_write && !reachable(ecx, item.id) { ret; }
|
||||
|
||||
fn add_to_index_(item: @item, ebml_w: ebml::writer,
|
||||
@ -598,7 +598,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
||||
encode_path(ebml_w, path, ast_map::path_name(item.ident));
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
item_ty(_, tps, rp) {
|
||||
item_ty(_, tps) {
|
||||
add_to_index();
|
||||
ebml_w.start_tag(tag_items_data_item);
|
||||
encode_def_id(ebml_w, local_def(item.id));
|
||||
@ -607,10 +607,10 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
||||
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
|
||||
encode_name(ebml_w, item.ident);
|
||||
encode_path(ebml_w, path, ast_map::path_name(item.ident));
|
||||
encode_region_param(ebml_w, rp);
|
||||
encode_region_param(ecx, ebml_w, item);
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
item_enum(variants, tps, rp) {
|
||||
item_enum(variants, tps) {
|
||||
add_to_index();
|
||||
do ebml_w.wr_tag(tag_items_data_item) {
|
||||
encode_def_id(ebml_w, local_def(item.id));
|
||||
@ -623,12 +623,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
||||
}
|
||||
ecx.encode_inlined_item(ecx, ebml_w, path, ii_item(item));
|
||||
encode_path(ebml_w, path, ast_map::path_name(item.ident));
|
||||
encode_region_param(ebml_w, rp);
|
||||
encode_region_param(ecx, ebml_w, item);
|
||||
}
|
||||
encode_enum_variant_info(ecx, ebml_w, item.id, variants,
|
||||
path, index, tps);
|
||||
}
|
||||
item_class(tps, traits, items, ctor, m_dtor, rp) {
|
||||
item_class(tps, traits, items, ctor, m_dtor) {
|
||||
/* First, encode the fields and methods
|
||||
These come first because we need to write them to make
|
||||
the index, and the index needs to be in the item for the
|
||||
@ -655,7 +655,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
||||
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
|
||||
encode_name(ebml_w, item.ident);
|
||||
encode_path(ebml_w, path, ast_map::path_name(item.ident));
|
||||
encode_region_param(ebml_w, rp);
|
||||
encode_region_param(ecx, ebml_w, item);
|
||||
for traits.each |t| {
|
||||
encode_trait_ref(ebml_w, ecx, t);
|
||||
}
|
||||
@ -704,12 +704,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
||||
encode_index(ebml_w, bkts, write_int);
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
item_impl(tps, rp, ifce, _, methods) {
|
||||
item_impl(tps, ifce, _, methods) {
|
||||
add_to_index();
|
||||
ebml_w.start_tag(tag_items_data_item);
|
||||
encode_def_id(ebml_w, local_def(item.id));
|
||||
encode_family(ebml_w, 'i');
|
||||
encode_region_param(ebml_w, rp);
|
||||
encode_region_param(ecx, ebml_w, item);
|
||||
encode_type_param_bounds(ebml_w, ecx, tps);
|
||||
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
|
||||
encode_name(ebml_w, item.ident);
|
||||
@ -733,12 +733,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
||||
vec::append(tps, m.tps));
|
||||
}
|
||||
}
|
||||
item_trait(tps, rp, ms) {
|
||||
item_trait(tps, ms) {
|
||||
add_to_index();
|
||||
ebml_w.start_tag(tag_items_data_item);
|
||||
encode_def_id(ebml_w, local_def(item.id));
|
||||
encode_family(ebml_w, 'I');
|
||||
encode_region_param(ebml_w, rp);
|
||||
encode_region_param(ecx, ebml_w, item);
|
||||
encode_type_param_bounds(ebml_w, ecx, tps);
|
||||
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
|
||||
encode_name(ebml_w, item.ident);
|
||||
@ -801,7 +801,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
||||
encode_info_for_item(ecx, ebml_w, i, index, *pt);
|
||||
/* encode ctor, then encode items */
|
||||
alt i.node {
|
||||
item_class(tps, _, _, ctor, m_dtor, _) {
|
||||
item_class(tps, _, _, ctor, m_dtor) {
|
||||
#debug("encoding info for ctor %s %d", *i.ident,
|
||||
ctor.node.id);
|
||||
vec::push(*index,
|
||||
|
@ -554,11 +554,11 @@ impl helpers for ebml::writer {
|
||||
do self.emit_rec {
|
||||
do self.emit_rec_field("bounds", 0u) {
|
||||
do self.emit_from_vec(*tpbt.bounds) |bs| {
|
||||
self.emit_bounds(ecx, bs)
|
||||
self.emit_bounds(ecx, bs);
|
||||
}
|
||||
}
|
||||
do self.emit_rec_field("rp", 1u) {
|
||||
ast::serialize_region_param(self, tpbt.rp)
|
||||
self.emit_bool(tpbt.rp);
|
||||
}
|
||||
do self.emit_rec_field("ty", 2u) {
|
||||
self.emit_ty(ecx, tpbt.ty);
|
||||
@ -759,7 +759,7 @@ impl decoder for ebml::ebml_deserializer {
|
||||
@self.read_to_vec(|| self.read_bounds(xcx) )
|
||||
}),
|
||||
rp: self.read_rec_field("rp", 1u, || {
|
||||
ast::deserialize_region_param(self)
|
||||
self.read_bool()
|
||||
}),
|
||||
ty: self.read_rec_field("ty", 2u, || {
|
||||
self.read_ty(xcx)
|
||||
|
@ -199,6 +199,12 @@ impl methods for gather_loan_ctxt {
|
||||
|
||||
if req_mutbl == m_imm && cmt.mutbl != m_imm {
|
||||
self.bccx.loaned_paths_imm += 1;
|
||||
|
||||
if self.tcx().sess.borrowck_note_loan() {
|
||||
self.bccx.span_note(
|
||||
cmt.span,
|
||||
#fmt["immutable loan required"]);
|
||||
}
|
||||
} else {
|
||||
self.bccx.loaned_paths_same += 1;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ fn check_item(sess: session, ast_map: ast_map::map, def_map: resolve::def_map,
|
||||
v.visit_expr(ex, true, v);
|
||||
check_item_recursion(sess, ast_map, def_map, it);
|
||||
}
|
||||
item_enum(vs, _, _) {
|
||||
item_enum(vs, _) {
|
||||
for vs.each |var| {
|
||||
do option::iter(var.node.disr_expr) |ex| {
|
||||
v.visit_expr(ex, true, v);
|
||||
|
@ -138,11 +138,13 @@ import syntax::{ast, visit};
|
||||
import syntax::codemap::span;
|
||||
import syntax::print::pprust;
|
||||
import syntax::ast_util::new_def_hash;
|
||||
import syntax::ast_map;
|
||||
import dvec::{dvec, extensions};
|
||||
import metadata::csearch;
|
||||
|
||||
import std::list;
|
||||
import std::list::list;
|
||||
import std::map;
|
||||
import std::map::hashmap;
|
||||
import std::map::{hashmap, int_hash};
|
||||
|
||||
type parent = option<ast::node_id>;
|
||||
|
||||
@ -386,7 +388,7 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
|
||||
-> region_map {
|
||||
let cx: ctxt = {sess: sess,
|
||||
def_map: def_map,
|
||||
region_map: map::int_hash(),
|
||||
region_map: int_hash(),
|
||||
parent: none};
|
||||
let visitor = visit::mk_vt(@{
|
||||
visit_block: resolve_block,
|
||||
@ -402,3 +404,208 @@ fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
|
||||
ret cx.region_map;
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Determining region parameterization
|
||||
//
|
||||
// Infers which type defns must be region parameterized---this is done
|
||||
// by scanning their contents to see whether they reference a region
|
||||
// type, directly or indirectly. This is a fixed-point computation.
|
||||
//
|
||||
// We do it in two passes. First we walk the AST and construct a map
|
||||
// from each type defn T1 to other defns which make use of it. For example,
|
||||
// if we have a type like:
|
||||
//
|
||||
// type S = *int;
|
||||
// type T = S;
|
||||
//
|
||||
// Then there would be a map entry from S to T. During the same walk,
|
||||
// we also construct add any types that reference regions to a set and
|
||||
// a worklist. We can then process the worklist, propagating indirect
|
||||
// dependencies until a fixed point is reached.
|
||||
|
||||
type region_paramd_items = hashmap<ast::node_id, ()>;
|
||||
type dep_map = hashmap<ast::node_id, @dvec<ast::node_id>>;
|
||||
|
||||
type determine_rp_ctxt = @{
|
||||
sess: session,
|
||||
ast_map: ast_map::map,
|
||||
def_map: resolve::def_map,
|
||||
region_paramd_items: region_paramd_items,
|
||||
dep_map: dep_map,
|
||||
worklist: dvec<ast::node_id>,
|
||||
|
||||
mut item_id: ast::node_id,
|
||||
mut anon_implies_rp: bool
|
||||
};
|
||||
|
||||
impl methods for determine_rp_ctxt {
|
||||
fn add_rp(id: ast::node_id) {
|
||||
assert id != 0;
|
||||
if self.region_paramd_items.insert(id, ()) {
|
||||
#debug["add region-parameterized item: %d (%s)",
|
||||
id, ast_map::node_id_to_str(self.ast_map, id)];
|
||||
self.worklist.push(id);
|
||||
} else {
|
||||
#debug["item %d already region-parameterized", id];
|
||||
}
|
||||
}
|
||||
|
||||
fn add_dep(from: ast::node_id, to: ast::node_id) {
|
||||
#debug["add dependency from %d -> %d (%s -> %s)",
|
||||
from, to,
|
||||
ast_map::node_id_to_str(self.ast_map, from),
|
||||
ast_map::node_id_to_str(self.ast_map, to)];
|
||||
let vec = alt self.dep_map.find(from) {
|
||||
some(vec) => {vec}
|
||||
none => {
|
||||
let vec = @dvec();
|
||||
self.dep_map.insert(from, vec);
|
||||
vec
|
||||
}
|
||||
};
|
||||
if !vec.contains(to) { vec.push(to); }
|
||||
}
|
||||
|
||||
fn region_is_relevant(r: @ast::region) -> bool {
|
||||
alt r.node {
|
||||
ast::re_anon {self.anon_implies_rp}
|
||||
ast::re_named(@"self") {true}
|
||||
ast::re_named(_) {false}
|
||||
}
|
||||
}
|
||||
|
||||
fn with(item_id: ast::node_id, anon_implies_rp: bool, f: fn()) {
|
||||
let old_item_id = self.item_id;
|
||||
let old_anon_implies_rp = self.anon_implies_rp;
|
||||
self.item_id = item_id;
|
||||
self.anon_implies_rp = anon_implies_rp;
|
||||
#debug["with_item_id(%d, %b)", item_id, anon_implies_rp];
|
||||
let _i = util::common::indenter();
|
||||
f();
|
||||
self.item_id = old_item_id;
|
||||
self.anon_implies_rp = old_anon_implies_rp;
|
||||
}
|
||||
}
|
||||
|
||||
fn determine_rp_in_item(item: @ast::item,
|
||||
&&cx: determine_rp_ctxt,
|
||||
visitor: visit::vt<determine_rp_ctxt>) {
|
||||
do cx.with(item.id, true) {
|
||||
visit::visit_item(item, cx, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
fn determine_rp_in_fn(fk: visit::fn_kind,
|
||||
decl: ast::fn_decl,
|
||||
body: ast::blk,
|
||||
sp: span,
|
||||
id: ast::node_id,
|
||||
&&cx: determine_rp_ctxt,
|
||||
visitor: visit::vt<determine_rp_ctxt>) {
|
||||
do cx.with(cx.item_id, false) {
|
||||
visit::visit_fn(fk, decl, body, sp, id, cx, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
fn determine_rp_in_ty_method(ty_m: ast::ty_method,
|
||||
&&cx: determine_rp_ctxt,
|
||||
visitor: visit::vt<determine_rp_ctxt>) {
|
||||
do cx.with(cx.item_id, false) {
|
||||
visit::visit_ty_method(ty_m, cx, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
fn determine_rp_in_ty(ty: @ast::ty,
|
||||
&&cx: determine_rp_ctxt,
|
||||
visitor: visit::vt<determine_rp_ctxt>) {
|
||||
|
||||
// we are only interesting in types that will require an item to
|
||||
// be region-parameterized. if cx.item_id is zero, then this type
|
||||
// is not a member of a type defn nor is it a constitutent of an
|
||||
// impl etc. So we can ignore it and its components.
|
||||
if cx.item_id == 0 { ret; }
|
||||
|
||||
// if this type directly references a region, either via a
|
||||
// region pointer like &r.ty or a region-parameterized path
|
||||
// like path/r, add to the worklist/set
|
||||
alt ty.node {
|
||||
ast::ty_rptr(r, _) |
|
||||
ast::ty_path(@{rp: some(r), _}, _) |
|
||||
ast::ty_vstore(_, ast::vstore_slice(r)) => {
|
||||
#debug["referenced type with regions %s", pprust::ty_to_str(ty)];
|
||||
if cx.region_is_relevant(r) {
|
||||
cx.add_rp(cx.item_id);
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// if this references another named type, add the dependency
|
||||
// to the dep_map. If the type is not defined in this crate,
|
||||
// then check whether it is region-parameterized and consider
|
||||
// that as a direct dependency.
|
||||
alt ty.node {
|
||||
ast::ty_path(_, id) {
|
||||
alt cx.def_map.get(id) {
|
||||
ast::def_ty(did) | ast::def_class(did) {
|
||||
if did.crate == ast::local_crate {
|
||||
cx.add_dep(did.node, cx.item_id);
|
||||
} else {
|
||||
let cstore = cx.sess.cstore;
|
||||
if csearch::get_region_param(cstore, did) {
|
||||
#debug["reference to external, rp'd type %s",
|
||||
pprust::ty_to_str(ty)];
|
||||
cx.add_rp(cx.item_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
|
||||
visit::visit_ty(ty, cx, visitor);
|
||||
}
|
||||
|
||||
fn determine_rp_in_crate(sess: session,
|
||||
ast_map: ast_map::map,
|
||||
def_map: resolve::def_map,
|
||||
crate: @ast::crate) -> region_paramd_items {
|
||||
let cx = @{sess: sess,
|
||||
ast_map: ast_map,
|
||||
def_map: def_map,
|
||||
region_paramd_items: int_hash(),
|
||||
dep_map: int_hash(),
|
||||
worklist: dvec(),
|
||||
mut item_id: 0,
|
||||
mut anon_implies_rp: false};
|
||||
|
||||
// gather up the base set, worklist and dep_map:
|
||||
let visitor = visit::mk_vt(@{
|
||||
visit_fn: determine_rp_in_fn,
|
||||
visit_item: determine_rp_in_item,
|
||||
visit_ty: determine_rp_in_ty,
|
||||
visit_ty_method: determine_rp_in_ty_method,
|
||||
with *visit::default_visitor()
|
||||
});
|
||||
visit::visit_crate(*crate, cx, visitor);
|
||||
|
||||
// propagate indirect dependencies
|
||||
while cx.worklist.len() != 0 {
|
||||
let id = cx.worklist.pop();
|
||||
#debug["popped %d from worklist", id];
|
||||
alt cx.dep_map.find(id) {
|
||||
none {}
|
||||
some(vec) {
|
||||
for vec.each |to_id| {
|
||||
cx.add_rp(to_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return final set
|
||||
ret cx.region_paramd_items;
|
||||
}
|
@ -439,10 +439,10 @@ fn resolve_names(e: @env, c: @ast::crate) {
|
||||
/* At this point, the code knows what traits the trait refs
|
||||
refer to, so it's possible to resolve them.
|
||||
*/
|
||||
ast::item_impl(_, _, ifce, _, _) {
|
||||
ast::item_impl(_, ifce, _, _) {
|
||||
ifce.iter(|p| resolve_trait_ref(p, sc, e))
|
||||
}
|
||||
ast::item_class(_, traits, _, _, _, _) {
|
||||
ast::item_class(_, traits, _, _, _) {
|
||||
for traits.each |p| {
|
||||
resolve_trait_ref(p, sc, e);
|
||||
}
|
||||
@ -552,7 +552,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
|
||||
|
||||
let sc = @cons(scope_item(i), sc);
|
||||
alt i.node {
|
||||
ast::item_impl(tps, _, ifce, sty, methods) {
|
||||
ast::item_impl(tps, ifce, sty, methods) {
|
||||
v.visit_ty_params(tps, sc, v);
|
||||
option::iter(ifce, |p| visit::visit_path(p.path, sc, v));
|
||||
v.visit_ty(sty, sc, v);
|
||||
@ -564,7 +564,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
|
||||
m.decl, m.body, m.span, m.id, msc, v);
|
||||
}
|
||||
}
|
||||
ast::item_trait(tps, _, methods) {
|
||||
ast::item_trait(tps, methods) {
|
||||
v.visit_ty_params(tps, sc, v);
|
||||
let isc = @cons(scope_method(i.id, tps), sc);
|
||||
for methods.each |m| {
|
||||
@ -574,7 +574,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
|
||||
v.visit_ty(m.decl.output, msc, v);
|
||||
}
|
||||
}
|
||||
ast::item_class(tps, traits, members, ctor, m_dtor, _) {
|
||||
ast::item_class(tps, traits, members, ctor, m_dtor) {
|
||||
v.visit_ty_params(tps, sc, v);
|
||||
let class_scope = @cons(scope_item(i), sc);
|
||||
/* visit the constructor... */
|
||||
@ -1042,13 +1042,13 @@ fn lookup_in_scope(e: env, &&sc: scopes, sp: span, name: ident, ns: namespace,
|
||||
}
|
||||
scope_item(it) {
|
||||
alt it.node {
|
||||
ast::item_impl(tps, _, _, _, _) {
|
||||
ast::item_impl(tps, _, _, _) {
|
||||
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
|
||||
}
|
||||
ast::item_enum(_, tps, _) | ast::item_ty(_, tps, _) {
|
||||
ast::item_enum(_, tps) | ast::item_ty(_, tps) {
|
||||
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
|
||||
}
|
||||
ast::item_trait(tps, _, _) {
|
||||
ast::item_trait(tps, _) {
|
||||
if ns == ns_type {
|
||||
if *name == "self" {
|
||||
ret some(def_self(it.id));
|
||||
@ -1062,7 +1062,7 @@ fn lookup_in_scope(e: env, &&sc: scopes, sp: span, name: ident, ns: namespace,
|
||||
ast::item_foreign_mod(m) {
|
||||
ret lookup_in_local_foreign_mod(e, it.id, sp, name, ns);
|
||||
}
|
||||
ast::item_class(tps, _, members, ctor, _, _) {
|
||||
ast::item_class(tps, _, members, ctor, _) {
|
||||
if ns == ns_type {
|
||||
ret lookup_in_ty_params(e, name, tps);
|
||||
}
|
||||
@ -1234,7 +1234,7 @@ fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint,
|
||||
}
|
||||
ast::decl_item(it) {
|
||||
alt it.node {
|
||||
ast::item_enum(variants, _, _) {
|
||||
ast::item_enum(variants, _) {
|
||||
if ns == ns_type {
|
||||
if str::eq(*it.ident, *name) {
|
||||
ret some(ast::def_ty(local_def(it.id)));
|
||||
@ -1339,7 +1339,7 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
|
||||
ast::item_ty(*) | item_trait(*) | item_enum(*) {
|
||||
if ns == ns_type { ret some(ast::def_ty(local_def(i.id))); }
|
||||
}
|
||||
ast::item_class(_, _, _members, ct, _, _) {
|
||||
ast::item_class(_, _, _members, ct, _) {
|
||||
alt ns {
|
||||
ns_type {
|
||||
ret some(ast::def_class(local_def(i.id)));
|
||||
@ -1641,11 +1641,11 @@ fn index_mod(md: ast::_mod) -> mod_index {
|
||||
for md.items.each |it| {
|
||||
alt it.node {
|
||||
ast::item_const(_, _) | ast::item_fn(_, _, _) | ast::item_mod(_) |
|
||||
ast::item_foreign_mod(_) | ast::item_ty(_, _, _) |
|
||||
ast::item_foreign_mod(_) | ast::item_ty(_, _) |
|
||||
ast::item_impl(*) | ast::item_trait(*) {
|
||||
add_to_index(index, it.ident, mie_item(it));
|
||||
}
|
||||
ast::item_enum(variants, _, _) {
|
||||
ast::item_enum(variants, _) {
|
||||
add_to_index(index, it.ident, mie_item(it));
|
||||
let mut variant_idx: uint = 0u;
|
||||
for variants.each |v| {
|
||||
@ -1655,7 +1655,7 @@ fn index_mod(md: ast::_mod) -> mod_index {
|
||||
variant_idx += 1u;
|
||||
}
|
||||
}
|
||||
ast::item_class(tps, _, items, ctor, _, _) {
|
||||
ast::item_class(tps, _, items, ctor, _) {
|
||||
// add the class name itself
|
||||
add_to_index(index, it.ident, mie_item(it));
|
||||
}
|
||||
@ -1780,15 +1780,15 @@ fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) {
|
||||
ensure_unique(*e, i.span, ty_params, |tp| tp.ident,
|
||||
"type parameter");
|
||||
}
|
||||
ast::item_enum(_, ty_params, _) {
|
||||
ast::item_enum(_, ty_params) {
|
||||
ensure_unique(*e, i.span, ty_params, |tp| tp.ident,
|
||||
"type parameter");
|
||||
}
|
||||
ast::item_trait(_, _, methods) {
|
||||
ast::item_trait(_, methods) {
|
||||
ensure_unique(*e, i.span, methods, |m| m.ident,
|
||||
"method");
|
||||
}
|
||||
ast::item_impl(_, _, _, _, methods) {
|
||||
ast::item_impl(_, _, _, methods) {
|
||||
ensure_unique(*e, i.span, methods, |m| m.ident,
|
||||
"method");
|
||||
}
|
||||
@ -1854,7 +1854,7 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
|
||||
}
|
||||
ast::decl_item(it) {
|
||||
alt it.node {
|
||||
ast::item_enum(variants, _, _) {
|
||||
ast::item_enum(variants, _) {
|
||||
add_name(types, it.span, it.ident);
|
||||
for variants.each |v| {
|
||||
add_name(values, v.span, v.node.name);
|
||||
@ -2051,7 +2051,7 @@ fn check_exports(e: @env) {
|
||||
some(ms) {
|
||||
let maybe_id = do list_search(ms) |m| {
|
||||
alt m {
|
||||
mie_item(@{node: item_enum(_, _, _), id, _}) { some(id) }
|
||||
mie_item(@{node: item_enum(_, _), id, _}) { some(id) }
|
||||
_ { none }
|
||||
}
|
||||
};
|
||||
@ -2242,7 +2242,7 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: ~[@_impl],
|
||||
name: option<ident>,
|
||||
ck_exports: option<@indexed_mod>) {
|
||||
alt i.node {
|
||||
ast::item_impl(_, _, ifce, _, mthds) {
|
||||
ast::item_impl(_, ifce, _, mthds) {
|
||||
if alt name { some(n) { n == i.ident } _ { true } } &&
|
||||
alt ck_exports {
|
||||
some(m) { is_exported(e, i.ident, m) }
|
||||
@ -2257,7 +2257,7 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: ~[@_impl],
|
||||
})});
|
||||
}
|
||||
}
|
||||
ast::item_class(tps, ifces, items, _, _, _) {
|
||||
ast::item_class(tps, ifces, items, _, _) {
|
||||
let (_, mthds) = ast_util::split_class_items(items);
|
||||
let n_tps = tps.len();
|
||||
do vec::iter(ifces) |p| {
|
||||
|
@ -847,7 +847,7 @@ class Resolver {
|
||||
}
|
||||
|
||||
// These items live in both the type and value namespaces.
|
||||
item_enum(variants, _, _) {
|
||||
item_enum(variants, _) {
|
||||
(*name_bindings).define_type(def_ty(local_def(item.id)));
|
||||
|
||||
for variants.each |variant| {
|
||||
@ -857,7 +857,7 @@ class Resolver {
|
||||
visitor);
|
||||
}
|
||||
}
|
||||
item_class(_, _, class_members, ctor, _, _) {
|
||||
item_class(_, _, class_members, ctor, _) {
|
||||
(*name_bindings).define_type(def_ty(local_def(item.id)));
|
||||
|
||||
let purity = ctor.node.dec.purity;
|
||||
@ -899,7 +899,7 @@ class Resolver {
|
||||
visit_item(item, new_parent, visitor);
|
||||
}
|
||||
|
||||
item_impl(_, _, _, _, methods) {
|
||||
item_impl(_, _, _, methods) {
|
||||
// Create the set of implementation information that the
|
||||
// implementation scopes (ImplScopes) need and write it into
|
||||
// the implementation definition list for this set of name
|
||||
@ -2884,8 +2884,8 @@ class Resolver {
|
||||
}
|
||||
|
||||
alt item.node {
|
||||
item_enum(_, type_parameters, _) |
|
||||
item_ty(_, type_parameters, _) {
|
||||
item_enum(_, type_parameters) |
|
||||
item_ty(_, type_parameters) {
|
||||
do self.with_type_parameter_rib
|
||||
(HasTypeParameters(&type_parameters, item.id, 0u,
|
||||
NormalRibKind))
|
||||
@ -2895,7 +2895,7 @@ class Resolver {
|
||||
}
|
||||
}
|
||||
|
||||
item_impl(type_parameters, _, interface_reference, self_type,
|
||||
item_impl(type_parameters, interface_reference, self_type,
|
||||
methods) {
|
||||
self.resolve_implementation(item.id,
|
||||
item.span,
|
||||
@ -2906,7 +2906,7 @@ class Resolver {
|
||||
visitor);
|
||||
}
|
||||
|
||||
item_trait(type_parameters, _, methods) {
|
||||
item_trait(type_parameters, methods) {
|
||||
// Create a new rib for the self type.
|
||||
let self_type_rib = @Rib(NormalRibKind);
|
||||
(*self.type_ribs).push(self_type_rib);
|
||||
@ -2948,7 +2948,7 @@ class Resolver {
|
||||
}
|
||||
|
||||
item_class(ty_params, interfaces, class_members, constructor,
|
||||
optional_destructor, _) {
|
||||
optional_destructor) {
|
||||
|
||||
self.resolve_class(item.id,
|
||||
@copy ty_params,
|
||||
|
@ -2291,7 +2291,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
|
||||
ccx.external.insert(parent_id, some(item.id));
|
||||
let mut my_id = 0;
|
||||
alt check item.node {
|
||||
ast::item_enum(_, _, _) {
|
||||
ast::item_enum(_, _) {
|
||||
let vs_here = ty::enum_variants(ccx.tcx, local_def(item.id));
|
||||
let vs_there = ty::enum_variants(ccx.tcx, parent_id);
|
||||
do vec::iter2(*vs_here, *vs_there) |here, there| {
|
||||
@ -4886,13 +4886,13 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::item_impl(tps, _rp, _, _, ms) {
|
||||
ast::item_impl(tps, _, _, ms) {
|
||||
impl::trans_impl(ccx, *path, item.ident, ms, tps);
|
||||
}
|
||||
ast::item_mod(m) {
|
||||
trans_mod(ccx, m);
|
||||
}
|
||||
ast::item_enum(variants, tps, _) {
|
||||
ast::item_enum(variants, tps) {
|
||||
if tps.len() == 0u {
|
||||
let degen = variants.len() == 1u;
|
||||
let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
|
||||
@ -4916,7 +4916,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
|
||||
};
|
||||
foreign::trans_foreign_mod(ccx, foreign_mod, abi);
|
||||
}
|
||||
ast::item_class(tps, _traits, items, ctor, m_dtor, _) {
|
||||
ast::item_class(tps, _traits, items, ctor, m_dtor) {
|
||||
if tps.len() == 0u {
|
||||
let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps),
|
||||
vtables: none,
|
||||
@ -5199,7 +5199,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
|
||||
~[path_name(enm.ident),
|
||||
path_name(v.node.name)]);
|
||||
let llfn = alt check enm.node {
|
||||
ast::item_enum(_, _, _) {
|
||||
ast::item_enum(_, _) {
|
||||
register_fn(ccx, v.span, pth, id)
|
||||
}
|
||||
};
|
||||
@ -5220,7 +5220,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
|
||||
fn trans_constant(ccx: @crate_ctxt, it: @ast::item) {
|
||||
let _icx = ccx.insn_ctxt("trans_constant");
|
||||
alt it.node {
|
||||
ast::item_enum(variants, _, _) {
|
||||
ast::item_enum(variants, _) {
|
||||
let vi = ty::enum_variants(ccx.tcx, {crate: ast::local_crate,
|
||||
node: it.id});
|
||||
let mut i = 0;
|
||||
|
@ -84,11 +84,11 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
|
||||
name: ast::ident) -> ast::def_id {
|
||||
if impl_id.crate == ast::local_crate {
|
||||
alt check ccx.tcx.items.get(impl_id.node) {
|
||||
ast_map::node_item(@{node: ast::item_impl(_, _, _, _, ms), _}, _) {
|
||||
ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) {
|
||||
method_from_methods(ms, name)
|
||||
}
|
||||
ast_map::node_item(@{node:
|
||||
ast::item_class(_, _, items, _, _, _), _}, _) {
|
||||
ast::item_class(_, _, items, _, _), _}, _) {
|
||||
let (_,ms) = split_class_items(items);
|
||||
method_from_methods(ms, name)
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
|
||||
traverse_inline_body(cx, blk);
|
||||
}
|
||||
}
|
||||
item_impl(tps, _, _, _, ms) {
|
||||
item_impl(tps, _, _, ms) {
|
||||
for vec::each(ms) |m| {
|
||||
if tps.len() > 0u || m.tps.len() > 0u ||
|
||||
attr::find_inline_attr(m.attrs) != attr::ia_none {
|
||||
@ -121,7 +121,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
|
||||
}
|
||||
}
|
||||
}
|
||||
item_class(tps, _traits, items, ctor, m_dtor, _) {
|
||||
item_class(tps, _traits, items, ctor, m_dtor) {
|
||||
cx.rmap.insert(ctor.node.id, ());
|
||||
do option::iter(m_dtor) |dtor| {
|
||||
cx.rmap.insert(dtor.node.id, ());
|
||||
@ -143,7 +143,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
|
||||
}
|
||||
}
|
||||
}
|
||||
item_ty(t, _, _) {
|
||||
item_ty(t, _) {
|
||||
traverse_ty(t, cx, mk_ty_visitor());
|
||||
}
|
||||
item_const(*) |
|
||||
@ -218,7 +218,7 @@ fn traverse_all_resources(cx: ctx, crate_mod: _mod) {
|
||||
visit_item: |i, cx, v| {
|
||||
visit::visit_item(i, cx, v);
|
||||
alt i.node {
|
||||
item_class(_, _, _, _, some(_), _) {
|
||||
item_class(_, _, _, _, some(_)) {
|
||||
traverse_public_item(cx, i);
|
||||
}
|
||||
_ {}
|
||||
|
@ -52,7 +52,7 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
|
||||
item_class(*) {
|
||||
fail "find_pre_post_item: shouldn't be called on item_class";
|
||||
}
|
||||
item_impl(_, _, _, _, ms) {
|
||||
item_impl(_, _, _, ms) {
|
||||
for ms.each |m| { find_pre_post_method(ccx, m); }
|
||||
}
|
||||
item_mac(*) { fail "item macros unimplemented" }
|
||||
|
@ -233,7 +233,9 @@ type ctxt =
|
||||
cstore: metadata::cstore::cstore,
|
||||
sess: session::session,
|
||||
def_map: resolve::def_map,
|
||||
|
||||
region_map: middle::region::region_map,
|
||||
region_paramd_items: middle::region::region_paramd_items,
|
||||
|
||||
// Stores the types for various nodes in the AST. Note that this table
|
||||
// is not guaranteed to be populated until after typeck. See
|
||||
@ -482,7 +484,7 @@ fn param_bounds_to_kind(bounds: param_bounds) -> kind {
|
||||
}
|
||||
|
||||
type ty_param_bounds_and_ty = {bounds: @~[param_bounds],
|
||||
rp: ast::region_param,
|
||||
rp: bool,
|
||||
ty: t};
|
||||
|
||||
type type_cache = hashmap<ast::def_id, ty_param_bounds_and_ty>;
|
||||
@ -505,9 +507,12 @@ fn new_ty_hash<V: copy>() -> map::hashmap<t, V> {
|
||||
|&&a: t, &&b: t| type_id(a) == type_id(b))
|
||||
}
|
||||
|
||||
fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
|
||||
fn mk_ctxt(s: session::session,
|
||||
dm: resolve::def_map,
|
||||
amap: ast_map::map,
|
||||
freevars: freevars::freevar_map,
|
||||
region_map: middle::region::region_map) -> ctxt {
|
||||
region_map: middle::region::region_map,
|
||||
region_paramd_items: middle::region::region_paramd_items) -> ctxt {
|
||||
let interner = map::hashmap(|&&k: intern_key| {
|
||||
hash_type_structure(k.struct) +
|
||||
option::map_default(k.o_def_id, 0u, ast_util::hash_def)
|
||||
@ -523,6 +528,7 @@ fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
|
||||
sess: s,
|
||||
def_map: dm,
|
||||
region_map: region_map,
|
||||
region_paramd_items: region_paramd_items,
|
||||
node_types: @smallintmap::mk(),
|
||||
node_type_substs: map::int_hash(),
|
||||
items: amap,
|
||||
@ -2543,10 +2549,10 @@ fn impl_trait(cx: ctxt, id: ast::def_id) -> option<t> {
|
||||
#debug("(impl_trait) searching for trait impl %?", id);
|
||||
alt cx.items.find(id.node) {
|
||||
some(ast_map::node_item(@{node: ast::item_impl(
|
||||
_, _, some(@{id: id, _}), _, _), _}, _)) {
|
||||
_, some(@{id: id, _}), _, _), _}, _)) {
|
||||
some(node_id_to_type(cx, id))
|
||||
}
|
||||
some(ast_map::node_item(@{node: ast::item_class(_, _, _, _, _, _),
|
||||
some(ast_map::node_item(@{node: ast::item_class(*),
|
||||
_},_)) {
|
||||
alt cx.def_map.find(id.node) {
|
||||
some(def_ty(trait_id)) {
|
||||
@ -2606,7 +2612,7 @@ fn ty_dtor(cx: ctxt, class_id: def_id) -> option<def_id> {
|
||||
if is_local(class_id) {
|
||||
alt cx.items.find(class_id.node) {
|
||||
some(ast_map::node_item(@{node: ast::item_class(_, _, _, _,
|
||||
some(dtor), _), _}, _))
|
||||
some(dtor)), _}, _))
|
||||
{ some(local_def(dtor.node.id)) }
|
||||
_ { none }
|
||||
}
|
||||
@ -2687,7 +2693,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[variant_info] {
|
||||
expr, since check_enum_variants also updates the enum_var_cache
|
||||
*/
|
||||
alt cx.items.get(id.node) {
|
||||
ast_map::node_item(@{node: ast::item_enum(variants, _, _), _}, _) {
|
||||
ast_map::node_item(@{node: ast::item_enum(variants, _), _}, _) {
|
||||
let mut disr_val = -1;
|
||||
@vec::map(variants, |variant| {
|
||||
let ctor_ty = node_id_to_type(cx, variant.node.id);
|
||||
@ -2780,7 +2786,7 @@ fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
|
||||
alt cx.items.find(did.node) {
|
||||
some(ast_map::node_item(i,_)) {
|
||||
alt i.node {
|
||||
ast::item_class(_, _, items, _, _, _) {
|
||||
ast::item_class(_, _, items, _, _) {
|
||||
class_field_tys(items)
|
||||
}
|
||||
_ { cx.sess.bug("class ID bound to non-class"); }
|
||||
@ -2822,7 +2828,7 @@ pure fn is_public(f: field_ty) -> bool {
|
||||
fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
|
||||
: is_local(did) -> ~[{name: ident, id: node_id, vis: visibility}] {
|
||||
alt cx.items.find(did.node) {
|
||||
some(ast_map::node_item(@{node: item_class(_,_,items,_,_,_), _}, _)) {
|
||||
some(ast_map::node_item(@{node: item_class(_,_,items,_,_), _}, _)) {
|
||||
let (_,ms) = split_class_items(items);
|
||||
vec::map(ms, |m| {name: m.ident, id: m.id,
|
||||
vis: m.vis})
|
||||
|
@ -185,7 +185,7 @@ fn lookup_def_ccx(ccx: @crate_ctxt, sp: span, id: ast::node_id) -> ast::def {
|
||||
}
|
||||
|
||||
fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty {
|
||||
{bounds: @~[], rp: ast::rp_none, ty: t}
|
||||
{bounds: @~[], rp: false, ty: t}
|
||||
}
|
||||
|
||||
fn require_same_types(
|
||||
|
@ -87,14 +87,17 @@ fn ast_path_to_substs_and_ty<AC: ast_conv, RS: region_scope copy>(
|
||||
let {bounds: decl_bounds, rp: decl_rp, ty: decl_ty} =
|
||||
self.get_item_ty(did);
|
||||
|
||||
#debug["ast_path_to_substs_and_ty: did=%? decl_rp=%b",
|
||||
did, decl_rp];
|
||||
|
||||
// If the type is parameterized by the self region, then replace self
|
||||
// region with the current anon region binding (in other words,
|
||||
// whatever & would get replaced with).
|
||||
let self_r = alt (decl_rp, path.rp) {
|
||||
(ast::rp_none, none) {
|
||||
(false, none) {
|
||||
none
|
||||
}
|
||||
(ast::rp_none, some(_)) {
|
||||
(false, some(_)) {
|
||||
tcx.sess.span_err(
|
||||
path.span,
|
||||
#fmt["no region bound is permitted on %s, \
|
||||
@ -102,12 +105,12 @@ fn ast_path_to_substs_and_ty<AC: ast_conv, RS: region_scope copy>(
|
||||
ty::item_path_str(tcx, did)]);
|
||||
none
|
||||
}
|
||||
(ast::rp_self, none) {
|
||||
(true, none) {
|
||||
let res = rscope.anon_region();
|
||||
let r = get_region_reporting_err(self.tcx(), path.span, res);
|
||||
some(r)
|
||||
}
|
||||
(ast::rp_self, some(r)) {
|
||||
(true, some(r)) {
|
||||
some(ast_region_to_region(self, rscope, path.span, r))
|
||||
}
|
||||
};
|
||||
|
@ -66,7 +66,7 @@ type parameter).
|
||||
|
||||
*/
|
||||
|
||||
import astconv::{ast_conv, ast_ty_to_ty};
|
||||
import astconv::{ast_conv, ast_ty_to_ty, ast_region_to_region};
|
||||
import collect::{methods}; // ccx.to_ty()
|
||||
import middle::ty::{tv_vid, vid};
|
||||
import regionmanip::{replace_bound_regions_in_fn_ty, region_of};
|
||||
@ -348,17 +348,20 @@ fn check_class_member(ccx: @crate_ctxt, class_t: ty::t,
|
||||
fn check_item(ccx: @crate_ctxt, it: @ast::item) {
|
||||
alt it.node {
|
||||
ast::item_const(_, e) { check_const(ccx, it.span, e, it.id); }
|
||||
ast::item_enum(vs, _, _) {
|
||||
ast::item_enum(vs, _) {
|
||||
check_enum_variants(ccx, it.span, vs, it.id);
|
||||
}
|
||||
ast::item_fn(decl, tps, body) {
|
||||
check_bare_fn(ccx, decl, body, it.id, none);
|
||||
}
|
||||
ast::item_impl(tps, rp, _, ty, ms) {
|
||||
ast::item_impl(tps, _, ty, ms) {
|
||||
let rp = ccx.tcx.region_paramd_items.contains_key(it.id);
|
||||
#debug["item_impl %s with id %d rp %b",
|
||||
*it.ident, it.id, rp];
|
||||
let self_ty = ccx.to_ty(rscope::type_rscope(rp), ty);
|
||||
for ms.each |m| { check_method(ccx, m, self_ty);}
|
||||
}
|
||||
ast::item_class(tps, traits, members, ctor, m_dtor, rp) {
|
||||
ast::item_class(tps, traits, members, ctor, m_dtor) {
|
||||
let tcx = ccx.tcx;
|
||||
let class_t = ty::node_id_to_type(tcx, it.id);
|
||||
// typecheck the ctor
|
||||
@ -387,9 +390,9 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
|
||||
// Check that the class is instantiable
|
||||
check_instantiable(ccx.tcx, it.span, it.id);
|
||||
}
|
||||
ast::item_ty(t, tps, rp) {
|
||||
ast::item_ty(t, tps) {
|
||||
let tpt_ty = ty::node_id_to_type(ccx.tcx, it.id);
|
||||
check_bounds_are_used(ccx, t.span, tps, rp, tpt_ty);
|
||||
check_bounds_are_used(ccx, t.span, tps, tpt_ty);
|
||||
}
|
||||
ast::item_foreign_mod(m) {
|
||||
if syntax::attr::foreign_abi(it.attrs) ==
|
||||
@ -647,15 +650,16 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
|
||||
let {n_tps, rp, raw_ty} = if did.crate == ast::local_crate {
|
||||
let rp = fcx.tcx().region_paramd_items.contains_key(did.node);
|
||||
alt check tcx.items.find(did.node) {
|
||||
some(ast_map::node_item(@{node: ast::item_impl(ts, rp, _, st, _),
|
||||
some(ast_map::node_item(@{node: ast::item_impl(ts, _, st, _),
|
||||
_}, _)) {
|
||||
{n_tps: ts.len(),
|
||||
rp: rp,
|
||||
raw_ty: fcx.ccx.to_ty(rscope::type_rscope(rp), st)}
|
||||
}
|
||||
some(ast_map::node_item(@{node: ast::item_class(ts,
|
||||
_,_,_,_,rp), id: class_id, _},_)) {
|
||||
_,_,_,_), id: class_id, _},_)) {
|
||||
/* If the impl is a class, the self ty is just the class ty
|
||||
(doing a no-op subst for the ty params; in the next step,
|
||||
we substitute in fresh vars for them)
|
||||
@ -663,9 +667,8 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
|
||||
{n_tps: ts.len(),
|
||||
rp: rp,
|
||||
raw_ty: ty::mk_class(tcx, local_def(class_id),
|
||||
{self_r: alt rp {
|
||||
ast::rp_self { some(fcx.infcx.next_region_var()) }
|
||||
ast::rp_none { none }},
|
||||
{self_r: if rp {some(ty::re_bound(ty::br_self))}
|
||||
else {none},
|
||||
self_ty: none,
|
||||
tps: ty::ty_params_to_tys(tcx, ts)})}
|
||||
}
|
||||
@ -679,10 +682,7 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
|
||||
raw_ty: ity.ty}
|
||||
};
|
||||
|
||||
let self_r = alt rp {
|
||||
ast::rp_none { none }
|
||||
ast::rp_self { some(fcx.infcx.next_region_var()) }
|
||||
};
|
||||
let self_r = if rp {some(fcx.infcx.next_region_var())} else {none};
|
||||
let tps = fcx.infcx.next_ty_vars(n_tps);
|
||||
|
||||
let substs = {self_r: self_r, self_ty: none, tps: tps};
|
||||
@ -2053,7 +2053,7 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
|
||||
// extern functions are just u8 pointers
|
||||
ret {
|
||||
bounds: @~[],
|
||||
rp: ast::rp_none,
|
||||
rp: false,
|
||||
ty: ty::mk_ptr(
|
||||
fcx.ccx.tcx,
|
||||
{
|
||||
@ -2109,13 +2109,27 @@ fn instantiate_path(fcx: @fn_ctxt,
|
||||
let ty_param_count = vec::len(*tpt.bounds);
|
||||
let ty_substs_len = vec::len(pth.types);
|
||||
|
||||
// For now, there is no way to explicitly specify the region bound.
|
||||
// This will have to change eventually.
|
||||
let self_r = alt tpt.rp {
|
||||
ast::rp_self { some(fcx.infcx.next_region_var()) }
|
||||
ast::rp_none { none }
|
||||
// determine the region bound, using the value given by the user
|
||||
// (if any) and otherwise using a fresh region variable
|
||||
let self_r = alt pth.rp {
|
||||
some(r) if !tpt.rp => {
|
||||
fcx.ccx.tcx.sess.span_err
|
||||
(sp, "this item is not region-parameterized");
|
||||
none
|
||||
}
|
||||
some(r) => {
|
||||
some(ast_region_to_region(fcx, fcx, sp, r))
|
||||
}
|
||||
none if tpt.rp => {
|
||||
some(fcx.infcx.next_region_var())
|
||||
}
|
||||
none => {
|
||||
none
|
||||
}
|
||||
};
|
||||
|
||||
// determine values for type parameters, using the values given by
|
||||
// the user (if any) and otherwise using fresh type variables
|
||||
let tps = if ty_substs_len == 0u {
|
||||
fcx.infcx.next_ty_vars(ty_param_count)
|
||||
} else if ty_param_count == 0u {
|
||||
@ -2203,24 +2217,14 @@ fn ast_expr_vstore_to_vstore(fcx: @fn_ctxt, e: @ast::expr, n: uint,
|
||||
fn check_bounds_are_used(ccx: @crate_ctxt,
|
||||
span: span,
|
||||
tps: ~[ast::ty_param],
|
||||
rp: ast::region_param,
|
||||
ty: ty::t) {
|
||||
let mut r_used = alt rp {
|
||||
ast::rp_self { false }
|
||||
ast::rp_none { true }
|
||||
};
|
||||
|
||||
if tps.len() == 0u && r_used { ret; }
|
||||
// make a vector of booleans initially false, set to true when used
|
||||
if tps.len() == 0u { ret; }
|
||||
let tps_used = vec::to_mut(vec::from_elem(tps.len(), false));
|
||||
|
||||
ty::walk_regions_and_ty(
|
||||
ccx.tcx, ty,
|
||||
|r| {
|
||||
alt r {
|
||||
ty::re_bound(_) { r_used = true; }
|
||||
_ { }
|
||||
}
|
||||
},
|
||||
|_r| {},
|
||||
|t| {
|
||||
alt ty::get(t).struct {
|
||||
ty::ty_param(idx, _) { tps_used[idx] = true; }
|
||||
@ -2229,12 +2233,6 @@ fn check_bounds_are_used(ccx: @crate_ctxt,
|
||||
true
|
||||
});
|
||||
|
||||
if !r_used {
|
||||
ccx.tcx.sess.span_err(
|
||||
span, "lifetime `self` unused inside \
|
||||
reference-parameterized type");
|
||||
}
|
||||
|
||||
for tps_used.eachi |i, b| {
|
||||
if !b {
|
||||
ccx.tcx.sess.span_err(
|
||||
|
@ -15,7 +15,7 @@ import middle::typeck::infer::{infer_ctxt, mk_subty, new_infer_ctxt};
|
||||
import syntax::ast::{crate, def_id, item, item_class, item_const, item_enum};
|
||||
import syntax::ast::{item_fn, item_foreign_mod, item_impl, item_mac};
|
||||
import syntax::ast::{item_mod, item_trait, item_ty, local_crate, method};
|
||||
import syntax::ast::{node_id, region_param, rp_none, rp_self, trait_ref};
|
||||
import syntax::ast::{node_id, trait_ref};
|
||||
import syntax::ast_util::{def_id_of_def, new_def_hash};
|
||||
import syntax::visit::{default_simple_visitor, default_visitor};
|
||||
import syntax::visit::{mk_simple_visitor, mk_vt, visit_crate, visit_item};
|
||||
@ -76,7 +76,7 @@ class CoherenceChecker {
|
||||
visit_crate(*crate, (), mk_simple_visitor(@{
|
||||
visit_item: |item| {
|
||||
alt item.node {
|
||||
item_impl(_, _, associated_trait, self_type, _) {
|
||||
item_impl(_, associated_trait, self_type, _) {
|
||||
self.check_implementation(item, associated_trait);
|
||||
}
|
||||
_ {
|
||||
@ -239,15 +239,9 @@ class CoherenceChecker {
|
||||
// Converts a polytype to a monotype by replacing all parameters with
|
||||
// type variables.
|
||||
fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t {
|
||||
let self_region;
|
||||
alt polytype.rp {
|
||||
rp_none {
|
||||
self_region = none;
|
||||
}
|
||||
rp_self {
|
||||
self_region = some(self.inference_context.next_region_var())
|
||||
}
|
||||
};
|
||||
let self_region =
|
||||
if polytype.rp {none}
|
||||
else {some(self.inference_context.next_region_var())};
|
||||
|
||||
let bounds_count = polytype.bounds.len();
|
||||
let type_parameters =
|
||||
@ -304,7 +298,7 @@ class CoherenceChecker {
|
||||
self.privileged_types.remove(privileged_type);
|
||||
}
|
||||
}
|
||||
item_impl(_, _, optional_trait_ref, _, _) {
|
||||
item_impl(_, optional_trait_ref, _, _) {
|
||||
alt self.base_type_def_ids.find(item.id) {
|
||||
none {
|
||||
// Nothing to do.
|
||||
|
@ -39,13 +39,13 @@ fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) {
|
||||
|
||||
alt intrinsic_item.node {
|
||||
|
||||
ast::item_trait(_, _, _) {
|
||||
ast::item_trait(_, _) {
|
||||
let ty = ty::mk_trait(ccx.tcx, def_id, substs);
|
||||
ccx.tcx.intrinsic_defs.insert
|
||||
(intrinsic_item.ident, (def_id, ty));
|
||||
}
|
||||
|
||||
ast::item_enum(_, _, _) {
|
||||
ast::item_enum(_, _) {
|
||||
let ty = ty::mk_enum(ccx.tcx, def_id, substs);
|
||||
ccx.tcx.intrinsic_defs.insert
|
||||
(intrinsic_item.ident, (def_id, ty));
|
||||
@ -107,7 +107,7 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
|
||||
enum_ty: ty::t,
|
||||
variants: ~[ast::variant],
|
||||
ty_params: ~[ast::ty_param],
|
||||
rp: ast::region_param) {
|
||||
rp: bool) {
|
||||
let tcx = ccx.tcx;
|
||||
|
||||
// Create a set of parameter types shared among all the variants.
|
||||
@ -144,13 +144,14 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id) {
|
||||
}
|
||||
|
||||
let tcx = ccx.tcx;
|
||||
let rp = tcx.region_paramd_items.contains_key(id);
|
||||
alt check tcx.items.get(id) {
|
||||
ast_map::node_item(@{node: ast::item_trait(_, rp, ms), _}, _) {
|
||||
ast_map::node_item(@{node: ast::item_trait(_, ms), _}, _) {
|
||||
store_methods::<ast::ty_method>(ccx, id, ms, |m| {
|
||||
ty_of_ty_method(ccx, m, rp)
|
||||
});
|
||||
}
|
||||
ast_map::node_item(@{node: ast::item_class(_,_,its,_,_,rp), _}, _) {
|
||||
ast_map::node_item(@{node: ast::item_class(_,_,its,_,_), _}, _) {
|
||||
let (_,ms) = split_class_items(its);
|
||||
// All methods need to be stored, since lookup_method
|
||||
// relies on the same method cache for self-calls
|
||||
@ -234,7 +235,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span,
|
||||
|
||||
fn check_methods_against_trait(ccx: @crate_ctxt,
|
||||
tps: ~[ast::ty_param],
|
||||
rp: ast::region_param,
|
||||
rp: bool,
|
||||
selfty: ty::t,
|
||||
a_trait_ty: @ast::trait_ref,
|
||||
ms: ~[converted_method]) {
|
||||
@ -267,7 +268,7 @@ fn check_methods_against_trait(ccx: @crate_ctxt,
|
||||
} // fn
|
||||
|
||||
fn convert_class_item(ccx: @crate_ctxt,
|
||||
rp: ast::region_param,
|
||||
rp: bool,
|
||||
bounds: @~[ty::param_bounds],
|
||||
v: ast_util::ivar) {
|
||||
let tt = ccx.to_ty(type_rscope(rp), v.ty);
|
||||
@ -280,7 +281,7 @@ type converted_method = {mty: ty::method, id: ast::node_id, span: span};
|
||||
|
||||
fn convert_methods(ccx: @crate_ctxt,
|
||||
ms: ~[@ast::method],
|
||||
rp: ast::region_param,
|
||||
rp: bool,
|
||||
rcvr_bounds: @~[ty::param_bounds],
|
||||
self_ty: ty::t) -> ~[converted_method] {
|
||||
|
||||
@ -303,16 +304,17 @@ fn convert_methods(ccx: @crate_ctxt,
|
||||
|
||||
fn convert(ccx: @crate_ctxt, it: @ast::item) {
|
||||
let tcx = ccx.tcx;
|
||||
let rp = tcx.region_paramd_items.contains_key(it.id);
|
||||
#debug["convert: item %s with id %d rp %b", *it.ident, it.id, rp];
|
||||
alt it.node {
|
||||
// These don't define types.
|
||||
ast::item_foreign_mod(_) | ast::item_mod(_) {}
|
||||
ast::item_enum(variants, ty_params, rp) {
|
||||
ast::item_enum(variants, ty_params) {
|
||||
let tpt = ty_of_item(ccx, it);
|
||||
write_ty_to_tcx(tcx, it.id, tpt.ty);
|
||||
get_enum_variant_types(ccx, tpt.ty, variants,
|
||||
ty_params, rp);
|
||||
get_enum_variant_types(ccx, tpt.ty, variants, ty_params, rp);
|
||||
}
|
||||
ast::item_impl(tps, rp, ifce, selfty, ms) {
|
||||
ast::item_impl(tps, ifce, selfty, ms) {
|
||||
let i_bounds = ty_param_bounds(ccx, tps);
|
||||
let selfty = ccx.to_ty(type_rscope(rp), selfty);
|
||||
write_ty_to_tcx(tcx, it.id, selfty);
|
||||
@ -333,7 +335,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
|
||||
write_ty_to_tcx(tcx, it.id, tpt.ty);
|
||||
ensure_trait_methods(ccx, it.id);
|
||||
}
|
||||
ast::item_class(tps, traits, members, ctor, m_dtor, rp) {
|
||||
ast::item_class(tps, traits, members, ctor, m_dtor) {
|
||||
// Write the class type
|
||||
let tpt = ty_of_item(ccx, it);
|
||||
write_ty_to_tcx(tcx, it.id, tpt.ty);
|
||||
@ -341,20 +343,19 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
|
||||
// Write the ctor type
|
||||
let t_args = ctor.node.dec.inputs.map(
|
||||
|a| ty_of_arg(ccx, type_rscope(rp), a, none) );
|
||||
let t_res = ty::mk_class(tcx, local_def(it.id),
|
||||
{self_r: alt rp {
|
||||
ast::rp_none { none }
|
||||
ast::rp_self { some(ty::re_bound(ty::br_self)) }
|
||||
},
|
||||
self_ty: none,
|
||||
tps: ty::ty_params_to_tys(tcx, tps)});
|
||||
let t_ctor = ty::mk_fn(tcx, {purity: ast::impure_fn,
|
||||
proto: ast::proto_any,
|
||||
inputs: t_args,
|
||||
output: t_res,
|
||||
ret_style: ast::return_val,
|
||||
constraints: ~[]}); // FIXME (#2813): allow ctors to have
|
||||
// constraints, or remove constraints from the language
|
||||
let t_res = ty::mk_class(
|
||||
tcx, local_def(it.id),
|
||||
{self_r: if rp {some(ty::re_bound(ty::br_self))} else {none},
|
||||
self_ty: none,
|
||||
tps: ty::ty_params_to_tys(tcx, tps)});
|
||||
let t_ctor = ty::mk_fn(
|
||||
tcx, {purity: ast::impure_fn,
|
||||
proto: ast::proto_any,
|
||||
inputs: t_args,
|
||||
output: t_res,
|
||||
ret_style: ast::return_val,
|
||||
constraints: ~[]}); // FIXME (#2813): allow ctors to have
|
||||
// constraints, or remove constraints from the language
|
||||
write_ty_to_tcx(tcx, ctor.node.id, t_ctor);
|
||||
tcx.tcache.insert(local_def(ctor.node.id),
|
||||
{bounds: tpt.bounds,
|
||||
@ -421,18 +422,18 @@ fn convert_foreign(ccx: @crate_ctxt, i: @ast::foreign_item) {
|
||||
|
||||
fn ty_of_method(ccx: @crate_ctxt,
|
||||
m: @ast::method,
|
||||
rp: ast::region_param) -> ty::method {
|
||||
rp: bool) -> ty::method {
|
||||
{ident: m.ident,
|
||||
tps: ty_param_bounds(ccx, m.tps),
|
||||
fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare,
|
||||
m.decl, none),
|
||||
m.decl, none),
|
||||
purity: m.decl.purity,
|
||||
vis: m.vis}
|
||||
}
|
||||
|
||||
fn ty_of_ty_method(self: @crate_ctxt,
|
||||
m: ast::ty_method,
|
||||
rp: ast::region_param) -> ty::method {
|
||||
rp: bool) -> ty::method {
|
||||
{ident: m.ident,
|
||||
tps: ty_param_bounds(self, m.tps),
|
||||
fty: ty_of_fn_decl(self, type_rscope(rp), ast::proto_bare,
|
||||
@ -446,8 +447,7 @@ fn ty_of_ty_method(self: @crate_ctxt,
|
||||
it's bound to a valid trait type. Returns the def_id for the defining
|
||||
trait. Fails if the type is a type other than an trait type.
|
||||
*/
|
||||
fn instantiate_trait_ref(ccx: @crate_ctxt, t: @ast::trait_ref,
|
||||
rp: ast::region_param)
|
||||
fn instantiate_trait_ref(ccx: @crate_ctxt, t: @ast::trait_ref, rp: bool)
|
||||
-> (ast::def_id, ty_param_substs_and_ty) {
|
||||
|
||||
let sp = t.path.span, err = "can only implement interface types",
|
||||
@ -480,6 +480,7 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
|
||||
some(tpt) { ret tpt; }
|
||||
_ {}
|
||||
}
|
||||
let rp = tcx.region_paramd_items.contains_key(it.id);
|
||||
alt it.node {
|
||||
ast::item_const(t, _) {
|
||||
let typ = ccx.to_ty(empty_rscope, t);
|
||||
@ -492,19 +493,20 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
|
||||
let tofd = ty_of_fn_decl(ccx, empty_rscope, ast::proto_bare,
|
||||
decl, none);
|
||||
let tpt = {bounds: bounds,
|
||||
rp: ast::rp_none, // functions do not have a self
|
||||
rp: false, // functions do not have a self
|
||||
ty: ty::mk_fn(ccx.tcx, tofd)};
|
||||
#debug["type of %s (id %d) is %s",
|
||||
*it.ident, it.id, ty_to_str(tcx, tpt.ty)];
|
||||
ccx.tcx.tcache.insert(local_def(it.id), tpt);
|
||||
ret tpt;
|
||||
}
|
||||
ast::item_ty(t, tps, rp) {
|
||||
ast::item_ty(t, tps) {
|
||||
alt tcx.tcache.find(local_def(it.id)) {
|
||||
some(tpt) { ret tpt; }
|
||||
none { }
|
||||
}
|
||||
|
||||
let rp = tcx.region_paramd_items.contains_key(it.id);
|
||||
let tpt = {
|
||||
let ty = {
|
||||
let t0 = ccx.to_ty(type_rscope(rp), t);
|
||||
@ -522,7 +524,7 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
|
||||
tcx.tcache.insert(local_def(it.id), tpt);
|
||||
ret tpt;
|
||||
}
|
||||
ast::item_enum(_, tps, rp) {
|
||||
ast::item_enum(_, tps) {
|
||||
// Create a new generic polytype.
|
||||
let {bounds, substs} = mk_substs(ccx, tps, rp);
|
||||
let t = ty::mk_enum(tcx, local_def(it.id), substs);
|
||||
@ -530,14 +532,14 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
|
||||
tcx.tcache.insert(local_def(it.id), tpt);
|
||||
ret tpt;
|
||||
}
|
||||
ast::item_trait(tps, rp, ms) {
|
||||
ast::item_trait(tps, ms) {
|
||||
let {bounds, substs} = mk_substs(ccx, tps, rp);
|
||||
let t = ty::mk_trait(tcx, local_def(it.id), substs);
|
||||
let tpt = {bounds: bounds, rp: rp, ty: t};
|
||||
tcx.tcache.insert(local_def(it.id), tpt);
|
||||
ret tpt;
|
||||
}
|
||||
ast::item_class(tps, _, _, _, _, rp) {
|
||||
ast::item_class(tps, _, _, _, _) {
|
||||
let {bounds,substs} = mk_substs(ccx, tps, rp);
|
||||
let t = ty::mk_class(tcx, local_def(it.id), substs);
|
||||
let tpt = {bounds: bounds, rp: rp, ty: t};
|
||||
@ -555,7 +557,7 @@ fn ty_of_foreign_item(ccx: @crate_ctxt, it: @ast::foreign_item)
|
||||
alt it.node {
|
||||
ast::foreign_item_fn(fn_decl, params) {
|
||||
ret ty_of_foreign_fn_decl(ccx, fn_decl, params,
|
||||
local_def(it.id));
|
||||
local_def(it.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -615,7 +617,7 @@ fn ty_of_foreign_fn_decl(ccx: @crate_ctxt,
|
||||
output: output_ty,
|
||||
ret_style: ast::return_val,
|
||||
constraints: ~[]});
|
||||
let tpt = {bounds: bounds, rp: ast::rp_none, ty: t_fn};
|
||||
let tpt = {bounds: bounds, rp: false, ty: t_fn};
|
||||
ccx.tcx.tcache.insert(def_id, tpt);
|
||||
ret tpt;
|
||||
}
|
||||
@ -633,13 +635,10 @@ fn mk_ty_params(ccx: @crate_ctxt, atps: ~[ast::ty_param])
|
||||
})}
|
||||
}
|
||||
|
||||
fn mk_substs(ccx: @crate_ctxt, atps: ~[ast::ty_param], rp: ast::region_param)
|
||||
fn mk_substs(ccx: @crate_ctxt, atps: ~[ast::ty_param], rp: bool)
|
||||
-> {bounds: @~[ty::param_bounds], substs: ty::substs} {
|
||||
|
||||
let {bounds, params} = mk_ty_params(ccx, atps);
|
||||
let self_r = alt rp {
|
||||
ast::rp_self { some(ty::re_bound(ty::br_self)) }
|
||||
ast::rp_none { none }
|
||||
};
|
||||
let self_r = if rp {some(ty::re_bound(ty::br_self))} else {none};
|
||||
{bounds: bounds, substs: {self_r: self_r, self_ty: none, tps: params}}
|
||||
}
|
||||
|
@ -16,15 +16,14 @@ impl of region_scope for empty_rscope {
|
||||
}
|
||||
}
|
||||
|
||||
enum type_rscope = ast::region_param;
|
||||
enum type_rscope = bool;
|
||||
impl of region_scope for type_rscope {
|
||||
fn anon_region() -> result<ty::region, str> {
|
||||
alt *self {
|
||||
ast::rp_self { result::ok(ty::re_bound(ty::br_self)) }
|
||||
ast::rp_none {
|
||||
if *self {
|
||||
result::ok(ty::re_bound(ty::br_self))
|
||||
} else {
|
||||
result::err("to use region types here, the containing type \
|
||||
must be declared with a region bound")
|
||||
}
|
||||
}
|
||||
}
|
||||
fn named_region(id: ast::ident) -> result<ty::region, str> {
|
||||
|
@ -147,7 +147,7 @@ fn fold_enum(
|
||||
let desc = do astsrv::exec(srv) |ctxt| {
|
||||
alt check ctxt.ast_map.get(doc_id) {
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_enum(ast_variants, _, _), _
|
||||
node: ast::item_enum(ast_variants, _), _
|
||||
}, _) {
|
||||
let ast_variant = option::get(
|
||||
vec::find(ast_variants, |v| {
|
||||
@ -204,14 +204,14 @@ fn merge_method_attrs(
|
||||
let attrs: ~[(str, option<str>)] = do astsrv::exec(srv) |ctxt| {
|
||||
alt ctxt.ast_map.get(item_id) {
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_trait(_, _, methods), _
|
||||
node: ast::item_trait(_, methods), _
|
||||
}, _) {
|
||||
par::seqmap(methods, |method| {
|
||||
(*method.ident, attr_parser::parse_desc(method.attrs))
|
||||
})
|
||||
}
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_impl(_, _, _, _, methods), _
|
||||
node: ast::item_impl(_, _, _, methods), _
|
||||
}, _) {
|
||||
par::seqmap(methods, |method| {
|
||||
(*method.ident, attr_parser::parse_desc(method.attrs))
|
||||
|
@ -78,22 +78,22 @@ fn moddoc_from_mod(
|
||||
constdoc_from_const(itemdoc)
|
||||
))
|
||||
}
|
||||
ast::item_enum(variants, _, _) {
|
||||
ast::item_enum(variants, _) {
|
||||
some(doc::enumtag(
|
||||
enumdoc_from_enum(itemdoc, variants)
|
||||
))
|
||||
}
|
||||
ast::item_trait(_, _, methods) {
|
||||
ast::item_trait(_, methods) {
|
||||
some(doc::traittag(
|
||||
traitdoc_from_trait(itemdoc, methods)
|
||||
))
|
||||
}
|
||||
ast::item_impl(_, _, _, _, methods) {
|
||||
ast::item_impl(_, _, _, methods) {
|
||||
some(doc::impltag(
|
||||
impldoc_from_impl(itemdoc, methods)
|
||||
))
|
||||
}
|
||||
ast::item_ty(_, _, _) {
|
||||
ast::item_ty(_, _) {
|
||||
some(doc::tytag(
|
||||
tydoc_from_ty(itemdoc)
|
||||
))
|
||||
|
@ -291,7 +291,7 @@ fn all_impls(m: ast::_mod) -> map::set<ast::def_id> {
|
||||
let all_impls = ast_util::new_def_hash();
|
||||
for m.items.each |item| {
|
||||
alt item.node {
|
||||
ast::item_impl(_, _, _, _, _) {
|
||||
ast::item_impl(_, _, _, _) {
|
||||
all_impls.insert(ast_util::local_def(item.id), ());
|
||||
}
|
||||
_ { }
|
||||
|
@ -110,7 +110,7 @@ fn fold_enum(
|
||||
let sig = do astsrv::exec(srv) |ctxt| {
|
||||
alt check ctxt.ast_map.get(doc_id) {
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_enum(ast_variants, _, _), _
|
||||
node: ast::item_enum(ast_variants, _), _
|
||||
}, _) {
|
||||
let ast_variant = option::get(
|
||||
do vec::find(ast_variants) |v| {
|
||||
@ -168,7 +168,7 @@ fn get_method_sig(
|
||||
do astsrv::exec(srv) |ctxt| {
|
||||
alt check ctxt.ast_map.get(item_id) {
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_trait(_, _, methods), _
|
||||
node: ast::item_trait(_, methods), _
|
||||
}, _) {
|
||||
alt check vec::find(methods, |method| {
|
||||
*method.ident == method_name
|
||||
@ -183,7 +183,7 @@ fn get_method_sig(
|
||||
}
|
||||
}
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_impl(_, _, _, _, methods), _
|
||||
node: ast::item_impl(_, _, _, methods), _
|
||||
}, _) {
|
||||
alt check vec::find(methods, |method| {
|
||||
*method.ident == method_name
|
||||
@ -218,7 +218,7 @@ fn fold_impl(
|
||||
let (trait_ty, self_ty) = do astsrv::exec(srv) |ctxt| {
|
||||
alt ctxt.ast_map.get(doc.id()) {
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_impl(_, _, trait_ty, self_ty, _), _
|
||||
node: ast::item_impl(_, trait_ty, self_ty, _), _
|
||||
}, _) {
|
||||
let trait_ty = option::map(trait_ty, |p| {
|
||||
pprust::path_to_str(p.path)
|
||||
@ -274,7 +274,7 @@ fn fold_type(
|
||||
alt ctxt.ast_map.get(doc.id()) {
|
||||
ast_map::node_item(@{
|
||||
ident: ident,
|
||||
node: ast::item_ty(ty, params, ast::rp_none), _
|
||||
node: ast::item_ty(ty, params), _
|
||||
}, _) {
|
||||
some(#fmt(
|
||||
"type %s%s = %s",
|
||||
|
@ -1,3 +0,0 @@
|
||||
type foo/& = {f: int}; //~ ERROR lifetime `self` unused
|
||||
|
||||
fn main() {}
|
@ -2,9 +2,9 @@
|
||||
// nominal types (but not on other types) and that they are type
|
||||
// checked.
|
||||
|
||||
enum an_enum/& { }
|
||||
iface an_iface/& { }
|
||||
class a_class/& { let x:int; new(x:int) { self.x = x; } }
|
||||
enum an_enum = ∫
|
||||
iface an_iface { fn foo() -> &self.int; }
|
||||
class a_class { let x:&self.int; new(x:&self.int) { self.x = x; } }
|
||||
|
||||
fn a_fn1(e: an_enum/&a) -> an_enum/&b {
|
||||
ret e; //~ ERROR mismatched types: expected `an_enum/&b` but found `an_enum/&a`
|
||||
|
@ -1,4 +1,4 @@
|
||||
enum ast/& {
|
||||
enum ast {
|
||||
num(uint),
|
||||
add(&ast, &ast)
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
type ctxt = { v: uint };
|
||||
|
||||
iface get_ctxt/& {
|
||||
iface get_ctxt {
|
||||
// Here the `&` is bound in the method definition:
|
||||
fn get_ctxt() -> &ctxt;
|
||||
}
|
||||
|
||||
type has_ctxt/& = { c: &ctxt };
|
||||
type has_ctxt = { c: &ctxt };
|
||||
|
||||
impl/& of get_ctxt for has_ctxt {
|
||||
impl of get_ctxt for has_ctxt {
|
||||
|
||||
// Here an error occurs because we used `&self` but
|
||||
// the definition used `&`:
|
||||
|
@ -1,12 +1,12 @@
|
||||
type ctxt = { v: uint };
|
||||
|
||||
iface get_ctxt/& {
|
||||
iface get_ctxt {
|
||||
fn get_ctxt() -> &self.ctxt;
|
||||
}
|
||||
|
||||
type has_ctxt/& = { c: &ctxt };
|
||||
type has_ctxt = { c: &ctxt };
|
||||
|
||||
impl/& of get_ctxt for has_ctxt {
|
||||
impl of get_ctxt for has_ctxt {
|
||||
fn get_ctxt() -> &self.ctxt { self.c }
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
iface get_ctxt/& {
|
||||
iface get_ctxt {
|
||||
fn get_ctxt() -> &self.uint;
|
||||
}
|
||||
|
||||
|
@ -1,24 +1,12 @@
|
||||
enum no0 {
|
||||
x0(&uint) //~ ERROR to use region types here, the containing type must be declared with a region bound
|
||||
}
|
||||
|
||||
enum no1 {
|
||||
x1(&self.uint) //~ ERROR to use region types here, the containing type must be declared with a region bound
|
||||
}
|
||||
|
||||
enum no2 {
|
||||
x2(&foo.uint) //~ ERROR named regions other than `self` are not allowed as part of a type declaration
|
||||
}
|
||||
|
||||
enum yes0/& {
|
||||
enum yes0 {
|
||||
x3(&uint)
|
||||
}
|
||||
|
||||
enum yes1/& {
|
||||
enum yes1 {
|
||||
x4(&self.uint)
|
||||
}
|
||||
|
||||
enum yes2/& {
|
||||
enum yes2 {
|
||||
x5(&foo.uint) //~ ERROR named regions other than `self` are not allowed as part of a type declaration
|
||||
}
|
||||
|
||||
|
@ -1,34 +1,16 @@
|
||||
class no0 {
|
||||
let x: &uint; //~ ERROR to use region types here, the containing type must be declared with a region bound
|
||||
new(x: &uint) { self.x = x; } //~ ERROR to use region types here, the containing type must be declared with a region bound
|
||||
drop {}
|
||||
}
|
||||
|
||||
class no1 {
|
||||
let x: &self.uint; //~ ERROR to use region types here, the containing type must be declared with a region bound
|
||||
new(x: &self.uint) { self.x = x; } //~ ERROR to use region types here, the containing type must be declared with a region bound
|
||||
drop {}
|
||||
}
|
||||
|
||||
class no2 {
|
||||
let x: &foo.uint; //~ ERROR named regions other than `self` are not allowed as part of a type declaration
|
||||
new(x: &foo.uint) { self.x = x; } //~ ERROR named regions other than `self` are not allowed as part of a type declaration
|
||||
drop {}
|
||||
}
|
||||
|
||||
class yes0/& {
|
||||
class yes0 {
|
||||
let x: &uint;
|
||||
new(x: &uint) { self.x = x; }
|
||||
drop {}
|
||||
}
|
||||
|
||||
class yes1/& {
|
||||
class yes1 {
|
||||
let x: &self.uint;
|
||||
new(x: &self.uint) { self.x = x; }
|
||||
drop {}
|
||||
}
|
||||
|
||||
class yes2/& {
|
||||
class yes2 {
|
||||
let x: &foo.uint; //~ ERROR named regions other than `self` are not allowed as part of a type declaration
|
||||
new(x: &foo.uint) { self.x = x; } //~ ERROR named regions other than `self` are not allowed as part of a type declaration
|
||||
drop {}
|
||||
|
@ -1,24 +1,12 @@
|
||||
type item_ty_no0 = {
|
||||
x: &uint //~ ERROR to use region types here, the containing type must be declared with a region bound
|
||||
};
|
||||
|
||||
type item_ty_no1 = {
|
||||
x: &self.uint //~ ERROR to use region types here, the containing type must be declared with a region bound
|
||||
};
|
||||
|
||||
type item_ty_no2 = {
|
||||
x: &foo.uint //~ ERROR named regions other than `self` are not allowed as part of a type declaration
|
||||
};
|
||||
|
||||
type item_ty_yes0/& = {
|
||||
type item_ty_yes0 = {
|
||||
x: &uint
|
||||
};
|
||||
|
||||
type item_ty_yes1/& = {
|
||||
type item_ty_yes1 = {
|
||||
x: &self.uint
|
||||
};
|
||||
|
||||
type item_ty_yes2/& = { //~ ERROR lifetime `self` unused inside reference-parameterized type
|
||||
type item_ty_yes2 = {
|
||||
x: &foo.uint //~ ERROR named regions other than `self` are not allowed as part of a type declaration
|
||||
};
|
||||
|
||||
|
18
src/test/compile-fail/regions-infer-paramd-indirect.rs
Normal file
18
src/test/compile-fail/regions-infer-paramd-indirect.rs
Normal 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 = ∫
|
||||
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() {}
|
32
src/test/compile-fail/regions-infer-paramd-method.rs
Normal file
32
src/test/compile-fail/regions-infer-paramd-method.rs
Normal 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() -> ∫
|
||||
}
|
||||
|
||||
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() -> ∫
|
||||
}
|
||||
|
||||
type with_bar = {mut f: bar};
|
||||
|
||||
impl methods for with_bar {
|
||||
fn set_foo(f: bar) {
|
||||
self.f = f;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -6,7 +6,7 @@ iface iterable<A> {
|
||||
fn iterate(blk: fn(A) -> bool);
|
||||
}
|
||||
|
||||
impl vec/&<A> of iterable<A> for &[const A] {
|
||||
impl vec<A> of iterable<A> for &[const A] {
|
||||
fn iterate(f: fn(A) -> bool) {
|
||||
vec::each(self, f);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
class font/& {
|
||||
class font {
|
||||
let fontbuf: &self.~[u8];
|
||||
|
||||
new(fontbuf: &self.~[u8]) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
class CMap/& {
|
||||
let buf: [u8]/&;
|
||||
class CMap {
|
||||
let buf: &[u8];
|
||||
|
||||
new(buf: [u8]/&) {
|
||||
new(buf: &self.[u8]) {
|
||||
self.buf = buf;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Note: impl on a slice
|
||||
impl foo/& for &int {
|
||||
impl foo for &int {
|
||||
fn get() -> int {
|
||||
ret *self;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Note: impl on a slice
|
||||
impl foo/& for &[int] {
|
||||
impl foo for &[int] {
|
||||
fn sum() -> int {
|
||||
let mut sum = 0;
|
||||
for vec::each(self) |e| { sum += e; }
|
||||
|
@ -1,4 +1,4 @@
|
||||
enum ast/& {
|
||||
enum ast {
|
||||
num(uint),
|
||||
add(&ast, &ast)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
enum ast/& {
|
||||
enum ast {
|
||||
num(uint),
|
||||
add(&ast, &ast)
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
type ctxt = { v: uint };
|
||||
|
||||
iface get_ctxt/& {
|
||||
iface get_ctxt {
|
||||
fn get_ctxt() -> &self.ctxt;
|
||||
}
|
||||
|
||||
type has_ctxt/& = { c: &ctxt };
|
||||
type has_ctxt = { c: &ctxt };
|
||||
|
||||
impl/& of get_ctxt for has_ctxt {
|
||||
impl of get_ctxt for has_ctxt {
|
||||
fn get_ctxt() -> &self.ctxt {
|
||||
self.c
|
||||
}
|
||||
|
@ -2,11 +2,11 @@ import libc, sys, unsafe;
|
||||
|
||||
enum arena = ();
|
||||
|
||||
type bcx/& = {
|
||||
type bcx = {
|
||||
fcx: &fcx
|
||||
};
|
||||
|
||||
type fcx/& = {
|
||||
type fcx = {
|
||||
arena: &arena,
|
||||
ccx: &ccx
|
||||
};
|
||||
|
@ -2,11 +2,11 @@ import libc, sys, unsafe;
|
||||
|
||||
enum arena = ();
|
||||
|
||||
type bcx/& = {
|
||||
type bcx = {
|
||||
fcx: &fcx
|
||||
};
|
||||
|
||||
type fcx/& = {
|
||||
type fcx = {
|
||||
arena: &arena,
|
||||
ccx: &ccx
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
enum roption/& {
|
||||
enum roption {
|
||||
a, b(&uint)
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
enum int_wrapper/& {
|
||||
enum int_wrapper {
|
||||
int_wrapper_ctor(&int)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user