Skip to content

Commit 94d40be

Browse files
committed
Prevent typenames in param bounds from resolving to their own param
I.e. fn foo<T: seq<T>>(...). This leads to weird circularities that seem to never make any sense, so it seems prudent to forbid it. Issue #1227
1 parent 42f6608 commit 94d40be

File tree

2 files changed

+38
-19
lines changed

2 files changed

+38
-19
lines changed

src/comp/middle/resolve.rs

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ type env =
142142
mutable data: [ast::node_id]},
143143
mutable reported: [{ident: str, sc: scope}],
144144
mutable ignored_imports: [node_id],
145+
mutable current_tp: option::t<uint>,
145146
sess: session};
146147

147148

@@ -168,6 +169,7 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
168169
used_imports: {mutable track: false, mutable data: []},
169170
mutable reported: [],
170171
mutable ignored_imports: [],
172+
mutable current_tp: none,
171173
sess: sess};
172174
map_crate(e, crate);
173175
resolve_imports(*e);
@@ -336,6 +338,7 @@ fn resolve_names(e: @env, c: @ast::crate) {
336338
visit_pat: bind walk_pat(e, _, _, _),
337339
visit_expr: bind walk_expr(e, _, _, _),
338340
visit_ty: bind walk_ty(e, _, _, _),
341+
visit_ty_params: bind walk_tps(e, _, _, _),
339342
visit_constr: bind walk_constr(e, _, _, _, _, _),
340343
visit_fn: bind visit_fn_with_scope(e, _, _, _, _, _, _, _)
341344
with *visit::default_visitor()};
@@ -369,6 +372,20 @@ fn resolve_names(e: @env, c: @ast::crate) {
369372
_ { }
370373
}
371374
}
375+
fn walk_tps(e: @env, tps: [ast::ty_param], sc: scopes, v: vt<scopes>) {
376+
let outer_current_tp = e.current_tp, current = 0u;
377+
for tp in tps {
378+
e.current_tp = some(current);
379+
for bound in *tp.bounds {
380+
alt bound {
381+
bound_iface(t) { v.visit_ty(t, sc, v); }
382+
_ {}
383+
}
384+
}
385+
current += 1u;
386+
}
387+
e.current_tp = outer_current_tp;
388+
}
372389
fn walk_constr(e: @env, p: @ast::path, sp: span, id: node_id, sc: scopes,
373390
_v: vt<scopes>) {
374391
maybe_insert(e, id, lookup_path_strict(*e, sc, sp, p.node, ns_value));
@@ -806,14 +823,14 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
806823
scope_item(it) {
807824
alt it.node {
808825
ast::item_obj(ob, ty_params, _) {
809-
ret lookup_in_obj(name, ob, ty_params, ns, it.id);
826+
ret lookup_in_obj(e, name, ob, ty_params, ns, it.id);
810827
}
811-
ast::item_impl(ty_params, _, _, _) {
812-
if ns == ns_type { ret lookup_in_ty_params(name, ty_params); }
828+
ast::item_impl(tps, _, _, _) {
829+
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
813830
}
814831
ast::item_iface(tps, _) | ast::item_tag(_, tps) |
815832
ast::item_ty(_, tps) {
816-
if ns == ns_type { ret lookup_in_ty_params(name, tps); }
833+
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
817834
}
818835
ast::item_mod(_) {
819836
ret lookup_in_local_mod(e, it.id, sp, name, ns, inside);
@@ -828,19 +845,19 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
828845
if (name == "self" && ns == ns_value) {
829846
ret some(ast::def_self(local_def(id)));
830847
} else if ns == ns_type {
831-
ret lookup_in_ty_params(name, tps);
848+
ret lookup_in_ty_params(e, name, tps);
832849
}
833850
}
834851
scope_native_item(it) {
835852
alt it.node {
836853
ast::native_item_fn(decl, ty_params) {
837-
ret lookup_in_fn(name, decl, ty_params, ns);
854+
ret lookup_in_fn(e, name, decl, ty_params, ns);
838855
}
839856
}
840857
}
841858
scope_bare_fn(decl, _, ty_params) |
842859
scope_fn_expr(decl, _, ty_params) {
843-
ret lookup_in_fn(name, decl, ty_params, ns);
860+
ret lookup_in_fn(e, name, decl, ty_params, ns);
844861
}
845862
scope_loop(local) {
846863
if ns == ns_value {
@@ -915,13 +932,13 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
915932
e.sess.bug("reached unreachable code in lookup_in_scope"); // sigh
916933
}
917934

918-
fn lookup_in_ty_params(name: ident, ty_params: [ast::ty_param]) ->
919-
option::t<def> {
935+
fn lookup_in_ty_params(e: env, name: ident, ty_params: [ast::ty_param])
936+
-> option::t<def> {
920937
let n = 0u;
921938
for tp: ast::ty_param in ty_params {
922-
if str::eq(tp.ident, name) {
923-
ret some(ast::def_ty_param(local_def(tp.id), n));
924-
}
939+
if str::eq(tp.ident, name) && alt e.current_tp {
940+
some(cur) { n < cur } none. { true }
941+
} { ret some(ast::def_ty_param(local_def(tp.id), n)); }
925942
n += 1u;
926943
}
927944
ret none::<def>;
@@ -936,7 +953,8 @@ fn lookup_in_pat(name: ident, pat: @ast::pat) -> option::t<def_id> {
936953
ret found;
937954
}
938955

939-
fn lookup_in_fn(name: ident, decl: ast::fn_decl, ty_params: [ast::ty_param],
956+
fn lookup_in_fn(e: env, name: ident, decl: ast::fn_decl,
957+
ty_params: [ast::ty_param],
940958
ns: namespace) -> option::t<def> {
941959
alt ns {
942960
ns_value. {
@@ -947,12 +965,13 @@ fn lookup_in_fn(name: ident, decl: ast::fn_decl, ty_params: [ast::ty_param],
947965
}
948966
ret none::<def>;
949967
}
950-
ns_type. { ret lookup_in_ty_params(name, ty_params); }
968+
ns_type. { ret lookup_in_ty_params(e, name, ty_params); }
951969
_ { ret none::<def>; }
952970
}
953971
}
954972

955-
fn lookup_in_obj(name: ident, ob: ast::_obj, ty_params: [ast::ty_param],
973+
fn lookup_in_obj(e: env, name: ident, ob: ast::_obj,
974+
ty_params: [ast::ty_param],
956975
ns: namespace, id: node_id) -> option::t<def> {
957976
alt ns {
958977
ns_value. {
@@ -964,7 +983,7 @@ fn lookup_in_obj(name: ident, ob: ast::_obj, ty_params: [ast::ty_param],
964983
}
965984
ret none::<def>;
966985
}
967-
ns_type. { ret lookup_in_ty_params(name, ty_params); }
986+
ns_type. { ret lookup_in_ty_params(e, name, ty_params); }
968987
_ { ret none::<def>; }
969988
}
970989
}

src/comp/middle/typeck.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2748,7 +2748,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, impl_m: ty::method,
27482748
let substs = substs + vec::init_fn({|i|
27492749
ty::mk_param(tcx, i + impl_tps, {crate: 0, node: 0})
27502750
}, vec::len(*if_m.tps));
2751-
let if_fty = ty::substitute_type_params(tcx, substs,
2751+
let if_fty = ty::substitute_type_params(tcx, substs,
27522752
ty::mk_fn(tcx, if_m.fty));
27532753
alt ty::unify::unify(impl_fty, if_fty, ty::unify::precise, tcx) {
27542754
ty::unify::ures_err(err) {
@@ -3064,8 +3064,8 @@ mod dict {
30643064
visit::visit_expr(ex, fcx, v);
30653065
}
30663066

3067-
// Detect points where an interface-bounded type parameter is instantiated,
3068-
// resolve the impls for the parameters.
3067+
// Detect points where an interface-bounded type parameter is
3068+
// instantiated, resolve the impls for the parameters.
30693069
fn resolve_in_block(fcx: @fn_ctxt, bl: ast::blk) {
30703070
visit::visit_block(bl, fcx, visit::mk_vt(@{
30713071
visit_expr: resolve_expr,

0 commit comments

Comments
 (0)