Skip to content

Commit f764128

Browse files
committed
Allow classes to be cast to ifaces that are in the same crate
I had to xfail one existing test case (class-implements-int) because, I think, of the same bug described in #2272.
1 parent 1c39fda commit f764128

23 files changed

+562
-162
lines changed

src/libcore/vec.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ fn map<T, U>(v: [T], f: fn(T) -> U) -> [U] {
448448
}
449449

450450
#[doc = "
451-
Apply a function eo each element of a vector and return a concatenation
451+
Apply a function to each element of a vector and return a concatenation
452452
of each result vector
453453
"]
454454
fn flat_map<T, U>(v: [T], f: fn(T) -> [U]) -> [U] {

src/librustsyntax/ast.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,10 @@ enum attr_style { attr_outer, attr_inner, }
636636
#[auto_serialize]
637637
type attribute_ = {style: attr_style, value: meta_item};
638638

639+
/*
640+
iface_refs appear in both impls and in classes that implement ifaces.
641+
resolve maps each iface_ref's id to its defining iface.
642+
*/
639643
#[auto_serialize]
640644
type iface_ref = {path: @path, id: node_id};
641645

@@ -661,14 +665,14 @@ enum item_ {
661665
node_id /* dtor id */, node_id /* ctor id */,
662666
region_param),
663667
item_class([ty_param], /* ty params for class */
664-
[iface_ref], /* ifaces this class implements */
668+
[@iface_ref], /* ifaces this class implements */
665669
[@class_member], /* methods, etc. */
666670
/* (not including ctor) */
667671
class_ctor,
668672
region_param
669673
),
670674
item_iface([ty_param], [ty_method]),
671-
item_impl([ty_param], option<@ty> /* iface */,
675+
item_impl([ty_param], option<@iface_ref> /* iface */,
672676
@ty /* self */, [@method]),
673677
}
674678

src/librustsyntax/ast_util.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ import codemap::span;
22
import ast::*;
33

44
fn spanned<T: copy>(lo: uint, hi: uint, t: T) -> spanned<T> {
5-
ret respan(mk_sp(lo, hi), t);
5+
respan(mk_sp(lo, hi), t)
66
}
77

88
fn respan<T: copy>(sp: span, t: T) -> spanned<T> {
9-
ret {node: t, span: sp};
9+
{node: t, span: sp}
1010
}
1111

1212
fn dummy_spanned<T: copy>(t: T) -> spanned<T> {
13-
ret respan(dummy_sp(), t);
13+
respan(dummy_sp(), t)
1414
}
1515

1616
/* assuming that we're not in macro expansion */
1717
fn mk_sp(lo: uint, hi: uint) -> span {
18-
ret {lo: lo, hi: hi, expn_info: none};
18+
{lo: lo, hi: hi, expn_info: none}
1919
}
2020

2121
// make this a const, once the compiler supports it
@@ -334,6 +334,16 @@ impl inlined_item_methods for inlined_item {
334334
}
335335
}
336336
}
337+
338+
/* True if d is either a def_self, or a chain of def_upvars
339+
referring to a def_self */
340+
fn is_self(d: ast::def) -> bool {
341+
alt d {
342+
def_self(_) { true }
343+
def_upvar(_, d, _) { is_self(*d) }
344+
_ { false }
345+
}
346+
}
337347
// Local Variables:
338348
// mode: rust
339349
// fill-column: 78;

src/librustsyntax/fold.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,7 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
279279
let ctor_id = fld.new_id(ctor.node.id);
280280
item_class(
281281
typms,
282-
vec::map(ifaces, {|p|
283-
{path: fld.fold_path(p.path),
284-
id: fld.new_id(p.id)}}),
282+
vec::map(ifaces, {|p| fold_iface_ref(p, fld) }),
285283
vec::map(items, fld.fold_class_item),
286284
{node: {body: ctor_body,
287285
dec: ctor_decl,
@@ -290,7 +288,8 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
290288
rp)
291289
}
292290
item_impl(tps, ifce, ty, methods) {
293-
item_impl(tps, option::map(ifce, fld.fold_ty), fld.fold_ty(ty),
291+
item_impl(tps, option::map(ifce, {|p| fold_iface_ref(p, fld)}),
292+
fld.fold_ty(ty),
294293
vec::map(methods, fld.fold_method))
295294
}
296295
item_iface(tps, methods) { item_iface(tps, methods) }
@@ -305,6 +304,10 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
305304
};
306305
}
307306

307+
fn fold_iface_ref(&&p: @iface_ref, fld: ast_fold) -> @iface_ref {
308+
@{path: fld.fold_path(p.path), id: fld.new_id(p.id)}
309+
}
310+
308311
fn noop_fold_method(&&m: @method, fld: ast_fold) -> @method {
309312
ret @{ident: fld.fold_ident(m.ident),
310313
attrs: m.attrs,

src/librustsyntax/parse/parser.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import token::{can_begin_expr, is_ident, is_plain_ident};
55
import codemap::{span,fss_none};
66
import util::interner;
77
import ast_util::{spanned, mk_sp, ident_to_path};
8+
import ast::{node_id};
89
import lexer::reader;
910
import prec::{op_spec, as_prec};
1011
import attr::{parse_outer_attrs_or_ext,
@@ -1788,9 +1789,6 @@ fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
17881789
// impl name<T> for [T] { ... }
17891790
fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
17901791
let lo = p.last_span.lo;
1791-
fn wrap_path(p: parser, pt: @ast::path) -> @ast::ty {
1792-
@{id: p.get_id(), node: ast::ty_path(pt, p.get_id()), span: pt.span}
1793-
}
17941792
let mut (ident, tps) = if !is_word(p, "of") {
17951793
if p.token == token::LT { (none, parse_ty_params(p)) }
17961794
else { (some(parse_ident(p)), parse_ty_params(p)) }
@@ -1800,7 +1798,7 @@ fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
18001798
if option::is_none(ident) {
18011799
ident = some(vec::last(path.idents));
18021800
}
1803-
some(wrap_path(p, path))
1801+
some(@{path: path, id: p.get_id()})
18041802
} else { none };
18051803
let ident = alt ident {
18061804
some(name) { name }
@@ -1855,9 +1853,13 @@ fn ident_to_path_tys(p: parser, i: ast::ident,
18551853
}
18561854
}
18571855

1858-
fn parse_iface_ref_list(p:parser) -> [ast::iface_ref] {
1856+
fn parse_iface_ref(p:parser) -> @ast::iface_ref {
1857+
@{path: parse_path(p), id: p.get_id()}
1858+
}
1859+
1860+
fn parse_iface_ref_list(p:parser) -> [@ast::iface_ref] {
18591861
parse_seq_to_before_end(token::LBRACE, seq_sep(token::COMMA),
1860-
{|p| {path: parse_path(p), id: p.get_id()}}, p)
1862+
parse_iface_ref, p)
18611863
}
18621864

18631865
fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
@@ -1866,7 +1868,7 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
18661868
let rp = parse_region_param(p);
18671869
let ty_params = parse_ty_params(p);
18681870
let class_path = ident_to_path_tys(p, class_name, ty_params);
1869-
let ifaces : [ast::iface_ref] = if eat_word(p, "implements")
1871+
let ifaces : [@ast::iface_ref] = if eat_word(p, "implements")
18701872
{ parse_iface_ref_list(p) }
18711873
else { [] };
18721874
expect(p, token::LBRACE);
@@ -1918,7 +1920,7 @@ fn parse_single_class_item(p: parser, privcy: ast::privacy)
19181920
enum class_contents { ctor_decl(ast::fn_decl, ast::blk, codemap::span),
19191921
members([@ast::class_member]) }
19201922

1921-
fn parse_class_item(p:parser, class_name_with_tps:@ast::path)
1923+
fn parse_class_item(p:parser, class_name_with_tps: @ast::path)
19221924
-> class_contents {
19231925
if eat_word(p, "new") {
19241926
let lo = p.last_span.lo;

src/librustsyntax/print/pprust.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -561,14 +561,11 @@ fn print_item(s: ps, &&item: @ast::item) {
561561
word(s.s, item.ident);
562562
print_type_params(s, tps);
563563
space(s.s);
564-
alt ifce {
565-
some(ty) {
564+
option::iter(ifce, {|p|
566565
word_nbsp(s, "of");
567-
print_type(s, ty);
566+
print_path(s, p.path, false);
568567
space(s.s);
569-
}
570-
_ {}
571-
}
568+
});
572569
word_nbsp(s, "for");
573570
print_type(s, ty);
574571
space(s.s);

src/librustsyntax/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
134134
}
135135
item_impl(tps, ifce, ty, methods) {
136136
v.visit_ty_params(tps, e, v);
137-
alt ifce { some(ty) { v.visit_ty(ty, e, v); } none {} }
137+
option::iter(ifce, {|p| visit_path(p.path, e, v)});
138138
v.visit_ty(ty, e, v);
139139
for methods.each {|m|
140140
visit_method_helper(m, e, v)

src/rustc/metadata/csearch.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,9 @@ fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
160160
ret {bounds: @[], rp: ast::rp_none, ty: ty};
161161
}
162162

163-
fn get_impl_iface(tcx: ty::ctxt, def: ast::def_id)
164-
-> option<ty::t> {
163+
// Given a def_id for an impl or class, return the iface it implements,
164+
// or none if it's not for an impl or for a class that implements ifaces
165+
fn get_impl_iface(tcx: ty::ctxt, def: ast::def_id) -> option<ty::t> {
165166
let cstore = tcx.sess.cstore;
166167
let cdata = cstore::get_crate_data(cstore, def.crate);
167168
decoder::get_impl_iface(cdata, def.node, tcx)

src/rustc/metadata/decoder.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ export get_class_method;
2727
export get_impl_method;
2828
export lookup_def;
2929
export lookup_item_name;
30-
export get_impl_iface;
3130
export resolve_path;
3231
export get_crate_attributes;
3332
export list_crate_metadata;
@@ -157,11 +156,9 @@ fn item_impl_iface(item: ebml::doc, tcx: ty::ctxt, cdata: cmd)
157156
-> option<ty::t> {
158157
let mut result = none;
159158
ebml::tagged_docs(item, tag_impl_iface) {|ity|
160-
let t = parse_ty_data(ity.data, cdata.cnum, ity.start, tcx, {|did|
161-
translate_def_id(cdata, did)
162-
});
163-
result = some(t);
164-
}
159+
result = some(parse_ty_data(ity.data, cdata.cnum, ity.start, tcx,
160+
{|did| translate_def_id(cdata, did)}));
161+
};
165162
result
166163
}
167164

src/rustc/metadata/encoder.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -659,9 +659,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
659659
}
660660
alt ifce {
661661
some(t) {
662-
let i_ty = alt check t.node {
663-
ty_path(_, id) { ty::node_id_to_type(tcx, id) }
664-
};
662+
let i_ty = ty::node_id_to_type(tcx, t.id);
665663
ebml_w.start_tag(tag_impl_iface);
666664
write_type(ecx, ebml_w, i_ty);
667665
ebml_w.end_tag();

src/rustc/middle/ast_map.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -204,16 +204,16 @@ fn map_item(i: @item, cx: ctx, v: vt) {
204204
cx.map.insert(nitem.id, node_native_item(nitem, abi, @cx.path));
205205
}
206206
}
207-
item_class(_, _, items, ctor, _) {
207+
item_class(tps, ifces, items, ctor, _) {
208+
let (_, ms) = ast_util::split_class_items(items);
209+
// Map iface refs to their parent classes. This is
210+
// so we can find the self_ty
211+
vec::iter(ifces) {|p| cx.map.insert(p.id,
212+
node_item(i, item_path)); };
208213
let d_id = ast_util::local_def(i.id);
209214
let p = extend(cx, i.ident);
210-
for items.each {|ci|
211215
// only need to handle methods
212-
alt ci.node {
213-
class_method(m) { map_method(d_id, p, m, cx); }
214-
_ {}
215-
}
216-
}
216+
vec::iter(ms) {|m| map_method(d_id, p, m, cx); }
217217
}
218218
_ { }
219219
}

src/rustc/middle/resolve.rs

+39-10
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import metadata::{csearch, cstore};
99
import driver::session::session;
1010
import util::common::*;
1111
import std::map::{int_hash, str_hash, hashmap};
12+
import vec::each;
1213
import syntax::codemap::span;
1314
import syntax::visit;
1415
import visit::vt;
@@ -402,6 +403,11 @@ fn maybe_insert(e: @env, id: node_id, def: option<def>) {
402403
}
403404
}
404405

406+
fn resolve_iface_ref(p: @iface_ref, sc: scopes, e: @env) {
407+
maybe_insert(e, p.id,
408+
lookup_path_strict(*e, sc, p.path.span, p.path, ns_type));
409+
}
410+
405411
fn resolve_names(e: @env, c: @ast::crate) {
406412
e.used_imports.track = true;
407413
let v =
@@ -431,9 +437,10 @@ fn resolve_names(e: @env, c: @ast::crate) {
431437
alt i.node {
432438
ast::item_class(_, ifaces, _, _, _) {
433439
/* visit the iface paths... */
434-
for ifaces.each {|p|
435-
maybe_insert(e, p.id,
436-
lookup_path_strict(*e, sc, p.path.span, p.path, ns_type))};
440+
for ifaces.each {|p| resolve_iface_ref(p, sc, e)};
441+
}
442+
ast::item_impl(_, ifce, _, _) {
443+
option::iter(ifce, {|p| resolve_iface_ref(p, sc, e)});
437444
}
438445
_ {}
439446
}
@@ -535,7 +542,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
535542
alt i.node {
536543
ast::item_impl(tps, ifce, sty, methods) {
537544
visit::visit_ty_params(tps, sc, v);
538-
alt ifce { some(ty) { v.visit_ty(ty, sc, v); } _ {} }
545+
option::iter(ifce) {|p| visit::visit_path(p.path, sc, v)};
539546
v.visit_ty(sty, sc, v);
540547
for methods.each {|m|
541548
v.visit_ty_params(m.tps, sc, v);
@@ -1109,20 +1116,20 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace,
11091116
}
11101117
ret some(df);
11111118
}
1112-
_ {}
1113-
}
1114-
if left_fn {
1115-
left_fn_level2 = true;
1116-
} else if ns != ns_module {
1119+
_ {}
1120+
}
1121+
if left_fn {
1122+
left_fn_level2 = true;
1123+
} else if ns != ns_module {
11171124
left_fn = scope_is_fn(hd);
11181125
alt scope_closes(hd) {
11191126
some(node_id) { closing += [node_id]; }
11201127
_ { }
11211128
}
11221129
}
11231130
sc = *tl;
1124-
}
11251131
}
1132+
}
11261133
};
11271134
}
11281135

@@ -2103,6 +2110,8 @@ fn check_exports(e: @env) {
21032110
// Impl resolution
21042111

21052112
type method_info = {did: def_id, n_tps: uint, ident: ast::ident};
2113+
/* what are the did and ident here? */
2114+
/* ident = the name of the impl */
21062115
type _impl = {did: def_id, ident: ast::ident, methods: [@method_info]};
21072116
type iscopes = list<@[@_impl]>;
21082117

@@ -2177,6 +2186,12 @@ fn find_impls_in_view_item(e: env, vi: @ast::view_item,
21772186
}
21782187
}
21792188

2189+
/*
2190+
Given an item <i>, adds one record to the mutable vec
2191+
<impls> if the item is an impl; zero or more records if the
2192+
item is a class; and none otherwise. Each record describes
2193+
one interface implemented by i.
2194+
*/
21802195
fn find_impls_in_item(e: env, i: @ast::item, &impls: [@_impl],
21812196
name: option<ident>,
21822197
ck_exports: option<@indexed_mod>) {
@@ -2196,6 +2211,20 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: [@_impl],
21962211
})}];
21972212
}
21982213
}
2214+
ast::item_class(tps, ifces, items, _, _) {
2215+
let (_, mthds) = ast_util::split_class_items(items);
2216+
let n_tps = tps.len();
2217+
vec::iter(ifces) {|p|
2218+
// The def_id, in this case, identifies the combination of
2219+
// class and iface
2220+
impls += [@{did: local_def(p.id),
2221+
ident: i.ident,
2222+
methods: vec::map(mthds, {|m|
2223+
@{did: local_def(m.id),
2224+
n_tps: n_tps + m.tps.len(),
2225+
ident: m.ident}})}];
2226+
}
2227+
}
21992228
_ {}
22002229
}
22012230
}

src/rustc/middle/trans/alt.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ fn enter_opt(tcx: ty::ctxt, m: match, opt: opt, col: uint,
164164
alt p.node {
165165
ast::pat_enum(_, subpats) {
166166
if opt_eq(tcx, variant_opt(tcx, p.id), opt) {
167-
some(option::get_or_default(subpats,
167+
some(option::get_default(subpats,
168168
vec::from_elem(variant_size, dummy))) }
169169
else { none }
170170
}

src/rustc/middle/trans/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1963,7 +1963,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
19631963
let mono_ty = ty::subst_tps(ccx.tcx, substs, item_ty);
19641964
let llfty = type_of_fn_from_ty(ccx, mono_ty);
19651965

1966-
let depth = option::get_or_default(ccx.monomorphizing.find(fn_id), 0u);
1966+
let depth = option::get_default(ccx.monomorphizing.find(fn_id), 0u);
19671967
// Random cut-off -- code that needs to instantiate the same function
19681968
// recursively more than ten times can probably safely be assumed to be
19691969
// causing an infinite expansion.

0 commit comments

Comments
 (0)