Skip to content

Commit 77d0a44

Browse files
committed
---
yaml --- r: 36060 b: refs/heads/try2 c: ec1c60c h: refs/heads/master v: v3
1 parent d42adde commit 77d0a44

File tree

10 files changed

+207
-46
lines changed

10 files changed

+207
-46
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: eb8fd119c65c67f3b1b8268cc7341c22d39b7b61
55
refs/heads/try: d324a424d8f84b1eb049b12cf34182bda91b0024
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 705afcd8445819c3f0493aa2befbe4788d9bb5ce
8+
refs/heads/try2: ec1c60c4d6b54d30c11c79e1fa51dc6cbee61223
99
refs/heads/incoming: d9317a174e434d4c99fc1a37fd7dc0d2f5328d37
1010
refs/heads/dist-snap: 22efa39382d41b084fde1719df7ae8ce5697d8c9
1111
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596

branches/try2/src/rustc/metadata/csearch.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export get_enum_variants;
2424
export get_impls_for_mod;
2525
export get_trait_methods;
2626
export get_provided_trait_methods;
27+
export get_supertraits;
2728
export get_method_names_if_trait;
2829
export get_type_name_if_impl;
2930
export get_static_methods_if_impl;
@@ -122,6 +123,12 @@ fn get_provided_trait_methods(tcx: ty::ctxt, def: ast::def_id) ->
122123
decoder::get_provided_trait_methods(cstore.intr, cdata, def.node, tcx)
123124
}
124125

126+
fn get_supertraits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] {
127+
let cstore = tcx.cstore;
128+
let cdata = cstore::get_crate_data(cstore, def.crate);
129+
decoder::get_supertraits(cdata, def.node, tcx)
130+
}
131+
125132
fn get_method_names_if_trait(cstore: cstore::CStore, def: ast::def_id)
126133
-> Option<@DVec<(ast::ident, ast::self_ty_)>> {
127134

branches/try2/src/rustc/metadata/decoder.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export get_crate_vers;
4343
export get_impls_for_mod;
4444
export get_trait_methods;
4545
export get_provided_trait_methods;
46+
export get_supertraits;
4647
export get_method_names_if_trait;
4748
export get_type_name_if_impl;
4849
export get_item_attrs;
@@ -771,6 +772,16 @@ fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
771772
return move result;
772773
}
773774

775+
/// Returns the supertraits of the given trait.
776+
fn get_supertraits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) -> ~[ty::t] {
777+
let results = dvec::DVec();
778+
let item_doc = lookup_item(id, cdata.data);
779+
for ebml::tagged_docs(item_doc, tag_impl_trait) |trait_doc| {
780+
results.push(doc_type(trait_doc, tcx, cdata));
781+
}
782+
return dvec::unwrap(move results);
783+
}
784+
774785
// If the item in question is a trait, returns its set of methods and
775786
// their self types. Otherwise, returns none. This overlaps in an
776787
// annoying way with get_trait_methods.

branches/try2/src/rustc/middle/ty.rs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use syntax::print::pprust::*;
2020
use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};
2121

2222
export ProvidedMethodSource;
23+
export InstantiatedTraitRef;
2324
export TyVid, IntVid, FnVid, RegionVid, vid;
2425
export br_hashmap;
2526
export is_instantiable;
@@ -66,13 +67,15 @@ export sequence_element_type;
6667
export stmt_node_id;
6768
export sty;
6869
export subst, subst_tps, substs_is_noop, substs_to_str, substs;
70+
export subst_substs;
6971
export t;
7072
export new_ty_hash;
7173
export enum_variants, substd_enum_variants, enum_is_univariant;
7274
export trait_methods, store_trait_methods, impl_traits;
7375
export enum_variant_with_id;
7476
export ty_dtor;
7577
export ty_param_bounds_and_ty;
78+
export ty_param_substs_and_ty;
7679
export ty_bool, mk_bool, type_is_bool;
7780
export ty_bot, mk_bot, type_is_bot;
7881
export ty_box, mk_box, mk_imm_box, type_is_box, type_is_boxed;
@@ -191,6 +194,7 @@ export region_variance, rv_covariant, rv_invariant, rv_contravariant;
191194
export opt_region_variance;
192195
export determine_inherited_purity;
193196
export provided_trait_methods;
197+
export trait_supertraits;
194198
export AutoAdjustment;
195199
export AutoRef, AutoRefKind, AutoSlice, AutoPtr;
196200

@@ -321,6 +325,11 @@ struct ProvidedMethodSource {
321325
impl_id: ast::def_id
322326
}
323327

328+
struct InstantiatedTraitRef {
329+
def_id: ast::def_id,
330+
tpt: ty_param_substs_and_ty
331+
}
332+
324333
type ctxt =
325334
@{diag: syntax::diagnostic::span_handler,
326335
interner: HashMap<intern_key, t_box>,
@@ -364,7 +373,8 @@ type ctxt =
364373
normalized_cache: HashMap<t, t>,
365374
lang_items: middle::lang_items::LanguageItems,
366375
legacy_boxed_traits: HashMap<node_id, ()>,
367-
provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>};
376+
provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>,
377+
supertraits: HashMap<ast::def_id, @~[InstantiatedTraitRef]>};
368378

369379
enum tbox_flag {
370380
has_params = 1,
@@ -819,6 +829,8 @@ type ty_param_bounds_and_ty = {bounds: @~[param_bounds],
819829
region_param: Option<region_variance>,
820830
ty: t};
821831

832+
type ty_param_substs_and_ty = {substs: ty::substs, ty: ty::t};
833+
822834
type type_cache = HashMap<ast::def_id, ty_param_bounds_and_ty>;
823835

824836
type constness_cache = HashMap<ast::def_id, const_eval::constness>;
@@ -888,7 +900,8 @@ fn mk_ctxt(s: session::Session,
888900
normalized_cache: new_ty_hash(),
889901
lang_items: move lang_items,
890902
legacy_boxed_traits: HashMap(),
891-
provided_method_sources: HashMap()}
903+
provided_method_sources: HashMap(),
904+
supertraits: HashMap()}
892905
}
893906

894907

@@ -1486,6 +1499,16 @@ fn subst(cx: ctxt,
14861499
}
14871500
}
14881501
1502+
// Performs substitutions on a set of substitutions (result = super(sub)) to
1503+
// yield a new set of substitutions. This is used in trait inheritance.
1504+
fn subst_substs(cx: ctxt, super: &substs, sub: &substs) -> substs {
1505+
{
1506+
self_r: super.self_r,
1507+
self_ty: super.self_ty.map(|typ| subst(cx, sub, *typ)),
1508+
tps: super.tps.map(|typ| subst(cx, sub, *typ))
1509+
}
1510+
}
1511+
14891512
// Type utilities
14901513
14911514
fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }
@@ -3365,6 +3388,35 @@ fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
33653388
}
33663389
}
33673390

3391+
fn trait_supertraits(cx: ctxt, id: ast::def_id) -> @~[InstantiatedTraitRef] {
3392+
// Check the cache.
3393+
match cx.supertraits.find(id) {
3394+
Some(instantiated_trait_info) => { return instantiated_trait_info; }
3395+
None => {} // Continue.
3396+
}
3397+
3398+
// Not in the cache. It had better be in the metadata, which means it
3399+
// shouldn't be local.
3400+
assert !is_local(id);
3401+
3402+
// Get the supertraits out of the metadata and create the
3403+
// InstantiatedTraitRef for each.
3404+
let result = dvec::DVec();
3405+
for csearch::get_supertraits(cx, id).each |trait_type| {
3406+
match get(*trait_type).sty {
3407+
ty_trait(def_id, substs, _) => {
3408+
result.push(InstantiatedTraitRef {
3409+
def_id: def_id,
3410+
tpt: { substs: substs, ty: *trait_type }
3411+
});
3412+
}
3413+
_ => cx.sess.bug(~"trait_supertraits: trait ref wasn't a trait")
3414+
}
3415+
}
3416+
3417+
// Unwrap and return the result.
3418+
return @dvec::unwrap(move result);
3419+
}
33683420

33693421
fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
33703422
match cx.trait_method_cache.find(id) {

branches/try2/src/rustc/middle/typeck.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use syntax::codemap::span;
5151
use pat_util::{pat_is_variant, pat_id_map, PatIdMap};
5252
use middle::ty;
5353
use middle::ty::{arg, field, node_type_table, mk_nil, ty_param_bounds_and_ty};
54-
use middle::ty::{vstore_uniq};
54+
use middle::ty::{ty_param_substs_and_ty, vstore_uniq};
5555
use std::smallintmap;
5656
use std::map;
5757
use std::map::HashMap;
@@ -174,8 +174,6 @@ impl vtable_origin {
174174

175175
type vtable_map = HashMap<ast::node_id, vtable_res>;
176176

177-
type ty_param_substs_and_ty = {substs: ty::substs, ty: ty::t};
178-
179177
type crate_ctxt_ = {// A mapping from method call sites to traits that have
180178
// that method.
181179
trait_map: resolve::TraitMap,

branches/try2/src/rustc/middle/typeck/check/method.rs

Lines changed: 66 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -313,45 +313,73 @@ impl LookupContext {
313313
}
314314
};
315315

316-
let trait_methods = ty::trait_methods(tcx, trait_id);
317-
let pos = {
318-
// FIXME #3453 can't use trait_methods.position
319-
match vec::position(*trait_methods,
320-
|m| (m.self_ty != ast::sty_static &&
321-
m.ident == self.m_name))
322-
{
323-
Some(pos) => pos,
324-
None => {
325-
loop; // check next bound
326-
}
316+
// Loop over the trait and all of its supertraits.
317+
let worklist = dvec::DVec();
318+
worklist.push((trait_id, move bound_substs));
319+
320+
let mut i = 0;
321+
while i < worklist.len() {
322+
let (trait_id, bound_substs) = worklist[i];
323+
i += 1;
324+
325+
// Replace any appearance of `self` with the type of the
326+
// generic parameter itself. Note that this is the only
327+
// case where this replacement is necessary: in all other
328+
// cases, we are either invoking a method directly from an
329+
// impl or class (where the self type is not permitted),
330+
// or from a trait type (in which case methods that refer
331+
// to self are not permitted).
332+
let rcvr_ty = ty::mk_param(tcx, param_ty.idx,
333+
param_ty.def_id);
334+
let rcvr_substs = {self_ty: Some(rcvr_ty), ..bound_substs};
335+
336+
// Add all the supertraits of this trait to the worklist.
337+
debug!("finding supertraits for %d:%d", trait_id.crate,
338+
trait_id.node);
339+
let instantiated_trait_refs = ty::trait_supertraits(
340+
tcx, trait_id);
341+
for instantiated_trait_refs.each |instantiated_trait_ref| {
342+
debug!("adding supertrait");
343+
344+
let new_substs = ty::subst_substs(
345+
tcx,
346+
&instantiated_trait_ref.tpt.substs,
347+
&rcvr_substs);
348+
349+
worklist.push(
350+
(instantiated_trait_ref.def_id, new_substs));
327351
}
328-
};
329-
let method = &trait_methods[pos];
330-
331-
// Replace any appearance of `self` with the type of the
332-
// generic parameter itself. Note that this is the only
333-
// case where this replacement is necessary: in all other
334-
// cases, we are either invoking a method directly from an
335-
// impl or class (where the self type is not permitted),
336-
// or from a trait type (in which case methods that refer
337-
// to self are not permitted).
338-
let rcvr_ty = ty::mk_param(tcx, param_ty.idx, param_ty.def_id);
339-
let rcvr_substs = {self_ty: Some(rcvr_ty), ..bound_substs};
340-
341-
let (rcvr_ty, rcvr_substs) =
342-
self.create_rcvr_ty_and_substs_for_method(
343-
method.self_ty, rcvr_ty, move rcvr_substs);
344-
345-
self.inherent_candidates.push(Candidate {
346-
rcvr_ty: rcvr_ty,
347-
rcvr_substs: rcvr_substs,
348-
num_method_tps: method.tps.len(),
349-
self_mode: get_mode_from_self_type(method.self_ty),
350-
origin: method_param({trait_id:trait_id,
351-
method_num:pos,
352-
param_num:param_ty.idx,
353-
bound_num:this_bound_idx})
354-
});
352+
353+
let trait_methods = ty::trait_methods(tcx, trait_id);
354+
let pos = {
355+
// FIXME #3453 can't use trait_methods.position
356+
match vec::position(*trait_methods,
357+
|m| (m.self_ty != ast::sty_static &&
358+
m.ident == self.m_name))
359+
{
360+
Some(pos) => pos,
361+
None => {
362+
loop; // check next trait or bound
363+
}
364+
}
365+
};
366+
let method = &trait_methods[pos];
367+
368+
let (rcvr_ty, rcvr_substs) =
369+
self.create_rcvr_ty_and_substs_for_method(
370+
method.self_ty, rcvr_ty, move rcvr_substs);
371+
372+
self.inherent_candidates.push(Candidate {
373+
rcvr_ty: rcvr_ty,
374+
rcvr_substs: rcvr_substs,
375+
num_method_tps: method.tps.len(),
376+
self_mode: get_mode_from_self_type(method.self_ty),
377+
origin: method_param({trait_id:trait_id,
378+
method_num:pos,
379+
param_num:param_ty.idx,
380+
bound_num:this_bound_idx})
381+
});
382+
}
355383
}
356384
}
357385

branches/try2/src/rustc/middle/typeck/collect.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ are represented as `ty_param()` instances.
2323
use astconv::{ast_conv, ty_of_fn_decl, ty_of_arg, ast_ty_to_ty};
2424
use ast_util::trait_method_to_ty_method;
2525
use rscope::*;
26-
use ty::{FnTyBase, FnMeta, FnSig};
26+
use ty::{FnTyBase, FnMeta, FnSig, InstantiatedTraitRef};
2727
use util::common::pluralize;
2828
use util::ppaux::bound_to_str;
2929

@@ -239,6 +239,21 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) {
239239
}
240240
}
241241

242+
fn ensure_supertraits(ccx: @crate_ctxt,
243+
id: ast::node_id,
244+
rp: Option<ty::region_variance>,
245+
trait_refs: &[@ast::trait_ref]) {
246+
if ccx.tcx.supertraits.contains_key(local_def(id)) { return; }
247+
248+
let instantiated = dvec::DVec();
249+
for trait_refs.each |trait_ref| {
250+
let (did, tpt) = instantiate_trait_ref(ccx, *trait_ref, rp);
251+
instantiated.push(InstantiatedTraitRef { def_id: did, tpt: tpt });
252+
}
253+
ccx.tcx.supertraits.insert(local_def(id),
254+
@dvec::unwrap(move instantiated));
255+
}
256+
242257
/**
243258
* Checks that a method from an impl/class conforms to the signature of
244259
* the same method as declared in the trait.
@@ -462,12 +477,13 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
462477
check_methods_against_trait(ccx, tps, rp, selfty, *t, cms);
463478
}
464479
}
465-
ast::item_trait(tps, _, trait_methods) => {
480+
ast::item_trait(tps, supertraits, trait_methods) => {
466481
let tpt = ty_of_item(ccx, it);
467482
debug!("item_trait(it.id=%d, tpt.ty=%s)",
468483
it.id, ty_to_str(tcx, tpt.ty));
469484
write_ty_to_tcx(tcx, it.id, tpt.ty);
470485
ensure_trait_methods(ccx, it.id, tpt.ty);
486+
ensure_supertraits(ccx, it.id, rp, supertraits);
471487

472488
let (_, provided_methods) = split_trait_methods(trait_methods);
473489
let {bounds, _} = mk_substs(ccx, tps, rp);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pub trait MyNum : Add<self,self>, Sub<self,self>, Mul<self,self> {
2+
}
3+
4+
pub impl int : MyNum {
5+
pure fn add(other: &int) -> int { self + *other }
6+
pure fn sub(other: &int) -> int { self - *other }
7+
pure fn mul(other: &int) -> int { self * *other }
8+
}
9+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// xfail-fast - check-fast doesn't understand aux-build
2+
// aux-build:trait_inheritance_overloading_xc.rs
3+
4+
extern mod trait_inheritance_overloading_xc;
5+
use trait_inheritance_overloading_xc::MyNum;
6+
7+
fn f<T:Copy MyNum>(x: T, y: T) -> (T, T, T) {
8+
return (x + y, x - y, x * y);
9+
}
10+
11+
fn main() {
12+
let (x, y) = (3, 5);
13+
let (a, b, c) = f(x, y);
14+
assert a == 8;
15+
assert b == -2;
16+
assert c == 15;
17+
}
18+
19+

0 commit comments

Comments
 (0)