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
This commit is contained in:
parent
42f6608ffd
commit
94d40be746
2 changed files with 38 additions and 19 deletions
|
@ -142,6 +142,7 @@ type env =
|
||||||
mutable data: [ast::node_id]},
|
mutable data: [ast::node_id]},
|
||||||
mutable reported: [{ident: str, sc: scope}],
|
mutable reported: [{ident: str, sc: scope}],
|
||||||
mutable ignored_imports: [node_id],
|
mutable ignored_imports: [node_id],
|
||||||
|
mutable current_tp: option::t<uint>,
|
||||||
sess: session};
|
sess: session};
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,6 +169,7 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
|
||||||
used_imports: {mutable track: false, mutable data: []},
|
used_imports: {mutable track: false, mutable data: []},
|
||||||
mutable reported: [],
|
mutable reported: [],
|
||||||
mutable ignored_imports: [],
|
mutable ignored_imports: [],
|
||||||
|
mutable current_tp: none,
|
||||||
sess: sess};
|
sess: sess};
|
||||||
map_crate(e, crate);
|
map_crate(e, crate);
|
||||||
resolve_imports(*e);
|
resolve_imports(*e);
|
||||||
|
@ -336,6 +338,7 @@ fn resolve_names(e: @env, c: @ast::crate) {
|
||||||
visit_pat: bind walk_pat(e, _, _, _),
|
visit_pat: bind walk_pat(e, _, _, _),
|
||||||
visit_expr: bind walk_expr(e, _, _, _),
|
visit_expr: bind walk_expr(e, _, _, _),
|
||||||
visit_ty: bind walk_ty(e, _, _, _),
|
visit_ty: bind walk_ty(e, _, _, _),
|
||||||
|
visit_ty_params: bind walk_tps(e, _, _, _),
|
||||||
visit_constr: bind walk_constr(e, _, _, _, _, _),
|
visit_constr: bind walk_constr(e, _, _, _, _, _),
|
||||||
visit_fn: bind visit_fn_with_scope(e, _, _, _, _, _, _, _)
|
visit_fn: bind visit_fn_with_scope(e, _, _, _, _, _, _, _)
|
||||||
with *visit::default_visitor()};
|
with *visit::default_visitor()};
|
||||||
|
@ -369,6 +372,20 @@ fn resolve_names(e: @env, c: @ast::crate) {
|
||||||
_ { }
|
_ { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn walk_tps(e: @env, tps: [ast::ty_param], sc: scopes, v: vt<scopes>) {
|
||||||
|
let outer_current_tp = e.current_tp, current = 0u;
|
||||||
|
for tp in tps {
|
||||||
|
e.current_tp = some(current);
|
||||||
|
for bound in *tp.bounds {
|
||||||
|
alt bound {
|
||||||
|
bound_iface(t) { v.visit_ty(t, sc, v); }
|
||||||
|
_ {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current += 1u;
|
||||||
|
}
|
||||||
|
e.current_tp = outer_current_tp;
|
||||||
|
}
|
||||||
fn walk_constr(e: @env, p: @ast::path, sp: span, id: node_id, sc: scopes,
|
fn walk_constr(e: @env, p: @ast::path, sp: span, id: node_id, sc: scopes,
|
||||||
_v: vt<scopes>) {
|
_v: vt<scopes>) {
|
||||||
maybe_insert(e, id, lookup_path_strict(*e, sc, sp, p.node, ns_value));
|
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)
|
||||||
scope_item(it) {
|
scope_item(it) {
|
||||||
alt it.node {
|
alt it.node {
|
||||||
ast::item_obj(ob, ty_params, _) {
|
ast::item_obj(ob, ty_params, _) {
|
||||||
ret lookup_in_obj(name, ob, ty_params, ns, it.id);
|
ret lookup_in_obj(e, name, ob, ty_params, ns, it.id);
|
||||||
}
|
}
|
||||||
ast::item_impl(ty_params, _, _, _) {
|
ast::item_impl(tps, _, _, _) {
|
||||||
if ns == ns_type { ret lookup_in_ty_params(name, ty_params); }
|
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
|
||||||
}
|
}
|
||||||
ast::item_iface(tps, _) | ast::item_tag(_, tps) |
|
ast::item_iface(tps, _) | ast::item_tag(_, tps) |
|
||||||
ast::item_ty(_, tps) {
|
ast::item_ty(_, tps) {
|
||||||
if ns == ns_type { ret lookup_in_ty_params(name, tps); }
|
if ns == ns_type { ret lookup_in_ty_params(e, name, tps); }
|
||||||
}
|
}
|
||||||
ast::item_mod(_) {
|
ast::item_mod(_) {
|
||||||
ret lookup_in_local_mod(e, it.id, sp, name, ns, inside);
|
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)
|
||||||
if (name == "self" && ns == ns_value) {
|
if (name == "self" && ns == ns_value) {
|
||||||
ret some(ast::def_self(local_def(id)));
|
ret some(ast::def_self(local_def(id)));
|
||||||
} else if ns == ns_type {
|
} else if ns == ns_type {
|
||||||
ret lookup_in_ty_params(name, tps);
|
ret lookup_in_ty_params(e, name, tps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope_native_item(it) {
|
scope_native_item(it) {
|
||||||
alt it.node {
|
alt it.node {
|
||||||
ast::native_item_fn(decl, ty_params) {
|
ast::native_item_fn(decl, ty_params) {
|
||||||
ret lookup_in_fn(name, decl, ty_params, ns);
|
ret lookup_in_fn(e, name, decl, ty_params, ns);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope_bare_fn(decl, _, ty_params) |
|
scope_bare_fn(decl, _, ty_params) |
|
||||||
scope_fn_expr(decl, _, ty_params) {
|
scope_fn_expr(decl, _, ty_params) {
|
||||||
ret lookup_in_fn(name, decl, ty_params, ns);
|
ret lookup_in_fn(e, name, decl, ty_params, ns);
|
||||||
}
|
}
|
||||||
scope_loop(local) {
|
scope_loop(local) {
|
||||||
if ns == ns_value {
|
if ns == ns_value {
|
||||||
|
@ -915,13 +932,13 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
|
||||||
e.sess.bug("reached unreachable code in lookup_in_scope"); // sigh
|
e.sess.bug("reached unreachable code in lookup_in_scope"); // sigh
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_in_ty_params(name: ident, ty_params: [ast::ty_param]) ->
|
fn lookup_in_ty_params(e: env, name: ident, ty_params: [ast::ty_param])
|
||||||
option::t<def> {
|
-> option::t<def> {
|
||||||
let n = 0u;
|
let n = 0u;
|
||||||
for tp: ast::ty_param in ty_params {
|
for tp: ast::ty_param in ty_params {
|
||||||
if str::eq(tp.ident, name) {
|
if str::eq(tp.ident, name) && alt e.current_tp {
|
||||||
ret some(ast::def_ty_param(local_def(tp.id), n));
|
some(cur) { n < cur } none. { true }
|
||||||
}
|
} { ret some(ast::def_ty_param(local_def(tp.id), n)); }
|
||||||
n += 1u;
|
n += 1u;
|
||||||
}
|
}
|
||||||
ret none::<def>;
|
ret none::<def>;
|
||||||
|
@ -936,7 +953,8 @@ fn lookup_in_pat(name: ident, pat: @ast::pat) -> option::t<def_id> {
|
||||||
ret found;
|
ret found;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_in_fn(name: ident, decl: ast::fn_decl, ty_params: [ast::ty_param],
|
fn lookup_in_fn(e: env, name: ident, decl: ast::fn_decl,
|
||||||
|
ty_params: [ast::ty_param],
|
||||||
ns: namespace) -> option::t<def> {
|
ns: namespace) -> option::t<def> {
|
||||||
alt ns {
|
alt ns {
|
||||||
ns_value. {
|
ns_value. {
|
||||||
|
@ -947,12 +965,13 @@ fn lookup_in_fn(name: ident, decl: ast::fn_decl, ty_params: [ast::ty_param],
|
||||||
}
|
}
|
||||||
ret none::<def>;
|
ret none::<def>;
|
||||||
}
|
}
|
||||||
ns_type. { ret lookup_in_ty_params(name, ty_params); }
|
ns_type. { ret lookup_in_ty_params(e, name, ty_params); }
|
||||||
_ { ret none::<def>; }
|
_ { ret none::<def>; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_in_obj(name: ident, ob: ast::_obj, ty_params: [ast::ty_param],
|
fn lookup_in_obj(e: env, name: ident, ob: ast::_obj,
|
||||||
|
ty_params: [ast::ty_param],
|
||||||
ns: namespace, id: node_id) -> option::t<def> {
|
ns: namespace, id: node_id) -> option::t<def> {
|
||||||
alt ns {
|
alt ns {
|
||||||
ns_value. {
|
ns_value. {
|
||||||
|
@ -964,7 +983,7 @@ fn lookup_in_obj(name: ident, ob: ast::_obj, ty_params: [ast::ty_param],
|
||||||
}
|
}
|
||||||
ret none::<def>;
|
ret none::<def>;
|
||||||
}
|
}
|
||||||
ns_type. { ret lookup_in_ty_params(name, ty_params); }
|
ns_type. { ret lookup_in_ty_params(e, name, ty_params); }
|
||||||
_ { ret none::<def>; }
|
_ { ret none::<def>; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2748,7 +2748,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, impl_m: ty::method,
|
||||||
let substs = substs + vec::init_fn({|i|
|
let substs = substs + vec::init_fn({|i|
|
||||||
ty::mk_param(tcx, i + impl_tps, {crate: 0, node: 0})
|
ty::mk_param(tcx, i + impl_tps, {crate: 0, node: 0})
|
||||||
}, vec::len(*if_m.tps));
|
}, vec::len(*if_m.tps));
|
||||||
let if_fty = ty::substitute_type_params(tcx, substs,
|
let if_fty = ty::substitute_type_params(tcx, substs,
|
||||||
ty::mk_fn(tcx, if_m.fty));
|
ty::mk_fn(tcx, if_m.fty));
|
||||||
alt ty::unify::unify(impl_fty, if_fty, ty::unify::precise, tcx) {
|
alt ty::unify::unify(impl_fty, if_fty, ty::unify::precise, tcx) {
|
||||||
ty::unify::ures_err(err) {
|
ty::unify::ures_err(err) {
|
||||||
|
@ -3064,8 +3064,8 @@ mod dict {
|
||||||
visit::visit_expr(ex, fcx, v);
|
visit::visit_expr(ex, fcx, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect points where an interface-bounded type parameter is instantiated,
|
// Detect points where an interface-bounded type parameter is
|
||||||
// resolve the impls for the parameters.
|
// instantiated, resolve the impls for the parameters.
|
||||||
fn resolve_in_block(fcx: @fn_ctxt, bl: ast::blk) {
|
fn resolve_in_block(fcx: @fn_ctxt, bl: ast::blk) {
|
||||||
visit::visit_block(bl, fcx, visit::mk_vt(@{
|
visit::visit_block(bl, fcx, visit::mk_vt(@{
|
||||||
visit_expr: resolve_expr,
|
visit_expr: resolve_expr,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue