Make sure type_use.rs doesn't get lost in recursive enums

Closes #2059
This commit is contained in:
Marijn Haverbeke 2012-03-28 10:35:16 +02:00
parent d3b6fe0a91
commit 90cf9e0d6f

View File

@ -18,6 +18,7 @@
// invasive.)
import std::map::hashmap;
import std::list;
import driver::session::session;
import metadata::csearch;
import syntax::ast::*, syntax::ast_util, syntax::visit;
@ -91,21 +92,25 @@ fn type_needs(cx: ctx, use: uint, ty: ty::t) {
let mut done = true;
// Optimization -- don't descend type if all params already have this use
for vec::each(cx.uses) {|u| if u & use != use { done = false } }
if !done { type_needs_inner(cx, use, ty); }
if !done { type_needs_inner(cx, use, ty, list::nil); }
}
fn type_needs_inner(cx: ctx, use: uint, ty: ty::t) {
fn type_needs_inner(cx: ctx, use: uint, ty: ty::t,
enums_seen: list::list<def_id>) {
ty::maybe_walk_ty(ty) {|ty|
if ty::type_has_params(ty) {
alt ty::get(ty).struct {
ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _) |
ty::ty_box(_) | ty::ty_iface(_, _) { false }
ty::ty_enum(did, tps) {
for vec::each(*ty::enum_variants(cx.ccx.tcx, did)) {|v|
for vec::each(v.args) {|aty|
let t = ty::substitute_type_params(cx.ccx.tcx, tps,
aty);
type_needs_inner(cx, use, t);
if option::is_none(list::find(enums_seen, {|id| id == did})) {
let seen = list::cons(did, @enums_seen);
for vec::each(*ty::enum_variants(cx.ccx.tcx, did)) {|v|
for vec::each(v.args) {|aty|
let t = ty::substitute_type_params(cx.ccx.tcx,
tps, aty);
type_needs_inner(cx, use, t, seen);
}
}
}
false