lots of work to make iface/impls parameterized by regions

- paths can now take region parameters, replacing the dirty hack
  I was doing before of abusing vstores.  vstores are now a bit
  of a hack though.

- fix various small bugs:
  - we never checked that iface types were compatible when casting
    to an iface with `as`
  - we allowed nonsense like int<int>
  - and more! (actually that may be it)
This commit is contained in:
Niko Matsakis 2012-04-24 15:52:52 -07:00
parent 458d2ff067
commit 825fd1808e
39 changed files with 849 additions and 547 deletions

View file

@ -37,7 +37,11 @@ type ident = str;
type fn_ident = option<ident>;
#[auto_serialize]
type path = {span: span, global: bool, idents: [ident], types: [@ty]};
type path = {span: span,
global: bool,
idents: [ident],
rp: option<@region>,
types: [@ty]};
#[auto_serialize]
type crate_num = int;
@ -175,7 +179,7 @@ enum vstore {
vstore_fixed(option<uint>), // [1,2,3,4]/_ or 4
vstore_uniq, // [1,2,3,4]/~
vstore_box, // [1,2,3,4]/@
vstore_slice(region) // [1,2,3,4]/&(foo)?
vstore_slice(@region) // [1,2,3,4]/&(foo)?
}
pure fn is_blockish(p: ast::proto) -> bool {
@ -462,7 +466,7 @@ enum ty_ {
ty_uniq(mt),
ty_vec(mt),
ty_ptr(mt),
ty_rptr(region, mt),
ty_rptr(@region, mt),
ty_rec([ty_field]),
ty_fn(proto, fn_decl),
ty_tup([@ty]),
@ -671,8 +675,8 @@ enum item_ {
class_ctor,
region_param
),
item_iface([ty_param], [ty_method]),
item_impl([ty_param], option<@iface_ref> /* iface */,
item_iface([ty_param], region_param, [ty_method]),
item_impl([ty_param], region_param, option<@iface_ref> /* iface */,
@ty /* self */, [@method]),
}

View file

@ -248,7 +248,8 @@ fn default_block(stmts1: [@stmt], expr1: option<@expr>, id1: node_id) ->
}
fn ident_to_path(s: span, i: ident) -> @path {
@{span: s, global: false, idents: [i], types: []}
@{span: s, global: false, idents: [i],
rp: none, types: []}
}
pure fn is_unguarded(&&a: arm) -> bool {

View file

@ -130,11 +130,11 @@ impl helpers for ext_ctxt {
}
fn path(span: span, strs: [str]) -> @ast::path {
@{span: span, global: false, idents: strs, types: []}
@{span: span, global: false, idents: strs, rp: none, types: []}
}
fn path_tps(span: span, strs: [str], tps: [@ast::ty]) -> @ast::path {
@{span: span, global: false, idents: strs, types: tps}
@{span: span, global: false, idents: strs, rp: none, types: tps}
}
fn ty_path(span: span, strs: [str], tps: [@ast::ty]) -> @ast::ty {
@ -193,7 +193,8 @@ impl helpers for ext_ctxt {
}
fn binder_pat(span: span, nm: str) -> @ast::pat {
let path = @{span: span, global: false, idents: [nm], types: []};
let path = @{span: span, global: false, idents: [nm],
rp: none, types: []};
@{id: self.next_id(),
node: ast::pat_ident(path, none),
span: span}

View file

@ -30,7 +30,8 @@ fn mk_unary(cx: ext_ctxt, sp: span, op: ast::unop, e: @ast::expr)
}
fn mk_path(cx: ext_ctxt, sp: span, idents: [ast::ident]) ->
@ast::expr {
let path = @{span: sp, global: false, idents: idents, types: []};
let path = @{span: sp, global: false, idents: idents,
rp: none, types: []};
let pathexpr = ast::expr_path(path);
ret @{id: cx.next_id(), node: pathexpr, span: sp};
}

View file

@ -17,6 +17,6 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
ret @{id: cx.next_id(),
node: ast::expr_path(@{span: sp, global: false, idents: [res],
types: []}),
rp: none, types: []}),
span: sp};
}

View file

@ -334,7 +334,8 @@ fn transcribe_path(cx: ext_ctxt, b: bindings, idx_path: @mut [uint],
if vec::len(p.types) > 0u || vec::len(p.idents) != 1u { ret p; }
alt follow_for_trans(cx, b.find(p.idents[0]), idx_path) {
some(match_ident(id)) {
{span: id.span, global: false, idents: [id.node], types: []}
{span: id.span, global: false, idents: [id.node],
rp: none, types: []}
}
some(match_path(a_pth)) { *a_pth }
some(m) { match_error(cx, m, "a path") }
@ -359,6 +360,7 @@ fn transcribe_expr(cx: ext_ctxt, b: bindings, idx_path: @mut [uint],
(expr_path(@{span: id.span,
global: false,
idents: [id.node],
rp: none,
types: []}), id.span)
}
some(match_path(a_pth)) { (expr_path(a_pth), s) }

View file

@ -287,12 +287,18 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
with ctor},
rp)
}
item_impl(tps, ifce, ty, methods) {
item_impl(tps, option::map(ifce, {|p| fold_iface_ref(p, fld)}),
item_impl(tps, rp, ifce, ty, methods) {
item_impl(fold_ty_params(tps, fld),
rp,
ifce.map { |p| fold_iface_ref(p, fld) },
fld.fold_ty(ty),
vec::map(methods, fld.fold_method))
vec::map(methods, fld.fold_method))
}
item_iface(tps, rp, methods) {
item_iface(fold_ty_params(tps, fld),
rp,
methods)
}
item_iface(tps, methods) { item_iface(tps, methods) }
item_res(decl, typms, body, did, cid, rp) {
item_res(fold_fn_decl(decl, fld),
fold_ty_params(typms, fld),
@ -565,6 +571,7 @@ fn noop_fold_ident(&&i: ident, _fld: ast_fold) -> ident { ret i; }
fn noop_fold_path(&&p: path, fld: ast_fold) -> path {
ret {span: fld.new_span(p.span), global: p.global,
idents: vec::map(p.idents, fld.fold_ident),
rp: p.rp,
types: vec::map(p.types, fld.fold_ty)};
}

View file

@ -175,7 +175,7 @@ fn parse_type_constr_arg(p: parser) -> @ast::ty_constr_arg {
if p.token == token::DOT {
// "*..." notation for record fields
p.bump();
let pth = parse_path(p);
let pth = parse_path_without_tps(p);
carg = ast::carg_ident(pth);
}
// No literals yet, I guess?
@ -196,7 +196,7 @@ fn parse_constr_arg(args: [ast::arg], p: parser) -> @ast::constr_arg {
fn parse_ty_constr(fn_args: [ast::arg], p: parser) -> @ast::constr {
let lo = p.span.lo;
let path = parse_path(p);
let path = parse_path_without_tps(p);
let args: {node: [@ast::constr_arg], span: span} =
parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
{|p| parse_constr_arg(fn_args, p)}, p);
@ -206,7 +206,7 @@ fn parse_ty_constr(fn_args: [ast::arg], p: parser) -> @ast::constr {
fn parse_constr_in_type(p: parser) -> @ast::ty_constr {
let lo = p.span.lo;
let path = parse_path(p);
let path = parse_path_without_tps(p);
let args: [@ast::ty_constr_arg] =
parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
parse_type_constr_arg, p).node;
@ -231,52 +231,6 @@ fn parse_type_constraints(p: parser) -> [@ast::ty_constr] {
ret parse_constrs(parse_constr_in_type, p);
}
fn parse_ty_postfix(orig_t: ast::ty_, p: parser, colons_before_params: bool,
lo: uint) -> @ast::ty {
fn mk_ty(p: parser, t: ast::ty_, lo: uint, hi: uint) -> @ast::ty {
@{id: p.get_id(),
node: t,
span: mk_sp(lo, hi)}
}
if p.token == token::BINOP(token::SLASH) {
let orig_hi = p.last_span.hi;
alt maybe_parse_vstore(p) {
none { }
some(v) {
let t = ast::ty_vstore(mk_ty(p, orig_t, lo, orig_hi), v);
ret mk_ty(p, t, lo, p.last_span.hi);
}
}
}
if colons_before_params && p.token == token::MOD_SEP {
p.bump();
expect(p, token::LT);
} else if !colons_before_params && p.token == token::LT {
p.bump();
} else {
ret mk_ty(p, orig_t, lo, p.last_span.hi);
}
// If we're here, we have explicit type parameter instantiation.
let seq = parse_seq_to_gt(some(token::COMMA), {|p| parse_ty(p, false)},
p);
alt orig_t {
ast::ty_path(pth, ann) {
ret mk_ty(p, ast::ty_path(@{span: mk_sp(lo, p.last_span.hi),
global: pth.global,
idents: pth.idents,
types: seq}, ann),
lo, p.last_span.hi);
}
_ { p.fatal("type parameter instantiation only allowed for paths"); }
}
}
fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
ret if eat(p, token::RARROW) {
let lo = p.span.lo;
@ -295,7 +249,7 @@ fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
}
}
fn region_from_name(p: parser, s: option<str>) -> ast::region {
fn region_from_name(p: parser, s: option<str>) -> @ast::region {
let r = alt s {
some (string) {
// FIXME: To be consistent with our type resolution, the
@ -310,10 +264,26 @@ fn region_from_name(p: parser, s: option<str>) -> ast::region {
none { ast::re_anon }
};
{id: p.get_id(), node: r}
@{id: p.get_id(), node: r}
}
fn parse_region(p: parser) -> ast::region {
// Parses something like "&x"
fn parse_region(p: parser) -> @ast::region {
expect(p, token::BINOP(token::AND));
alt p.token {
token::IDENT(sid, _) {
p.bump();
let n = p.get_str(sid);
region_from_name(p, some(n))
}
_ {
region_from_name(p, none)
}
}
}
// Parses something like "&x." (note the trailing dot)
fn parse_region_dot(p: parser) -> @ast::region {
let name =
alt p.token {
token::IDENT(sid, _) if p.look_ahead(1u) == token::DOT {
@ -384,7 +354,7 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
t
} else if p.token == token::BINOP(token::AND) {
p.bump();
let region = parse_region(p);
let region = parse_region_dot(p);
let mt = parse_mt(p);
ast::ty_rptr(region, mt)
} else if eat_keyword(p, "fn") {
@ -398,10 +368,28 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
expect_keyword(p, "fn");
ast::ty_fn(ast::proto_bare, parse_ty_fn(p))
} else if p.token == token::MOD_SEP || is_ident(p.token) {
let path = parse_path(p);
let path = parse_path_with_tps(p, colons_before_params);
ast::ty_path(path, p.get_id())
} else { p.fatal("expecting type"); };
ret parse_ty_postfix(t, p, colons_before_params, lo);
fn mk_ty(p: parser, t: ast::ty_, lo: uint, hi: uint) -> @ast::ty {
@{id: p.get_id(),
node: t,
span: mk_sp(lo, hi)}
}
let ty = mk_ty(p, t, lo, p.last_span.hi);
// Consider a vstore suffix like /@ or /~
alt maybe_parse_vstore(p) {
none {
ret ty;
}
some(v) {
let t1 = ast::ty_vstore(ty, v);
ret mk_ty(p, t1, lo, p.last_span.hi);
}
}
}
fn parse_arg_mode(p: parser) -> ast::mode {
@ -484,17 +472,7 @@ fn maybe_parse_vstore(p: parser) -> option<ast::vstore> {
p.bump(); some(ast::vstore_fixed(some(i as uint)))
}
token::BINOP(token::AND) {
p.bump();
alt p.token {
token::IDENT(sid, _) {
p.bump();
let n = p.get_str(sid);
some(ast::vstore_slice(region_from_name(p, some(n))))
}
_ {
some(ast::vstore_slice(region_from_name(p, none)))
}
}
some(ast::vstore_slice(parse_region(p)))
}
_ {
none
@ -530,18 +508,19 @@ fn parse_lit(p: parser) -> ast::lit {
ret {node: lit, span: mk_sp(lo, p.last_span.hi)};
}
fn parse_path(p: parser) -> @ast::path {
fn parse_path_without_tps(p: parser) -> @ast::path {
let lo = p.span.lo;
let global = eat(p, token::MOD_SEP);
let mut ids = [parse_ident(p)];
while p.look_ahead(1u) != token::LT && eat(p, token::MOD_SEP) {
ids += [parse_ident(p)];
}
@{span: mk_sp(lo, p.last_span.hi), global: global, idents: ids, types: []}
@{span: mk_sp(lo, p.last_span.hi), global: global,
idents: ids, rp: none, types: []}
}
fn parse_value_path(p: parser) -> @ast::path {
let pt = parse_path(p);
let pt = parse_path_without_tps(p);
let last_word = vec::last(pt.idents);
if is_restricted_keyword(p, last_word) {
p.fatal("found " + last_word + " in expression position");
@ -549,16 +528,45 @@ fn parse_value_path(p: parser) -> @ast::path {
pt
}
fn parse_path_and_ty_param_substs(p: parser, colons: bool) -> @ast::path {
fn parse_path_with_tps(p: parser, colons: bool) -> @ast::path {
#debug["parse_path_with_tps(colons=%b)", colons];
let lo = p.span.lo;
let path = parse_path(p);
let b = if colons { eat(p, token::MOD_SEP) }
else { p.token == token::LT };
if b {
let seq = parse_seq_lt_gt(some(token::COMMA),
{|p| parse_ty(p, false)}, p);
@{span: mk_sp(lo, seq.span.hi), types: seq.node with *path}
} else { path }
let path = parse_path_without_tps(p);
if colons && !eat(p, token::MOD_SEP) {
ret path;
}
// Parse the region parameter, if any, which will
// be written "foo/&x"
let rp = {
// Hack: avoid parsing vstores like /@ and /~. This is painful
// because the notation for region bounds and the notation for vstores
// is... um... the same. I guess that's my fault. This is still not
// ideal as for str/& we end up parsing more than we ought to and have
// to sort it out later.
if p.token == token::BINOP(token::SLASH)
&& p.look_ahead(1u) == token::BINOP(token::AND) {
expect(p, token::BINOP(token::SLASH));
some(parse_region(p))
} else {
none
}
};
// Parse any type parameters which may appear:
let tps = {
if p.token == token::LT {
parse_seq_lt_gt(some(token::COMMA), {|p| parse_ty(p, false)}, p)
} else {
{node: [], span: path.span}
}
};
ret @{span: mk_sp(lo, tps.span.hi),
rp: rp,
types: tps.node with *path};
}
fn parse_mutability(p: parser) -> ast::mutability {
@ -803,7 +811,7 @@ fn parse_bottom_expr(p: parser) -> pexpr {
is_ident(p.token) && !is_keyword(p, "true") &&
!is_keyword(p, "false") {
check_restricted_keywords(p);
let pth = parse_path_and_ty_param_substs(p, true);
let pth = parse_path_with_tps(p, true);
hi = pth.span.hi;
ex = ast::expr_path(pth);
} else {
@ -850,7 +858,7 @@ fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
token::IDENT(_, _) {}
_ { p.fatal("expected a syntax expander name"); }
}
let pth = parse_path(p);
let pth = parse_path_without_tps(p);
//temporary for a backwards-compatible cycle:
let sep = seq_sep(token::COMMA);
let mut e = none;
@ -1424,7 +1432,7 @@ fn parse_pat(p: parser) -> @ast::pat {
else { none };
pat = ast::pat_ident(name, sub);
} else {
let enum_path = parse_path_and_ty_param_substs(p, true);
let enum_path = parse_path_with_tps(p, true);
hi = enum_path.span.hi;
let mut args: [@ast::pat] = [];
let mut star_pat = false;
@ -1779,24 +1787,39 @@ fn parse_method(p: parser, pr: ast::privacy) -> @ast::method {
}
fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo, ident = parse_ident(p),
tps = parse_ty_params(p), meths = parse_ty_methods(p);
let lo = p.last_span.lo, ident = parse_ident(p);
let rp = parse_region_param(p);
let tps = parse_ty_params(p);
let meths = parse_ty_methods(p);
ret mk_item(p, lo, p.last_span.hi, ident,
ast::item_iface(tps, meths), attrs);
ast::item_iface(tps, rp, meths), attrs);
}
// Parses three variants (with the initial params always optional):
// impl <T: copy> of to_str for [T] { ... }
// impl name<T> of to_str for [T] { ... }
// impl name<T> for [T] { ... }
// Parses three variants (with the region/type params always optional):
// impl /&<T: copy> of to_str for [T] { ... }
// impl name/&<T> of to_str for [T] { ... }
// impl name/&<T> for [T] { ... }
fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo;
let mut (ident, tps) = if !is_keyword(p, "of") {
if p.token == token::LT { (none, parse_ty_params(p)) }
else { (some(parse_ident(p)), parse_ty_params(p)) }
} else { (none, []) };
fn wrap_path(p: parser, pt: @ast::path) -> @ast::ty {
@{id: p.get_id(), node: ast::ty_path(pt, p.get_id()), span: pt.span}
}
let mut (ident, rp, tps) = {
if p.token == token::LT {
(none, ast::rp_none, parse_ty_params(p))
} else if p.token == token::BINOP(token::SLASH) {
(none, parse_region_param(p), parse_ty_params(p))
}
else if is_keyword(p, "of") {
(none, ast::rp_none, [])
} else {
let id = parse_ident(p);
let rp = parse_region_param(p);
(some(id), rp, parse_ty_params(p))
}
};
let ifce = if eat_keyword(p, "of") {
let path = parse_path_and_ty_param_substs(p, false);
let path = parse_path_with_tps(p, false);
if option::is_none(ident) {
ident = some(vec::last(path.idents));
}
@ -1812,7 +1835,7 @@ fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
expect(p, token::LBRACE);
while !eat(p, token::RBRACE) { meths += [parse_method(p, ast::pub)]; }
ret mk_item(p, lo, p.last_span.hi, ident,
ast::item_impl(tps, ifce, ty, meths), attrs);
ast::item_impl(tps, rp, ifce, ty, meths), attrs);
}
fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
@ -1842,21 +1865,32 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
attrs);
}
// 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 the return
// type of the ctor function.
fn ident_to_path_tys(p: parser, i: ast::ident,
rp: ast::region_param,
typarams: [ast::ty_param]) -> @ast::path {
let s = p.last_span;
// Hack. But then, this whole function is in service of a hack.
let a_r = alt rp {
ast::rp_none { none }
ast::rp_self { some(region_from_name(p, some("self"))) }
};
@{span: s, global: false, idents: [i],
rp: a_r,
types: vec::map(typarams, {|tp|
@{id: p.get_id(),
node: ast::ty_path(ident_to_path(s, tp.ident),
p.get_id()),
node: ast::ty_path(ident_to_path(s, tp.ident), p.get_id()),
span: s}})
}
}
fn parse_iface_ref(p:parser) -> @ast::iface_ref {
@{path: parse_path(p), id: p.get_id()}
@{path: parse_path_with_tps(p, false),
id: p.get_id()}
}
fn parse_iface_ref_list(p:parser) -> [@ast::iface_ref] {
@ -1869,7 +1903,7 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
let class_name = parse_value_ident(p);
let rp = parse_region_param(p);
let ty_params = parse_ty_params(p);
let class_path = ident_to_path_tys(p, class_name, ty_params);
let class_path = ident_to_path_tys(p, class_name, rp, ty_params);
let ifaces : [@ast::iface_ref] = if eat_keyword(p, "implements")
{ parse_iface_ref_list(p) }
else { [] };
@ -2240,7 +2274,7 @@ fn parse_view_path(p: parser) -> @ast::view_path {
path += [id];
}
let path = @{span: mk_sp(lo, p.span.hi), global: false,
idents: path, types: []};
idents: path, rp: none, types: []};
ret @spanned(lo, p.span.hi,
ast::view_path_simple(first_ident, path, p.get_id()));
}
@ -2264,7 +2298,8 @@ fn parse_view_path(p: parser) -> @ast::view_path {
seq_sep(token::COMMA),
parse_path_list_ident, p).node;
let path = @{span: mk_sp(lo, p.span.hi),
global: false, idents: path, types: []};
global: false, idents: path,
rp: none, types: []};
ret @spanned(lo, p.span.hi,
ast::view_path_list(path, idents, p.get_id()));
}
@ -2273,7 +2308,8 @@ fn parse_view_path(p: parser) -> @ast::view_path {
token::BINOP(token::STAR) {
p.bump();
let path = @{span: mk_sp(lo, p.span.hi),
global: false, idents: path, types: []};
global: false, idents: path,
rp: none, types: []};
ret @spanned(lo, p.span.hi,
ast::view_path_glob(path, p.get_id()));
}
@ -2286,7 +2322,7 @@ fn parse_view_path(p: parser) -> @ast::view_path {
}
let last = path[vec::len(path) - 1u];
let path = @{span: mk_sp(lo, p.span.hi), global: false,
idents: path, types: []};
idents: path, rp: none, types: []};
ret @spanned(lo, p.span.hi,
ast::view_path_simple(last, path, p.get_id()));
}

View file

@ -325,11 +325,14 @@ fn print_native_mod(s: ps, nmod: ast::native_mod, attrs: [ast::attribute]) {
for nmod.items.each {|item| print_native_item(s, item); }
}
fn print_region(s: ps, region: ast::region) {
fn print_region(s: ps, region: @ast::region) {
alt region.node {
ast::re_anon { /* no-op */ }
ast::re_named(name) { word(s.s, name); word(s.s, "."); }
ast::re_static { word(s.s, "static"); word(s.s, "."); }
ast::re_anon { word_space(s, "&"); }
ast::re_static { word_space(s, "&static"); }
ast::re_named(name) {
word(s.s, "&");
word_space(s, name);
}
}
}
@ -353,8 +356,10 @@ fn print_type(s: ps, &&ty: @ast::ty) {
}
ast::ty_ptr(mt) { word(s.s, "*"); print_mt(s, mt); }
ast::ty_rptr(region, mt) {
word(s.s, "&");
print_region(s, region);
alt region.node {
ast::re_anon { word(s.s, "&"); }
_ { print_region(s, region); word(s.s, "."); }
}
print_mt(s, mt);
}
ast::ty_rec(fields) {
@ -556,9 +561,10 @@ fn print_item(s: ps, &&item: @ast::item) {
}
bclose(s, item.span);
}
ast::item_impl(tps, ifce, ty, methods) {
ast::item_impl(tps, rp, 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|
@ -575,9 +581,10 @@ fn print_item(s: ps, &&item: @ast::item) {
}
bclose(s, item.span);
}
ast::item_iface(tps, methods) {
ast::item_iface(tps, rp, methods) {
head(s, "iface");
word(s.s, item.ident);
print_region_param(s, rp);
print_type_params(s, tps);
word(s.s, " ");
bopen(s);
@ -831,16 +838,7 @@ fn print_vstore(s: ps, t: ast::vstore) {
ast::vstore_fixed(none) { word_space(s, "/_"); }
ast::vstore_uniq { word_space(s, "/~"); }
ast::vstore_box { word_space(s, "/@"); }
ast::vstore_slice(r) {
alt r.node {
ast::re_anon { word_space(s, "/&"); }
ast::re_static { word_space(s, "/&static"); }
ast::re_named(name) {
word(s.s, "/&");
word_space(s, name);
}
}
}
ast::vstore_slice(r) { word(s.s, "/"); print_region(s, r); }
}
}
@ -1225,11 +1223,22 @@ fn print_path(s: ps, &&path: @ast::path, colons_before_params: bool) {
if first { first = false; } else { word(s.s, "::"); }
word(s.s, id);
}
if vec::len(path.types) > 0u {
if path.rp.is_some() || !path.types.is_empty() {
if colons_before_params { word(s.s, "::"); }
word(s.s, "<");
commasep(s, inconsistent, path.types, print_type);
word(s.s, ">");
alt path.rp {
none { /* ok */ }
some(r) {
word(s.s, "/");
print_region(s, r);
}
}
if !path.types.is_empty() {
word(s.s, "<");
commasep(s, inconsistent, path.types, print_type);
word(s.s, ">");
}
}
}

View file

@ -132,7 +132,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
for vr.node.args.each {|va| v.visit_ty(va.ty, e, v); }
}
}
item_impl(tps, ifce, ty, methods) {
item_impl(tps, _rp, 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);
@ -149,7 +149,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
visit_class_ctor_helper(ctor, i.ident, tps,
ast_util::local_def(i.id), e, v);
}
item_iface(tps, methods) {
item_iface(tps, _rp, 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); }

View file

@ -207,7 +207,7 @@ fn nospan<T: copy>(t: T) -> ast::spanned<T> {
}
fn path_node(ids: [ast::ident]) -> @ast::path {
@{span: dummy_sp(), global: false, idents: ids, types: []}
@{span: dummy_sp(), global: false, idents: ids, rp: none, types: []}
}
fn mk_tests(cx: test_ctxt) -> @ast::item {

View file

@ -185,14 +185,14 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
ebml_w.end_tag();
encode_enum_variant_paths(ebml_w, variants, path, index);
}
item_iface(_, _) {
item_iface(*) {
add_to_index(ebml_w, path, index, it.ident);
ebml_w.start_tag(tag_paths_data_item);
encode_name(ebml_w, it.ident);
encode_def_id(ebml_w, local_def(it.id));
ebml_w.end_tag();
}
item_impl(_, _, _, _) {}
item_impl(*) {}
}
}
}
@ -649,11 +649,12 @@ 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_impl(tps, ifce, _, methods) {
item_impl(tps, rp, 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_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);
@ -681,11 +682,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
should_inline(m.attrs), item.id, m, tps + m.tps);
}
}
item_iface(tps, ms) {
item_iface(tps, rp, 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_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);

View file

@ -104,7 +104,8 @@ fn parse_path(st: @pstate) -> @ast::path {
c {
if c == '(' {
ret @{span: ast_util::dummy_sp(),
global: false, idents: idents, types: []};
global: false, idents: idents,
rp: none, types: []};
} else { idents += [parse_ident_(st, is_last)]; }
}
}
@ -286,12 +287,11 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
ret ty::mk_enum(st.tcx, def, substs);
}
'x' {
assert (next(st) == '[');
assert next(st) == '[';
let def = parse_def(st, conv);
let mut params: [ty::t] = [];
while peek(st) != ']' { params += [parse_ty(st, conv)]; }
st.pos = st.pos + 1u;
ret ty::mk_iface(st.tcx, def, params);
let substs = parse_substs(st, conv);
assert next(st) == ']';
ret ty::mk_iface(st.tcx, def, substs);
}
'p' {
let did = parse_def(st, conv);
@ -299,10 +299,9 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
}
's' {
assert next(st) == '[';
let mut params = [];
while peek(st) != ']' { params += [parse_ty(st, conv)]; }
st.pos += 1u;
ret ty::mk_self(st.tcx, params);
let substs = parse_substs(st, conv);
assert next(st) == ']';
ret ty::mk_self(st.tcx, substs);
}
'@' { ret ty::mk_box(st.tcx, parse_mt(st, conv)); }
'~' { ret ty::mk_uniq(st.tcx, parse_mt(st, conv)); }
@ -344,7 +343,7 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
parse_ty_rust_fn(st, conv, proto)
}
'r' {
assert (next(st) == '[');
assert next(st) == '[';
let def = parse_def(st, conv);
let inner = parse_ty(st, conv);
let substs = parse_substs(st, conv);

View file

@ -220,11 +220,11 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
enc_substs(w, cx, substs);
w.write_char(']');
}
ty::ty_iface(def, tys) {
ty::ty_iface(def, substs) {
w.write_str("x["/&);
w.write_str(cx.ds(def));
w.write_char('|');
for tys.each {|t| enc_ty(w, cx, t); }
enc_substs(w, cx, substs);
w.write_char(']');
}
ty::ty_tup(ts) {
@ -281,9 +281,9 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
w.write_char('|');
w.write_str(uint::str(id));
}
ty::ty_self(tps) {
ty::ty_self(substs) {
w.write_str("s["/&);
for tps.each {|t| enc_ty(w, cx, t); }
enc_substs(w, cx, substs);
w.write_char(']');
}
ty::ty_type { w.write_char('Y'); }

View file

@ -177,7 +177,7 @@ fn map_item(i: @item, cx: ctx, v: vt) {
let item_path = @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);

View file

@ -15,6 +15,7 @@ import util::common::{indent, indenter};
export infer_ctxt;
export new_infer_ctxt;
export mk_subty;
export mk_subr;
export mk_eqty;
export mk_assignty;
export resolve_shallow;
@ -73,6 +74,11 @@ fn mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
indent {|| cx.commit {|| sub(cx).tys(a, b) } }.to_ures()
}
fn mk_subr(cx: infer_ctxt, a: ty::region, b: ty::region) -> ures {
#debug["mk_subr(%s <: %s)", a.to_str(cx), b.to_str(cx)];
indent {|| cx.commit {|| sub(cx).regions(a, b) } }.to_ures()
}
fn mk_eqty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
#debug["mk_eqty(%s <: %s)", a.to_str(cx), b.to_str(cx)];
indent {|| cx.commit {|| cx.eq_tys(a, b) } }.to_ures()
@ -1120,10 +1126,10 @@ fn super_tys<C:combine>(
}
}
(ty::ty_iface(a_id, a_tps), ty::ty_iface(b_id, b_tps))
(ty::ty_iface(a_id, a_substs), ty::ty_iface(b_id, b_substs))
if a_id == b_id {
self.tps(a_tps, b_tps).chain {|tps|
ok(ty::mk_iface(tcx, a_id, tps))
self.substs(a_substs, b_substs).chain {|substs|
ok(ty::mk_iface(tcx, a_id, substs))
}
}

View file

@ -435,14 +435,14 @@ fn resolve_names(e: @env, c: @ast::crate) {
non-class items
*/
alt i.node {
ast::item_class(_, ifaces, _, _, _) {
/* visit the iface paths... */
for ifaces.each {|p| resolve_iface_ref(p, sc, e)};
}
ast::item_impl(_, ifce, _, _) {
option::iter(ifce, {|p| resolve_iface_ref(p, sc, e)});
}
_ {}
ast::item_class(_, ifaces, _, _, _) {
/* visit the iface paths... */
for ifaces.each {|p| resolve_iface_ref(p, sc, e) ;}
}
ast::item_impl(_, _, ifce, _, _) {
ifce.iter { |p| resolve_iface_ref(p, sc, e); }
}
_ {}
}
}
@ -540,7 +540,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
let sc = cons(scope_item(i), @sc);
alt i.node {
ast::item_impl(tps, ifce, sty, methods) {
ast::item_impl(tps, _, ifce, sty, methods) {
visit::visit_ty_params(tps, sc, v);
option::iter(ifce) {|p| visit::visit_path(p.path, sc, v)};
v.visit_ty(sty, sc, v);
@ -551,7 +551,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
m.decl, m.body, m.span, m.id, msc, v);
}
}
ast::item_iface(tps, methods) {
ast::item_iface(tps, _, methods) {
visit::visit_ty_params(tps, sc, v);
for methods.each {|m|
let msc = cons(scope_method(i.id, tps + m.tps), @sc);
@ -1008,13 +1008,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, _) {
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
}
ast::item_iface(tps, _) {
ast::item_iface(tps, _, _) {
if ns == ns_type {
if name == "self" {
ret some(def_self(it.id));
@ -1286,7 +1286,7 @@ fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint,
fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
alt i.node {
ast::item_const(_, _) {
ast::item_const(*) {
if ns == ns_val {
ret some(ast::def_const(local_def(i.id))); }
}
@ -1301,7 +1301,7 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
ast::item_native_mod(_) {
if ns == ns_module { ret some(ast::def_native_mod(local_def(i.id))); }
}
ast::item_ty(_, _, _) | item_iface(_, _) | item_enum(_, _, _) {
ast::item_ty(*) | item_iface(*) | item_enum(*) {
if ns == ns_type { ret some(ast::def_ty(local_def(i.id))); }
}
ast::item_res(_, _, _, _, ctor_id, _) {
@ -1313,12 +1313,12 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
_ { }
}
}
ast::item_class(_, _, _, _, _) {
ast::item_class(*) {
if ns == ns_type {
ret some(ast::def_class(local_def(i.id)));
}
}
ast::item_impl(_,_,_,_) { /* ??? */ }
ast::item_impl(*) { /* ??? */ }
}
ret none;
}
@ -1607,8 +1607,7 @@ fn index_mod(md: ast::_mod) -> mod_index {
alt it.node {
ast::item_const(_, _) | ast::item_fn(_, _, _) | ast::item_mod(_) |
ast::item_native_mod(_) | ast::item_ty(_, _, _) |
ast::item_res(_, _, _, _, _, _) |
ast::item_impl(_, _, _, _) | ast::item_iface(_, _) {
ast::item_res(*) | ast::item_impl(*) | ast::item_iface(*) {
add_to_index(index, it.ident, mie_item(it));
}
ast::item_enum(variants, _, _) {
@ -1753,11 +1752,11 @@ 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_iface(_, methods) {
ast::item_iface(_, _, 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");
}
@ -1832,13 +1831,13 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
ast::item_mod(_) | ast::item_native_mod(_) {
add_name(mods, it.span, it.ident);
}
ast::item_const(_, _) | ast::item_fn(_, _, _) {
ast::item_const(_, _) | ast::item_fn(*) {
add_name(values, it.span, it.ident);
}
ast::item_ty(_, _, _) | ast::item_iface(_, _) {
ast::item_ty(*) | ast::item_iface(*) {
add_name(types, it.span, it.ident);
}
ast::item_res(_, _, _, _, _, _) {
ast::item_res(*) {
add_name(types, it.span, it.ident);
add_name(values, it.span, it.ident);
}
@ -2196,7 +2195,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) }

View file

@ -4477,7 +4477,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
}
}
}
ast::item_impl(tps, _, _, ms) {
ast::item_impl(tps, _rp, _, _, ms) {
impl::trans_impl(ccx, *path, item.ident, ms, tps);
}
ast::item_res(decl, tps, body, dtor_id, ctor_id, _) {

View file

@ -90,7 +90,7 @@ 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:

View file

@ -94,7 +94,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 {
@ -117,8 +117,8 @@ fn traverse_public_item(cx: ctx, item: @item) {
}
}
}
item_const(_, _) | item_ty(_, _, _) |
item_enum(_, _, _) | item_iface(_, _) {}
item_const(*) | item_ty(*) |
item_enum(*) | item_iface(*) {}
}
}

View file

@ -48,7 +48,7 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
}
item_mod(m) { find_pre_post_mod(m); }
item_native_mod(nm) { find_pre_post_native_mod(nm); }
item_ty(_, _, _) | item_enum(_, _, _) | item_iface(_, _) { ret; }
item_ty(*) | item_enum(*) | item_iface(*) { ret; }
item_res(_, _, body, dtor_id, _, _) {
let fcx =
{enclosing: ccx.fm.get(dtor_id),
@ -60,7 +60,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); }
}
}

View file

@ -325,14 +325,14 @@ enum sty {
ty_rptr(region, mt),
ty_rec([field]),
ty_fn(fn_ty),
ty_iface(def_id, [t]),
ty_iface(def_id, substs),
ty_class(def_id, substs),
ty_res(def_id, t, substs),
ty_tup([t]),
ty_var(ty_vid), // type variable during typechecking
ty_param(uint, def_id), // type parameter
ty_self([t]), // interface method self type
ty_self(substs), // interface method self type
ty_type, // type_desc*
ty_opaque_box, // used by monomorphizer to represent any @ box
@ -520,16 +520,10 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t {
ty_opaque_box {}
ty_param(_, _) { has_params = true; }
ty_var(_) | ty_self(_) { has_vars = true; }
ty_enum(_, substs) | ty_class(_, substs) {
ty_enum(_, substs) | ty_class(_, substs) | ty_iface(_, substs) {
derive_sflags(has_params, has_vars, has_regions,
has_resources, substs);
}
ty_iface(_, tys) {
for tys.each {|tt|
derive_flags(has_params, has_vars, has_regions,
has_resources, tt);
}
}
ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_evec(m, _) | ty_ptr(m) {
derive_flags(has_params, has_vars, has_regions,
has_resources, m.ty);
@ -652,8 +646,8 @@ fn mk_tup(cx: ctxt, ts: [t]) -> t { mk_t(cx, ty_tup(ts)) }
fn mk_fn(cx: ctxt, fty: fn_ty) -> t { mk_t(cx, ty_fn(fty)) }
fn mk_iface(cx: ctxt, did: ast::def_id, tys: [t]) -> t {
mk_t(cx, ty_iface(did, tys))
fn mk_iface(cx: ctxt, did: ast::def_id, substs: substs) -> t {
mk_t(cx, ty_iface(did, substs))
}
fn mk_class(cx: ctxt, class_id: ast::def_id, substs: substs) -> t {
@ -667,7 +661,7 @@ fn mk_res(cx: ctxt, did: ast::def_id,
fn mk_var(cx: ctxt, v: ty_vid) -> t { mk_t(cx, ty_var(v)) }
fn mk_self(cx: ctxt, tps: [t]) -> t { mk_t(cx, ty_self(tps)) }
fn mk_self(cx: ctxt, substs: substs) -> t { mk_t(cx, ty_self(substs)) }
fn mk_param(cx: ctxt, n: uint, k: def_id) -> t { mk_t(cx, ty_param(n, k)) }
@ -712,12 +706,10 @@ fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
ty_ptr(tm) | ty_rptr(_, tm) {
maybe_walk_ty(tm.ty, f);
}
ty_enum(_, substs) | ty_class(_, substs) {
ty_enum(_, substs) | ty_class(_, substs) |
ty_iface(_, substs) | ty_self(substs) {
for substs.tps.each {|subty| maybe_walk_ty(subty, f); }
}
ty_iface(_, subtys) |ty_self(subtys) {
for subtys.each {|subty| maybe_walk_ty(subty, f); }
}
ty_rec(fields) {
for fields.each {|fl| maybe_walk_ty(fl.mt.ty, f); }
}
@ -764,11 +756,11 @@ fn fold_sty(sty: sty, fldop: fn(t) -> t) -> sty {
ty_enum(tid, substs) {
ty_enum(tid, fold_substs(substs, fldop))
}
ty_iface(did, subtys) {
ty_iface(did, vec::map(subtys) {|t| fldop(t) })
ty_iface(did, substs) {
ty_iface(did, fold_substs(substs, fldop))
}
ty_self(subtys) {
ty_self(vec::map(subtys) {|t| fldop(t) })
ty_self(substs) {
ty_self(fold_substs(substs, fldop))
}
ty_rec(fields) {
let new_fields = vec::map(fields) {|fl|
@ -864,6 +856,12 @@ fn fold_regions_and_ty(
ty_class(def_id, substs) {
ty::mk_class(cx, def_id, fold_substs(substs, fldr, fldt))
}
ty_iface(def_id, substs) {
ty::mk_iface(cx, def_id, fold_substs(substs, fldr, fldt))
}
ty_self(substs) {
ty::mk_self(cx, fold_substs(substs, fldr, fldt))
}
ty_res(def_id, t, substs) {
ty::mk_res(cx, def_id, fldt(t),
fold_substs(substs, fldr, fldt))
@ -1828,10 +1826,8 @@ fn hash_type_structure(st: sty) -> uint {
}
ty_var(v) { hash_uint(30u, v.to_uint()) }
ty_param(pid, did) { hash_def(hash_uint(31u, pid), did) }
ty_self(ts) {
let mut h = 28u;
for ts.each {|t| h = hash_subty(h, t); }
h
ty_self(substs) {
hash_substs(28u, substs)
}
ty_type { 32u }
ty_bot { 34u }
@ -1850,10 +1846,9 @@ fn hash_type_structure(st: sty) -> uint {
h
}
ty_uniq(mt) { hash_subty(37u, mt.ty) }
ty_iface(did, tys) {
ty_iface(did, substs) {
let mut h = hash_def(40u, did);
for tys.each {|typ| h = hash_subty(h, typ); }
h
hash_substs(h, substs)
}
ty_opaque_closure_ptr(ck_block) { 41u }
ty_opaque_closure_ptr(ck_box) { 42u }
@ -2286,7 +2281,7 @@ fn impl_iface(cx: ctxt, id: ast::def_id) -> option<t> {
if id.crate == ast::local_crate {
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(_, _, _, _, _),

File diff suppressed because it is too large Load diff

View file

@ -134,12 +134,10 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
some(def_id) {
let cs = ast_map::path_to_str(ty::item_path(cx, def_id));
ret alt ty::get(typ).struct {
ty_enum(_, substs) | ty_res(_, _, substs) | ty_class(_, substs) {
ty_enum(_, substs) | ty_res(_, _, substs) | ty_class(_, substs) |
ty_iface(_, substs) {
parameterized(cx, cs, substs.self_r, substs.tps)
}
ty_iface(_, tps) {
parameterized(cx, cs, none, tps)
}
_ { cs }
};
}
@ -159,7 +157,6 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
ty_float(ast::ty_f) { "float" }
ty_float(t) { ast_util::float_ty_to_str(t) }
ty_str { "str" }
ty_self(ts) { parameterized(cx, "self", none, ts) }
ty_box(tm) { "@" + mt_to_str(cx, tm) }
ty_uniq(tm) { "~" + mt_to_str(cx, tm) }
ty_ptr(tm) { "*" + mt_to_str(cx, tm) }
@ -191,15 +188,18 @@ fn ty_to_str(cx: ctxt, typ: t) -> str {
ty_param(id, _) {
"'" + str::from_bytes([('a' as u8) + (id as u8)])
}
ty_self(substs) {
parameterized(cx, "self", substs.self_r, substs.tps)
}
ty_enum(did, substs) | ty_res(did, _, substs) | ty_class(did, substs) {
let path = ty::item_path(cx, did);
let base = ast_map::path_to_str(path);
parameterized(cx, base, substs.self_r, substs.tps)
}
ty_iface(did, tps) {
ty_iface(did, substs) {
let path = ty::item_path(cx, did);
let base = ast_map::path_to_str(path);
parameterized(cx, base, none, tps)
parameterized(cx, base, substs.self_r, substs.tps)
}
ty_evec(mt, vs) {
#fmt["[%s]/%s", mt_to_str(cx, mt),

View file

@ -204,14 +204,14 @@ fn merge_method_attrs(
let attrs: [(str, option<str>)] = astsrv::exec(srv) {|ctxt|
alt ctxt.ast_map.get(item_id) {
ast_map::node_item(@{
node: ast::item_iface(_, methods), _
node: ast::item_iface(_, _, methods), _
}, _) {
par::seqmap(methods) {|method|
(method.ident, attr_parser::parse_desc(method.attrs))
}
}
ast_map::node_item(@{
node: ast::item_impl(_, _, _, methods), _
node: ast::item_impl(_, _, _, _, methods), _
}, _) {
par::seqmap(methods) {|method|
(method.ident, attr_parser::parse_desc(method.attrs))

View file

@ -88,12 +88,12 @@ fn moddoc_from_mod(
resdoc_from_resource(itemdoc)
))
}
ast::item_iface(_, methods) {
ast::item_iface(_, _, methods) {
some(doc::ifacetag(
ifacedoc_from_iface(itemdoc, methods)
))
}
ast::item_impl(_, _, _, methods) {
ast::item_impl(_, _, _, _, methods) {
some(doc::impltag(
impldoc_from_impl(itemdoc, methods)
))

View file

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

View file

@ -197,7 +197,7 @@ fn get_method_sig(
astsrv::exec(srv) {|ctxt|
alt check ctxt.ast_map.get(item_id) {
ast_map::node_item(@{
node: ast::item_iface(_, methods), _
node: ast::item_iface(_, _, methods), _
}, _) {
alt check vec::find(methods) {|method|
method.ident == method_name
@ -212,7 +212,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
@ -247,7 +247,7 @@ fn fold_impl(
let (iface_ty, self_ty) = astsrv::exec(srv) {|ctxt|
alt ctxt.ast_map.get(doc.id()) {
ast_map::node_item(@{
node: ast::item_impl(_, iface_ty, self_ty, _), _
node: ast::item_impl(_, _, iface_ty, self_ty, _), _
}, _) {
let iface_ty = option::map(iface_ty) {|p|
pprust::path_to_str(p.path)

View file

@ -0,0 +1,8 @@
iface foo<T> { }
fn bar(x: foo<uint>) -> foo<int> {
ret (x as foo::<int>);
//!^ ERROR mismatched types: expected `foo<int>` but found `foo<uint>`
}
fn main() {}

View file

@ -0,0 +1,29 @@
fn main() {
let x: int<int>; //! ERROR Type parameters are not allowed on this type.
let x: i8<int>; //! ERROR Type parameters are not allowed on this type.
let x: i16<int>; //! ERROR Type parameters are not allowed on this type.
let x: i32<int>; //! ERROR Type parameters are not allowed on this type.
let x: i64<int>; //! ERROR Type parameters are not allowed on this type.
let x: uint<int>; //! ERROR Type parameters are not allowed on this type.
let x: u8<int>; //! ERROR Type parameters are not allowed on this type.
let x: u16<int>; //! ERROR Type parameters are not allowed on this type.
let x: u32<int>; //! ERROR Type parameters are not allowed on this type.
let x: u64<int>; //! ERROR Type parameters are not allowed on this type.
let x: float<int>; //! ERROR Type parameters are not allowed on this type.
let x: char<int>; //! ERROR Type parameters are not allowed on this type.
let x: int/&; //! ERROR Region parameters are not allowed on this type.
let x: i8/&; //! ERROR Region parameters are not allowed on this type.
let x: i16/&; //! ERROR Region parameters are not allowed on this type.
let x: i32/&; //! ERROR Region parameters are not allowed on this type.
let x: i64/&; //! ERROR Region parameters are not allowed on this type.
let x: uint/&; //! ERROR Region parameters are not allowed on this type.
let x: u8/&; //! ERROR Region parameters are not allowed on this type.
let x: u16/&; //! ERROR Region parameters are not allowed on this type.
let x: u32/&; //! ERROR Region parameters are not allowed on this type.
let x: u64/&; //! ERROR Region parameters are not allowed on this type.
let x: float/&; //! ERROR Region parameters are not allowed on this type.
let x: char/&; //! ERROR Region parameters are not allowed on this type.
}

View file

@ -0,0 +1,32 @@
// Check that explicit region bounds are allowed on the various
// nominal types (but not on other types) and that they are type
// checked.
enum an_enum/& { }
iface an_iface/& { }
class a_class/& { new() { } }
resource a_rsrc/&(_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`
}
fn a_fn2(e: an_iface/&a) -> an_iface/&b {
ret e; //! ERROR mismatched types: expected `an_iface/&b` but found `an_iface/&a`
}
fn a_fn3(e: a_class/&a) -> a_class/&b {
ret e; //! ERROR mismatched types: expected `a_class/&b` but found `a_class/&a`
}
fn a_fn4(e: a_rsrc/&a) -> a_rsrc/&b {
ret e; //! ERROR mismatched types: expected `a_rsrc/&b` but found `a_rsrc/&a`
}
fn a_fn5(e: int/&a) -> int/&b {
//!^ ERROR Region parameters are not allowed on this type.
//!^^ ERROR Region parameters are not allowed on this type.
ret e;
}
fn main() { }

View file

@ -0,0 +1,28 @@
type ctxt = { v: uint };
iface get_ctxt/& {
// Here the `&` is bound in the method definition:
fn get_ctxt() -> &ctxt;
}
type has_ctxt/& = { c: &ctxt };
impl/& of get_ctxt for has_ctxt {
// Here an error occurs because we used `&self` but
// the definition used `&`:
fn get_ctxt() -> &self.ctxt { //! ERROR method `get_ctxt` has an incompatible type
self.c
}
}
fn get_v(gc: get_ctxt) -> uint {
gc.get_ctxt().v
}
fn main() {
let ctxt = { v: 22u };
let hc = { c: &ctxt };
assert get_v(hc as get_ctxt) == 22u;
}

View file

@ -0,0 +1,21 @@
type ctxt = { v: uint };
iface get_ctxt/& {
fn get_ctxt() -> &self.ctxt;
}
type has_ctxt/& = { c: &ctxt };
impl/& of get_ctxt for has_ctxt {
fn get_ctxt() -> &self.ctxt { self.c }
}
fn make_gc() -> get_ctxt {
let ctxt = { v: 22u };
let hc = { c: &ctxt };
ret hc as get_ctxt; //! ERROR mismatched types: expected `get_ctxt/&`
}
fn main() {
make_gc().get_ctxt().v;
}

View file

@ -0,0 +1,14 @@
iface get_ctxt/& {
fn get_ctxt() -> &self.uint;
}
fn make_gc1(gc: get_ctxt/&a) -> get_ctxt/&b {
ret gc; //! ERROR mismatched types: expected `get_ctxt/&b` but found `get_ctxt/&a`
}
fn make_gc2(gc: get_ctxt/&a) -> get_ctxt/&b {
ret gc as get_ctxt; //! ERROR mismatched types: expected `get_ctxt/&b` but found `get_ctxt/&a`
}
fn main() {
}

View file

@ -1,4 +1,4 @@
// xfail-test it don't work yet
// xfail-test
fn foo(x: [uint]/&) -> uint {
x[0]

View file

@ -1,4 +1,5 @@
// xfail-test
fn foo(x: [int]/&) -> int {
x[0]
}

View file

@ -0,0 +1,23 @@
type ctxt = { v: uint };
iface get_ctxt/& {
fn get_ctxt() -> &self.ctxt;
}
type has_ctxt/& = { c: &ctxt };
impl/& of get_ctxt for has_ctxt {
fn get_ctxt() -> &self.ctxt {
self.c
}
}
fn get_v(gc: get_ctxt) -> uint {
gc.get_ctxt().v
}
fn main() {
let ctxt = { v: 22u };
let hc = { c: &ctxt };
assert get_v(hc as get_ctxt) == 22u;
}

View file

@ -1,9 +1,6 @@
// xfail-test
// ^ handling of self is currently broken
type clam/& = { chowder: &int };
type clam = { chowder: &int };
impl clam for clam {
impl clam/& for clam {
fn get_chowder() -> &self.int { ret self.chowder; }
}

View file

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