Skip to content

Commit 05e51e6

Browse files
committed
Call default methods on bound typarams more correctly
1 parent bde2dcc commit 05e51e6

10 files changed

+156
-36
lines changed

src/librustc/middle/trans/meth.rs

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -294,20 +294,52 @@ fn trans_static_method_callee(bcx: block,
294294
}
295295
296296
fn method_from_methods(ms: ~[@ast::method], name: ast::ident)
297-
-> ast::def_id {
298-
local_def(option::get(vec::find(ms, |m| m.ident == name)).id)
297+
-> Option<ast::def_id> {
298+
ms.find(|m| m.ident == name).map(|m| local_def(m.id))
299299
}
300300
301301
fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
302302
name: ast::ident) -> ast::def_id {
303303
if impl_id.crate == ast::local_crate {
304304
match ccx.tcx.items.get(impl_id.node) {
305305
ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => {
306-
method_from_methods(ms, name)
306+
method_from_methods(ms, name).get()
307307
}
308308
ast_map::node_item(@{node:
309309
ast::item_class(struct_def, _), _}, _) => {
310-
method_from_methods(struct_def.methods, name)
310+
method_from_methods(struct_def.methods, name).get()
311+
}
312+
_ => fail ~"method_with_name"
313+
}
314+
} else {
315+
csearch::get_impl_method(ccx.sess.cstore, impl_id, name)
316+
}
317+
}
318+
319+
fn method_with_name_or_default(ccx: @crate_ctxt, impl_id: ast::def_id,
320+
name: ast::ident) -> ast::def_id {
321+
if impl_id.crate == ast::local_crate {
322+
match ccx.tcx.items.get(impl_id.node) {
323+
ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => {
324+
let did = method_from_methods(ms, name);
325+
if did.is_some() {
326+
return did.get();
327+
} else {
328+
// Look for a default method
329+
let pmm = ccx.tcx.provided_methods;
330+
match pmm.find(impl_id) {
331+
Some(pmis) => {
332+
for pmis.each |pmi| {
333+
if pmi.method_info.ident == name {
334+
debug!("XXX %?", pmi.method_info.did);
335+
return pmi.method_info.did;
336+
}
337+
}
338+
fail
339+
}
340+
None => fail
341+
}
342+
}
311343
}
312344
_ => fail ~"method_with_name"
313345
}
@@ -318,10 +350,22 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
318350
319351
fn method_ty_param_count(ccx: @crate_ctxt, m_id: ast::def_id,
320352
i_id: ast::def_id) -> uint {
353+
debug!("mythod_ty_param_count: m_id: %?, i_id: %?", m_id, i_id);
321354
if m_id.crate == ast::local_crate {
322-
match ccx.tcx.items.get(m_id.node) {
323-
ast_map::node_method(m, _, _) => vec::len(m.tps),
324-
_ => fail ~"method_ty_param_count"
355+
match ccx.tcx.items.find(m_id.node) {
356+
Some(ast_map::node_method(m, _, _)) => m.tps.len(),
357+
None => {
358+
match ccx.tcx.provided_method_sources.find(m_id) {
359+
Some(source) => {
360+
method_ty_param_count(ccx, source.method_id, source.impl_id)
361+
}
362+
None => fail
363+
}
364+
}
365+
Some(ast_map::node_trait_method(@ast::provided(@m), _, _)) => {
366+
m.tps.len()
367+
}
368+
e => fail fmt!("method_ty_param_count %?", e)
325369
}
326370
} else {
327371
csearch::get_type_param_count(ccx.sess.cstore, m_id) -
@@ -343,7 +387,8 @@ fn trans_monomorphized_callee(bcx: block,
343387
typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
344388
let ccx = bcx.ccx();
345389
let mname = ty::trait_methods(ccx.tcx, trait_id)[n_method].ident;
346-
let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
390+
let mth_id = method_with_name_or_default(
391+
bcx.ccx(), impl_did, mname);
347392
348393
// obtain the `self` value:
349394
let Result {bcx, val: llself_val} =

src/librustc/middle/ty.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#[warn(deprecated_pattern)];
22

3+
use core::dvec::DVec;
34
use std::{map, smallintmap};
45
use result::Result;
56
use std::map::HashMap;
@@ -17,8 +18,11 @@ use middle::lint::{get_lint_level, allow};
1718
use syntax::ast::*;
1819
use syntax::print::pprust::*;
1920
use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};
21+
use middle::resolve::{Impl, MethodInfo};
2022

2123
export ProvidedMethodSource;
24+
export ProvidedMethodInfo;
25+
export ProvidedMethodsMap;
2226
export InstantiatedTraitRef;
2327
export TyVid, IntVid, FloatVid, FnVid, RegionVid, vid;
2428
export br_hashmap;
@@ -331,6 +335,21 @@ enum AutoRefKind {
331335
AutoBorrowFn,
332336
}
333337

338+
// Stores information about provided methods (a.k.a. default methods) in
339+
// implementations.
340+
//
341+
// This is a map from ID of each implementation to the method info and trait
342+
// method ID of each of the default methods belonging to the trait that that
343+
// implementation implements.
344+
type ProvidedMethodsMap = HashMap<def_id,@DVec<@ProvidedMethodInfo>>;
345+
346+
// Stores the method info and definition ID of the associated trait method for
347+
// each instantiation of each provided method.
348+
struct ProvidedMethodInfo {
349+
method_info: @MethodInfo,
350+
trait_method_def_id: def_id
351+
}
352+
334353
struct ProvidedMethodSource {
335354
method_id: ast::def_id,
336355
impl_id: ast::def_id
@@ -395,6 +414,10 @@ type ctxt =
395414
normalized_cache: HashMap<t, t>,
396415
lang_items: middle::lang_items::LanguageItems,
397416
legacy_boxed_traits: HashMap<node_id, ()>,
417+
// A mapping from an implementation ID to the method info and trait method
418+
// ID of the provided (a.k.a. default) methods in the traits that that
419+
// implementation implements.
420+
provided_methods: ProvidedMethodsMap,
398421
provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>,
399422
supertraits: HashMap<ast::def_id, @~[InstantiatedTraitRef]>,
400423
deriving_struct_methods: HashMap<ast::def_id, @~[DerivedFieldInfo]>,
@@ -951,6 +974,7 @@ fn mk_ctxt(s: session::Session,
951974
normalized_cache: new_ty_hash(),
952975
lang_items: move lang_items,
953976
legacy_boxed_traits: HashMap(),
977+
provided_methods: HashMap(),
954978
provided_method_sources: HashMap(),
955979
supertraits: HashMap(),
956980
deriving_struct_methods: HashMap(),

src/librustc/middle/typeck/check/method.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ obtained the type `Foo`, we would never match this method.
6969
7070
*/
7171

72-
use coherence::{ProvidedMethodInfo, get_base_type_def_id};
72+
use coherence::get_base_type_def_id;
7373
use middle::resolve::{Impl, MethodInfo};
7474
use middle::ty::*;
7575
use syntax::ast::{def_id, sty_by_ref, sty_value, sty_region, sty_box,
@@ -293,7 +293,7 @@ impl LookupContext {
293293
}
294294

295295
// Look for default methods.
296-
match coherence_info.provided_methods.find(*trait_did) {
296+
match self.tcx().provided_methods.find(*trait_did) {
297297
Some(methods) => {
298298
self.push_candidates_from_provided_methods(
299299
&self.extension_candidates, self_ty, *trait_did,

src/librustc/middle/typeck/coherence.rs

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use metadata::csearch::{get_impls_for_mod};
99
use metadata::cstore::{CStore, iter_crate_data};
1010
use metadata::decoder::{dl_def, dl_field, dl_impl};
1111
use middle::resolve::{Impl, MethodInfo};
12-
use middle::ty::{DerivedMethodInfo, ProvidedMethodSource, get};
12+
use middle::ty::{DerivedMethodInfo, ProvidedMethodSource, ProvidedMethodInfo, get};
1313
use middle::ty::{lookup_item_type, subst, t, ty_bot, ty_box, ty_class};
1414
use middle::ty::{ty_bool, ty_enum, ty_int, ty_nil, ty_ptr, ty_rptr, ty_uint};
1515
use middle::ty::{ty_float, ty_estr, ty_evec, ty_rec, ty_uniq};
@@ -120,21 +120,6 @@ fn method_to_MethodInfo(ast_method: @method) -> @MethodInfo {
120120
}
121121
}
122122

123-
// Stores the method info and definition ID of the associated trait method for
124-
// each instantiation of each provided method.
125-
struct ProvidedMethodInfo {
126-
method_info: @MethodInfo,
127-
trait_method_def_id: def_id
128-
}
129-
130-
// Stores information about provided methods (a.k.a. default methods) in
131-
// implementations.
132-
//
133-
// This is a map from ID of each implementation to the method info and trait
134-
// method ID of each of the default methods belonging to the trait that that
135-
// implementation implements.
136-
type ProvidedMethodsMap = HashMap<def_id,@DVec<@ProvidedMethodInfo>>;
137-
138123
struct CoherenceInfo {
139124
// Contains implementations of methods that are inherent to a type.
140125
// Methods in these implementations don't need to be exported.
@@ -144,17 +129,12 @@ struct CoherenceInfo {
144129
// the associated trait must be imported at the call site.
145130
extension_methods: HashMap<def_id,@DVec<@Impl>>,
146131

147-
// A mapping from an implementation ID to the method info and trait method
148-
// ID of the provided (a.k.a. default) methods in the traits that that
149-
// implementation implements.
150-
provided_methods: ProvidedMethodsMap,
151132
}
152133

153134
fn CoherenceInfo() -> CoherenceInfo {
154135
CoherenceInfo {
155136
inherent_methods: HashMap(),
156137
extension_methods: HashMap(),
157-
provided_methods: HashMap(),
158138
}
159139
}
160140

@@ -340,7 +320,7 @@ impl CoherenceChecker {
340320
trait_method_def_id: trait_method.def_id
341321
};
342322

343-
let pmm = self.crate_context.coherence_info.provided_methods;
323+
let pmm = self.crate_context.tcx.provided_methods;
344324
match pmm.find(local_def(impl_id)) {
345325
Some(mis) => {
346326
// If the trait already has an entry in the
@@ -755,8 +735,7 @@ impl CoherenceChecker {
755735
let trait_did =
756736
self.trait_ref_to_trait_def_id(*trait_ref);
757737

758-
match self.crate_context
759-
.coherence_info
738+
match self.crate_context.tcx
760739
.provided_methods
761740
.find(local_def(item.id)) {
762741
None => {
@@ -915,7 +894,7 @@ impl CoherenceChecker {
915894

916895
fn add_default_methods_for_external_trait(trait_def_id: ast::def_id) {
917896
let tcx = self.crate_context.tcx;
918-
let pmm = self.crate_context.coherence_info.provided_methods;
897+
let pmm = tcx.provided_methods;
919898

920899
if pmm.contains_key(trait_def_id) { return; }
921900

src/librustc/middle/typeck/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export vtable_origin;
7878
export method_static, method_param, method_trait, method_self;
7979
export vtable_static, vtable_param, vtable_trait;
8080
export provided_methods_map;
81+
export coherence;
8182

8283
#[legacy_exports]
8384
#[path = "check/mod.rs"]
@@ -367,7 +368,7 @@ fn check_for_main_fn(ccx: @crate_ctxt) {
367368
fn check_crate(tcx: ty::ctxt,
368369
trait_map: resolve::TraitMap,
369370
crate: @ast::crate)
370-
-> (method_map, vtable_map) {
371+
-> (method_map, vtable_map) {
371372

372373
let ccx = @crate_ctxt_({trait_map: trait_map,
373374
method_map: std::map::HashMap(),
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// xfail-test
2+
3+
trait A<T> {
4+
fn g<U>(x: T, y: U) -> (T, U) { (move x, move y) }
5+
}
6+
7+
impl int: A<int> { }
8+
9+
fn f<T, U, V: A<T>>(i: V, j: T, k: U) -> (T, U) {
10+
i.g(move j, move k)
11+
}
12+
13+
fn main () {
14+
assert f(0, 1, 2) == (1, 2);
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// xfail-test
2+
3+
trait A<T> {
4+
fn g(x: T) -> T { move x }
5+
}
6+
7+
impl int: A<int> { }
8+
9+
fn f<T, V: A<T>>(i: V, j: T) -> T {
10+
i.g(move j)
11+
}
12+
13+
fn main () {
14+
assert f(0, 2) == 2;
15+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
trait A {
2+
fn g<T>(x: T, y: T) -> (T, T) { (move x, move y) }
3+
}
4+
5+
impl int: A { }
6+
7+
fn f<T, V: A>(i: V, j: T, k: T) -> (T, T) {
8+
i.g(move j, move k)
9+
}
10+
11+
fn main () {
12+
assert f(0, 1, 2) == (1, 2);
13+
assert f(0, 1u8, 2u8) == (1u8, 2u8);
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
trait A<T> {
2+
fn g(x: uint) -> uint { move x }
3+
}
4+
5+
impl<T> int: A<T> { }
6+
7+
fn f<T, V: A<T>>(i: V, j: uint) -> uint {
8+
i.g(move j)
9+
}
10+
11+
fn main () {
12+
assert f::<float, int>(0, 2u) == 2u;
13+
assert f::<uint, int>(0, 2u) == 2u;
14+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
trait A {
2+
fn g() -> int { 10 }
3+
}
4+
5+
impl int: A { }
6+
7+
fn f<T: A>(i: T) {
8+
assert i.g() == 10;
9+
}
10+
11+
fn main () {
12+
f(0);
13+
}

0 commit comments

Comments
 (0)