Skip to content

Commit 5ea3c96

Browse files
committed
Wire in resolution of param bounds for method calls
Issue #1227
1 parent 506a6ec commit 5ea3c96

File tree

3 files changed

+61
-15
lines changed

3 files changed

+61
-15
lines changed

src/comp/middle/ty.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1462,8 +1462,6 @@ fn constrs_eq(cs: [@constr], ds: [@constr]) -> bool {
14621462
// Type lookups
14631463
fn node_id_to_ty_param_substs_opt_and_ty(cx: ctxt, id: ast::node_id) ->
14641464
ty_param_substs_opt_and_ty {
1465-
1466-
14671465
// Pull out the node type table.
14681466
alt smallintmap::find(*cx.node_types, id as uint) {
14691467
none. {

src/comp/middle/typeck.rs

+39-13
Original file line numberDiff line numberDiff line change
@@ -2875,11 +2875,21 @@ type dict_map = hashmap<ast::node_id, dict_res>;
28752875
// Detect points where an interface-bounded type parameter is instantiated,
28762876
// resolve the impls for the parameters.
28772877
fn resolve_dicts(tcx: ty::ctxt, impl_map: resolve::impl_map,
2878-
crate: @ast::crate) -> dict_map {
2878+
method_map: method_map, crate: @ast::crate) -> dict_map {
28792879
type ccx = {tcx: ty::ctxt,
28802880
impl_map: resolve::impl_map,
2881+
method_map: method_map,
28812882
dict_map: dict_map};
2882-
let cx = {tcx: tcx, impl_map: impl_map, dict_map: new_int_hash()};
2883+
let cx = {tcx: tcx, impl_map: impl_map,
2884+
method_map: method_map, dict_map: new_int_hash()};
2885+
2886+
fn has_iface_bounds(tps: [ty::param_bounds]) -> bool {
2887+
vec::any(tps, {|bs|
2888+
vec::any(*bs, {|b|
2889+
alt b { ty::bound_iface(_) { true } _ { false } }
2890+
})
2891+
})
2892+
}
28832893
fn resolve_expr(ex: @ast::expr, cx: ccx, v: visit::vt<ccx>) {
28842894
alt ex.node {
28852895
ast::expr_path(_) {
@@ -2889,14 +2899,25 @@ fn resolve_dicts(tcx: ty::ctxt, impl_map: resolve::impl_map,
28892899
some(ts) {
28902900
let did = ast_util::def_id_of_def(cx.tcx.def_map.get(ex.id));
28912901
let item_ty = ty::lookup_item_type(cx.tcx, did);
2892-
if vec::any(*item_ty.bounds, {|bs|
2893-
vec::any(*bs, {|b|
2894-
alt b { ty::bound_iface(_) { true } _ { false } }
2895-
})
2896-
}) {
2902+
if has_iface_bounds(*item_ty.bounds) {
28972903
let impls = cx.impl_map.get(ex.id);
28982904
cx.dict_map.insert(ex.id, lookup_dicts(
2899-
cx.tcx, impls, ex.span, *item_ty.bounds, ts));
2905+
cx.tcx, impls, ex.span, item_ty.bounds, ts));
2906+
}
2907+
}
2908+
_ {}
2909+
}
2910+
}
2911+
// Must resolve bounds on methods with bounded params
2912+
ast::expr_field(_, _, _) {
2913+
alt cx.method_map.find(ex.id) {
2914+
some(method_static(did)) {
2915+
let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
2916+
if has_iface_bounds(*bounds) {
2917+
let tys = ty::node_id_to_type_params(cx.tcx, ex.id);
2918+
let iscs = cx.impl_map.get(ex.id);
2919+
cx.dict_map.insert(ex.id, lookup_dicts(
2920+
cx.tcx, iscs, ex.span, bounds, tys));
29002921
}
29012922
}
29022923
_ {}
@@ -2906,8 +2927,9 @@ fn resolve_dicts(tcx: ty::ctxt, impl_map: resolve::impl_map,
29062927
}
29072928
visit::visit_expr(ex, cx, v);
29082929
}
2930+
29092931
fn lookup_dicts(tcx: ty::ctxt, isc: resolve::iscopes, sp: span,
2910-
bounds: [ty::param_bounds], tys: [ty::t])
2932+
bounds: @[ty::param_bounds], tys: [ty::t])
29112933
-> dict_res {
29122934
let result = [], i = 0u;
29132935
for ty in tys {
@@ -2923,6 +2945,7 @@ fn resolve_dicts(tcx: ty::ctxt, impl_map: resolve::impl_map,
29232945
}
29242946
@result
29252947
}
2948+
29262949
fn lookup_dict(tcx: ty::ctxt, isc: resolve::iscopes, sp: span,
29272950
ty: ty::t, iface_ty: ty::t) -> dict_origin {
29282951
let iface_id = alt ty::struct(tcx, iface_ty) {
@@ -2951,6 +2974,7 @@ fn resolve_dicts(tcx: ty::ctxt, impl_map: resolve::impl_map,
29512974
for im in *impls {
29522975
if im.iface_did == some(iface_id) {
29532976
let self_ty = impl_self_ty(tcx, im.did).ty;
2977+
let im_bs = ty::lookup_item_type(tcx, im.did).bounds;
29542978
let params = @mutable [mutable];
29552979
alt ty::unify::unify(ty, self_ty,
29562980
ty::unify::bind_params(params),
@@ -2963,9 +2987,10 @@ fn resolve_dicts(tcx: ty::ctxt, impl_map: resolve::impl_map,
29632987
} else {
29642988
let params = vec::map_mut(
29652989
*params, {|p| option::get(p)});
2966-
// FIXME[impl] check for sub-bounds
2967-
found = some(dict_static(
2968-
im.did, params, @[]));
2990+
let subres = lookup_dicts(tcx, isc, sp,
2991+
im_bs, params);
2992+
found = some(dict_static(im.did, params,
2993+
subres));
29692994
}
29702995
}
29712996
_ {}
@@ -2985,6 +3010,7 @@ fn resolve_dicts(tcx: ty::ctxt, impl_map: resolve::impl_map,
29853010
ty_to_str(tcx, iface_ty) + " for " +
29863011
ty_to_str(tcx, ty));
29873012
}
3013+
29883014
visit::visit_crate(*crate, cx, visit::mk_vt(@{
29893015
visit_expr: resolve_expr
29903016
with *visit::default_visitor()
@@ -3006,7 +3032,7 @@ fn check_crate(tcx: ty::ctxt, impl_map: resolve::impl_map,
30063032
bind check_native_item(ccx, _)
30073033
with *visit::default_simple_visitor()});
30083034
visit::visit_crate(*crate, (), visit);
3009-
let dict_map = resolve_dicts(tcx, impl_map, crate);
3035+
let dict_map = resolve_dicts(tcx, impl_map, ccx.method_map, crate);
30103036
check_for_main_fn(tcx, crate);
30113037
tcx.sess.abort_if_errors();
30123038
(ccx.method_map, dict_map)

src/test/run-pass/iface-to-str.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
iface to_str {
2+
fn to_str() -> str;
3+
}
4+
5+
impl of to_str for int {
6+
fn to_str() -> str { int::str(self) }
7+
}
8+
9+
impl <T: to_str> of to_str for [T] {
10+
fn to_str() -> str {
11+
"[" + str::connect(vec::map(self, {|e| e.to_str()}), ", ") + "]"
12+
}
13+
}
14+
15+
fn main() {
16+
fn indirect<T: to_str>(x: T) -> str {
17+
x.to_str() + "!"
18+
}
19+
assert 1.to_str() == "1";
20+
assert [2, 3, 4].to_str() == "[2, 3, 4]";
21+
assert indirect([10, 20]) == "[10, 20]!";
22+
}

0 commit comments

Comments
 (0)