Skip to content

Commit e71081e

Browse files
committed
Merge pull request #4101 from brson/bound-default-methods
Call default methods on bound typarams more correctly
2 parents 3bcc9de + 05e51e6 commit e71081e

10 files changed

+156
-36
lines changed

src/librustc/middle/trans/meth.rs

+53-8
Original file line numberDiff line numberDiff line change
@@ -309,20 +309,52 @@ fn trans_static_method_callee(bcx: block,
309309
}
310310
311311
fn method_from_methods(ms: ~[@ast::method], name: ast::ident)
312-
-> ast::def_id {
313-
local_def(option::get(vec::find(ms, |m| m.ident == name)).id)
312+
-> Option<ast::def_id> {
313+
ms.find(|m| m.ident == name).map(|m| local_def(m.id))
314314
}
315315
316316
fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
317317
name: ast::ident) -> ast::def_id {
318318
if impl_id.crate == ast::local_crate {
319319
match ccx.tcx.items.get(impl_id.node) {
320320
ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => {
321-
method_from_methods(ms, name)
321+
method_from_methods(ms, name).get()
322322
}
323323
ast_map::node_item(@{node:
324324
ast::item_class(struct_def, _), _}, _) => {
325-
method_from_methods(struct_def.methods, name)
325+
method_from_methods(struct_def.methods, name).get()
326+
}
327+
_ => fail ~"method_with_name"
328+
}
329+
} else {
330+
csearch::get_impl_method(ccx.sess.cstore, impl_id, name)
331+
}
332+
}
333+
334+
fn method_with_name_or_default(ccx: @crate_ctxt, impl_id: ast::def_id,
335+
name: ast::ident) -> ast::def_id {
336+
if impl_id.crate == ast::local_crate {
337+
match ccx.tcx.items.get(impl_id.node) {
338+
ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => {
339+
let did = method_from_methods(ms, name);
340+
if did.is_some() {
341+
return did.get();
342+
} else {
343+
// Look for a default method
344+
let pmm = ccx.tcx.provided_methods;
345+
match pmm.find(impl_id) {
346+
Some(pmis) => {
347+
for pmis.each |pmi| {
348+
if pmi.method_info.ident == name {
349+
debug!("XXX %?", pmi.method_info.did);
350+
return pmi.method_info.did;
351+
}
352+
}
353+
fail
354+
}
355+
None => fail
356+
}
357+
}
326358
}
327359
_ => fail ~"method_with_name"
328360
}
@@ -333,10 +365,22 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
333365
334366
fn method_ty_param_count(ccx: @crate_ctxt, m_id: ast::def_id,
335367
i_id: ast::def_id) -> uint {
368+
debug!("mythod_ty_param_count: m_id: %?, i_id: %?", m_id, i_id);
336369
if m_id.crate == ast::local_crate {
337-
match ccx.tcx.items.get(m_id.node) {
338-
ast_map::node_method(m, _, _) => vec::len(m.tps),
339-
_ => fail ~"method_ty_param_count"
370+
match ccx.tcx.items.find(m_id.node) {
371+
Some(ast_map::node_method(m, _, _)) => m.tps.len(),
372+
None => {
373+
match ccx.tcx.provided_method_sources.find(m_id) {
374+
Some(source) => {
375+
method_ty_param_count(ccx, source.method_id, source.impl_id)
376+
}
377+
None => fail
378+
}
379+
}
380+
Some(ast_map::node_trait_method(@ast::provided(@m), _, _)) => {
381+
m.tps.len()
382+
}
383+
e => fail fmt!("method_ty_param_count %?", e)
340384
}
341385
} else {
342386
csearch::get_type_param_count(ccx.sess.cstore, m_id) -
@@ -358,7 +402,8 @@ fn trans_monomorphized_callee(bcx: block,
358402
typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
359403
let ccx = bcx.ccx();
360404
let mname = ty::trait_methods(ccx.tcx, trait_id)[n_method].ident;
361-
let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
405+
let mth_id = method_with_name_or_default(
406+
bcx.ccx(), impl_did, mname);
362407
363408
// obtain the `self` value:
364409
let Result {bcx, val: llself_val} =

src/librustc/middle/ty.rs

+24
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#[warn(deprecated_pattern)];
1212

13+
use core::dvec::DVec;
1314
use std::{map, smallintmap};
1415
use result::Result;
1516
use std::map::HashMap;
@@ -27,8 +28,11 @@ use middle::lint::{get_lint_level, allow};
2728
use syntax::ast::*;
2829
use syntax::print::pprust::*;
2930
use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};
31+
use middle::resolve::{Impl, MethodInfo};
3032

3133
export ProvidedMethodSource;
34+
export ProvidedMethodInfo;
35+
export ProvidedMethodsMap;
3236
export InstantiatedTraitRef;
3337
export TyVid, IntVid, FloatVid, FnVid, RegionVid, vid;
3438
export br_hashmap;
@@ -352,6 +356,21 @@ enum AutoRefKind {
352356
AutoBorrowFn,
353357
}
354358

359+
// Stores information about provided methods (a.k.a. default methods) in
360+
// implementations.
361+
//
362+
// This is a map from ID of each implementation to the method info and trait
363+
// method ID of each of the default methods belonging to the trait that that
364+
// implementation implements.
365+
type ProvidedMethodsMap = HashMap<def_id,@DVec<@ProvidedMethodInfo>>;
366+
367+
// Stores the method info and definition ID of the associated trait method for
368+
// each instantiation of each provided method.
369+
struct ProvidedMethodInfo {
370+
method_info: @MethodInfo,
371+
trait_method_def_id: def_id
372+
}
373+
355374
struct ProvidedMethodSource {
356375
method_id: ast::def_id,
357376
impl_id: ast::def_id
@@ -416,6 +435,10 @@ type ctxt =
416435
normalized_cache: HashMap<t, t>,
417436
lang_items: middle::lang_items::LanguageItems,
418437
legacy_boxed_traits: HashMap<node_id, ()>,
438+
// A mapping from an implementation ID to the method info and trait method
439+
// ID of the provided (a.k.a. default) methods in the traits that that
440+
// implementation implements.
441+
provided_methods: ProvidedMethodsMap,
419442
provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>,
420443
supertraits: HashMap<ast::def_id, @~[InstantiatedTraitRef]>,
421444
deriving_struct_methods: HashMap<ast::def_id, @~[DerivedFieldInfo]>,
@@ -975,6 +998,7 @@ fn mk_ctxt(s: session::Session,
975998
normalized_cache: new_ty_hash(),
976999
lang_items: move lang_items,
9771000
legacy_boxed_traits: HashMap(),
1001+
provided_methods: HashMap(),
9781002
provided_method_sources: HashMap(),
9791003
supertraits: HashMap(),
9801004
deriving_struct_methods: HashMap(),

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ obtained the type `Foo`, we would never match this method.
7979
8080
*/
8181

82-
use coherence::{ProvidedMethodInfo, get_base_type_def_id};
82+
use coherence::get_base_type_def_id;
8383
use middle::resolve::{Impl, MethodInfo};
8484
use middle::ty::*;
8585
use syntax::ast::{def_id, sty_by_ref, sty_value, sty_region, sty_box,
@@ -313,7 +313,7 @@ impl LookupContext {
313313
}
314314

315315
// Look for default methods.
316-
match coherence_info.provided_methods.find(*trait_did) {
316+
match self.tcx().provided_methods.find(*trait_did) {
317317
Some(methods) => {
318318
self.push_candidates_from_provided_methods(
319319
&self.extension_candidates, self_ty, *trait_did,

src/librustc/middle/typeck/coherence.rs

+4-25
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use metadata::csearch::{get_impls_for_mod};
1919
use metadata::cstore::{CStore, iter_crate_data};
2020
use metadata::decoder::{dl_def, dl_field, dl_impl};
2121
use middle::resolve::{Impl, MethodInfo};
22-
use middle::ty::{DerivedMethodInfo, ProvidedMethodSource, get};
22+
use middle::ty::{DerivedMethodInfo, ProvidedMethodSource, ProvidedMethodInfo, get};
2323
use middle::ty::{lookup_item_type, subst, t, ty_bot, ty_box, ty_class};
2424
use middle::ty::{ty_bool, ty_enum, ty_int, ty_nil, ty_ptr, ty_rptr, ty_uint};
2525
use middle::ty::{ty_float, ty_estr, ty_evec, ty_rec, ty_uniq};
@@ -130,21 +130,6 @@ fn method_to_MethodInfo(ast_method: @method) -> @MethodInfo {
130130
}
131131
}
132132

133-
// Stores the method info and definition ID of the associated trait method for
134-
// each instantiation of each provided method.
135-
struct ProvidedMethodInfo {
136-
method_info: @MethodInfo,
137-
trait_method_def_id: def_id
138-
}
139-
140-
// Stores information about provided methods (a.k.a. default methods) in
141-
// implementations.
142-
//
143-
// This is a map from ID of each implementation to the method info and trait
144-
// method ID of each of the default methods belonging to the trait that that
145-
// implementation implements.
146-
type ProvidedMethodsMap = HashMap<def_id,@DVec<@ProvidedMethodInfo>>;
147-
148133
struct CoherenceInfo {
149134
// Contains implementations of methods that are inherent to a type.
150135
// Methods in these implementations don't need to be exported.
@@ -154,17 +139,12 @@ struct CoherenceInfo {
154139
// the associated trait must be imported at the call site.
155140
extension_methods: HashMap<def_id,@DVec<@Impl>>,
156141

157-
// A mapping from an implementation ID to the method info and trait method
158-
// ID of the provided (a.k.a. default) methods in the traits that that
159-
// implementation implements.
160-
provided_methods: ProvidedMethodsMap,
161142
}
162143

163144
fn CoherenceInfo() -> CoherenceInfo {
164145
CoherenceInfo {
165146
inherent_methods: HashMap(),
166147
extension_methods: HashMap(),
167-
provided_methods: HashMap(),
168148
}
169149
}
170150

@@ -350,7 +330,7 @@ impl CoherenceChecker {
350330
trait_method_def_id: trait_method.def_id
351331
};
352332

353-
let pmm = self.crate_context.coherence_info.provided_methods;
333+
let pmm = self.crate_context.tcx.provided_methods;
354334
match pmm.find(local_def(impl_id)) {
355335
Some(mis) => {
356336
// If the trait already has an entry in the
@@ -765,8 +745,7 @@ impl CoherenceChecker {
765745
let trait_did =
766746
self.trait_ref_to_trait_def_id(*trait_ref);
767747

768-
match self.crate_context
769-
.coherence_info
748+
match self.crate_context.tcx
770749
.provided_methods
771750
.find(local_def(item.id)) {
772751
None => {
@@ -925,7 +904,7 @@ impl CoherenceChecker {
925904

926905
fn add_default_methods_for_external_trait(trait_def_id: ast::def_id) {
927906
let tcx = self.crate_context.tcx;
928-
let pmm = self.crate_context.coherence_info.provided_methods;
907+
let pmm = tcx.provided_methods;
929908

930909
if pmm.contains_key(trait_def_id) { return; }
931910

src/librustc/middle/typeck/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ export vtable_origin;
8888
export method_static, method_param, method_trait, method_self;
8989
export vtable_static, vtable_param, vtable_trait;
9090
export provided_methods_map;
91+
export coherence;
9192

9293
#[legacy_exports]
9394
#[path = "check/mod.rs"]
@@ -380,7 +381,7 @@ fn check_for_main_fn(ccx: @crate_ctxt) {
380381
fn check_crate(tcx: ty::ctxt,
381382
trait_map: resolve::TraitMap,
382383
crate: @ast::crate)
383-
-> (method_map, vtable_map) {
384+
-> (method_map, vtable_map) {
384385

385386
let ccx = @crate_ctxt_({trait_map: trait_map,
386387
method_map: std::map::HashMap(),
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+
}
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+
}
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+
}
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+
}
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)