Clean up some FIXMEs in middle:: modules

Rename all TODOs to FIXMEs
This commit is contained in:
Marijn Haverbeke 2012-02-21 15:59:48 +01:00
parent 92a45f5582
commit ff927f18f5
2 changed files with 86 additions and 122 deletions

View file

@ -1359,17 +1359,14 @@ fn field_idx(id: ast::ident, fields: [field]) -> option<uint> {
} }
fn get_field(rec_ty: t, id: ast::ident) -> field { fn get_field(rec_ty: t, id: ast::ident) -> field {
alt vec::find(get_fields(rec_ty), {|f| str::eq(f.ident, id) }) { alt check vec::find(get_fields(rec_ty), {|f| str::eq(f.ident, id) }) {
some(f) { f } some(f) { f }
_ { fail #fmt("get_field: bad field id %s", id); }
} }
} }
// TODO: could have a precondition instead of failing
fn get_fields(rec_ty:t) -> [field] { fn get_fields(rec_ty:t) -> [field] {
alt get(rec_ty).struct { alt check get(rec_ty).struct {
ty_rec(fields) { fields } ty_rec(fields) { fields }
_ { fail "get_fields called on non-record type"; }
} }
} }
@ -2080,14 +2077,11 @@ mod unify {
let err = terr_record_size(expected_len, actual_len); let err = terr_record_size(expected_len, actual_len);
ret ures_err(err); ret ures_err(err);
} }
// TODO: implement an iterator that can iterate over
// two arrays simultaneously.
let result_fields: [field] = []; let result_fields = [], i = 0u;
let i = 0u; while i < actual_len {
while i < expected_len { let expected_field = expected_fields[i],
let expected_field = expected_fields[i]; actual_field = actual_fields[i];
let actual_field = actual_fields[i];
let u_mut = unify_mut(expected_field.mt.mutbl, let u_mut = unify_mut(expected_field.mt.mutbl,
actual_field.mt.mutbl, actual_field.mt.mutbl,
variance); variance);
@ -2127,19 +2121,13 @@ mod unify {
let err = terr_tuple_size(expected_len, actual_len); let err = terr_tuple_size(expected_len, actual_len);
ret ures_err(err); ret ures_err(err);
} }
// TODO: implement an iterator that can iterate over
// two arrays simultaneously.
let result_elems = []; let result_elems = [], i = 0u;
let i = 0u; while i < actual_len {
while i < expected_len { alt unify_step(cx, expected_elems[i], actual_elems[i],
let expected_elem = expected_elems[i]; variance) {
let actual_elem = actual_elems[i];
let result = unify_step(
cx, expected_elem, actual_elem, variance);
alt result {
ures_ok(rty) { result_elems += [rty]; } ures_ok(rty) { result_elems += [rty]; }
_ { ret result; } r { ret r; }
} }
i += 1u; i += 1u;
} }

View file

@ -285,9 +285,6 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
} }
fn instantiate(tcx: ty::ctxt, sp: span, mode: mode, fn instantiate(tcx: ty::ctxt, sp: span, mode: mode,
id: ast::def_id, args: [@ast::ty]) -> ty::t { id: ast::def_id, args: [@ast::ty]) -> ty::t {
// TODO: maybe record cname chains so we can do
// "foo = int" like OCaml?
let ty_param_bounds_and_ty = getter(tcx, mode, id); let ty_param_bounds_and_ty = getter(tcx, mode, id);
if vec::len(*ty_param_bounds_and_ty.bounds) == 0u { if vec::len(*ty_param_bounds_and_ty.bounds) == 0u {
ret ty_param_bounds_and_ty.ty; ret ty_param_bounds_and_ty.ty;
@ -783,22 +780,14 @@ fn fixup_self_in_method_ty(cx: ty::ctxt, mty: ty::t, m_substs: [ty::t],
// //
// We then annotate the AST with the resulting types and return the annotated // We then annotate the AST with the resulting types and return the annotated
// AST, along with a table mapping item IDs to their types. // AST, along with a table mapping item IDs to their types.
//
// TODO: This logic is quite convoluted; it's a relic of the time when we
// actually wrote types directly into the AST and didn't have a type cache.
// Could use some cleanup. Consider topologically sorting in phase (1) above.
mod collect { mod collect {
type ctxt = {tcx: ty::ctxt}; fn get_enum_variant_types(tcx: ty::ctxt, enum_ty: ty::t,
fn get_enum_variant_types(cx: @ctxt, enum_ty: ty::t,
variants: [ast::variant], variants: [ast::variant],
ty_params: [ast::ty_param]) { ty_params: [ast::ty_param]) {
// Create a set of parameter types shared among all the variants. // Create a set of parameter types shared among all the variants.
for variant in variants {
for variant: ast::variant in variants {
// Nullary enum constructors get turned into constants; n-ary enum // Nullary enum constructors get turned into constants; n-ary enum
// constructors get turned into functions. // constructors get turned into functions.
let result_ty = if vec::len(variant.node.args) == 0u { let result_ty = if vec::len(variant.node.args) == 0u {
enum_ty enum_ty
} else { } else {
@ -806,19 +795,19 @@ mod collect {
// should be called to resolve named types. // should be called to resolve named types.
let args: [arg] = []; let args: [arg] = [];
for va: ast::variant_arg in variant.node.args { for va: ast::variant_arg in variant.node.args {
let arg_ty = ast_ty_to_ty(cx.tcx, m_collect, va.ty); let arg_ty = ast_ty_to_ty(tcx, m_collect, va.ty);
args += [{mode: ast::expl(ast::by_copy), ty: arg_ty}]; args += [{mode: ast::expl(ast::by_copy), ty: arg_ty}];
} }
// FIXME: this will be different for constrained types // FIXME: this will be different for constrained types
ty::mk_fn(cx.tcx, ty::mk_fn(tcx,
{proto: ast::proto_box, {proto: ast::proto_box,
inputs: args, output: enum_ty, inputs: args, output: enum_ty,
ret_style: ast::return_val, constraints: []}) ret_style: ast::return_val, constraints: []})
}; };
let tpt = {bounds: ty_param_bounds(cx.tcx, m_collect, ty_params), let tpt = {bounds: ty_param_bounds(tcx, m_collect, ty_params),
ty: result_ty}; ty: result_ty};
cx.tcx.tcache.insert(local_def(variant.node.id), tpt); tcx.tcache.insert(local_def(variant.node.id), tpt);
write_ty(cx.tcx, variant.node.id, result_ty); write_ty(tcx, variant.node.id, result_ty);
} }
} }
fn ensure_iface_methods(tcx: ty::ctxt, id: ast::node_id) { fn ensure_iface_methods(tcx: ty::ctxt, id: ast::node_id) {
@ -830,7 +819,7 @@ mod collect {
} }
} }
} }
fn convert_class_item(cx: @ctxt, ci: ast::class_member) { fn convert_class_item(tcx: ty::ctxt, ci: ast::class_member) {
/* we want to do something here, b/c within the /* we want to do something here, b/c within the
scope of the class, it's ok to refer to fields & scope of the class, it's ok to refer to fields &
methods unqualified */ methods unqualified */
@ -839,76 +828,76 @@ mod collect {
class. outside the class, it's done with expr_field */ class. outside the class, it's done with expr_field */
alt ci { alt ci {
ast::instance_var(_,t,_,id) { ast::instance_var(_,t,_,id) {
let tt = ast_ty_to_ty(cx.tcx, m_collect, t); let tt = ast_ty_to_ty(tcx, m_collect, t);
write_ty(cx.tcx, id, tt); write_ty(tcx, id, tt);
} }
ast::class_method(it) { convert(cx, it); } ast::class_method(it) { convert(tcx, it); }
} }
} }
fn convert(cx: @ctxt, it: @ast::item) { fn convert(tcx: ty::ctxt, it: @ast::item) {
alt it.node { alt it.node {
// These don't define types. // These don't define types.
ast::item_mod(_) | ast::item_native_mod(_) {} ast::item_mod(_) | ast::item_native_mod(_) {}
ast::item_enum(variants, ty_params) { ast::item_enum(variants, ty_params) {
let tpt = ty_of_item(cx.tcx, m_collect, it); let tpt = ty_of_item(tcx, m_collect, it);
write_ty(cx.tcx, it.id, tpt.ty); write_ty(tcx, it.id, tpt.ty);
get_enum_variant_types(cx, tpt.ty, variants, ty_params); get_enum_variant_types(tcx, tpt.ty, variants, ty_params);
} }
ast::item_impl(tps, ifce, selfty, ms) { ast::item_impl(tps, ifce, selfty, ms) {
let i_bounds = ty_param_bounds(cx.tcx, m_collect, tps); let i_bounds = ty_param_bounds(tcx, m_collect, tps);
let my_methods = []; let my_methods = [];
for m in ms { for m in ms {
let bounds = ty_param_bounds(cx.tcx, m_collect, m.tps); let bounds = ty_param_bounds(tcx, m_collect, m.tps);
let mty = ty_of_method(cx.tcx, m_collect, m); let mty = ty_of_method(tcx, m_collect, m);
my_methods += [{mty: mty, id: m.id, span: m.span}]; my_methods += [{mty: mty, id: m.id, span: m.span}];
let fty = ty::mk_fn(cx.tcx, mty.fty); let fty = ty::mk_fn(tcx, mty.fty);
cx.tcx.tcache.insert(local_def(m.id), tcx.tcache.insert(local_def(m.id),
{bounds: @(*i_bounds + *bounds), {bounds: @(*i_bounds + *bounds),
ty: fty}); ty: fty});
write_ty(cx.tcx, m.id, fty); write_ty(tcx, m.id, fty);
} }
let selfty = ast_ty_to_ty(cx.tcx, m_collect, selfty); let selfty = ast_ty_to_ty(tcx, m_collect, selfty);
write_ty(cx.tcx, it.id, selfty); write_ty(tcx, it.id, selfty);
alt ifce { alt ifce {
some(t) { some(t) {
let iface_ty = ast_ty_to_ty(cx.tcx, m_collect, t); let iface_ty = ast_ty_to_ty(tcx, m_collect, t);
cx.tcx.tcache.insert(local_def(it.id), tcx.tcache.insert(local_def(it.id),
{bounds: i_bounds, ty: iface_ty}); {bounds: i_bounds, ty: iface_ty});
alt ty::get(iface_ty).struct { alt ty::get(iface_ty).struct {
ty::ty_iface(did, tys) { ty::ty_iface(did, tys) {
if did.crate == ast::local_crate { if did.crate == ast::local_crate {
ensure_iface_methods(cx.tcx, did.node); ensure_iface_methods(tcx, did.node);
} }
for if_m in *ty::iface_methods(cx.tcx, did) { for if_m in *ty::iface_methods(tcx, did) {
alt vec::find(my_methods, alt vec::find(my_methods,
{|m| if_m.ident == m.mty.ident}) { {|m| if_m.ident == m.mty.ident}) {
some({mty: m, id, span}) { some({mty: m, id, span}) {
if m.purity != if_m.purity { if m.purity != if_m.purity {
cx.tcx.sess.span_err( tcx.sess.span_err(
span, "method `" + m.ident + "`'s purity \ span, "method `" + m.ident + "`'s purity \
not match the iface method's \ not match the iface method's \
purity"); purity");
} }
let mt = compare_impl_method( let mt = compare_impl_method(
cx.tcx, span, m, vec::len(tps), if_m, tys, tcx, span, m, vec::len(tps), if_m, tys,
selfty); selfty);
let old = cx.tcx.tcache.get(local_def(id)); let old = tcx.tcache.get(local_def(id));
if old.ty != mt { if old.ty != mt {
cx.tcx.tcache.insert(local_def(id), tcx.tcache.insert(local_def(id),
{bounds: old.bounds, {bounds: old.bounds,
ty: mt}); ty: mt});
write_ty(cx.tcx, id, mt); write_ty(tcx, id, mt);
} }
} }
none { none {
cx.tcx.sess.span_err(t.span, "missing method `" + tcx.sess.span_err(t.span, "missing method `" +
if_m.ident + "`"); if_m.ident + "`");
} }
} }
} }
} }
_ { _ {
cx.tcx.sess.span_fatal(t.span, "can only implement \ tcx.sess.span_fatal(t.span, "can only implement \
interface types"); interface types");
} }
} }
@ -917,81 +906,76 @@ mod collect {
} }
} }
ast::item_res(decl, tps, _, dtor_id, ctor_id) { ast::item_res(decl, tps, _, dtor_id, ctor_id) {
let {bounds, params} = mk_ty_params(cx.tcx, tps); let {bounds, params} = mk_ty_params(tcx, tps);
let t_arg = ty_of_arg(cx.tcx, m_collect, decl.inputs[0]); let t_arg = ty_of_arg(tcx, m_collect, decl.inputs[0]);
let t_res = ty::mk_res(cx.tcx, local_def(it.id), t_arg.ty, let t_res = ty::mk_res(tcx, local_def(it.id), t_arg.ty,
params); params);
let t_ctor = ty::mk_fn(cx.tcx, { let t_ctor = ty::mk_fn(tcx, {
proto: ast::proto_box, proto: ast::proto_box,
inputs: [{mode: ast::expl(ast::by_copy) with t_arg}], inputs: [{mode: ast::expl(ast::by_copy) with t_arg}],
output: t_res, output: t_res,
ret_style: ast::return_val, constraints: [] ret_style: ast::return_val, constraints: []
}); });
let t_dtor = ty::mk_fn(cx.tcx, { let t_dtor = ty::mk_fn(tcx, {
proto: ast::proto_box, proto: ast::proto_box,
inputs: [t_arg], output: ty::mk_nil(cx.tcx), inputs: [t_arg], output: ty::mk_nil(tcx),
ret_style: ast::return_val, constraints: [] ret_style: ast::return_val, constraints: []
}); });
write_ty(cx.tcx, it.id, t_res); write_ty(tcx, it.id, t_res);
write_ty(cx.tcx, ctor_id, t_ctor); write_ty(tcx, ctor_id, t_ctor);
cx.tcx.tcache.insert(local_def(ctor_id), tcx.tcache.insert(local_def(ctor_id),
{bounds: bounds, ty: t_ctor}); {bounds: bounds, ty: t_ctor});
write_ty(cx.tcx, dtor_id, t_dtor); write_ty(tcx, dtor_id, t_dtor);
} }
ast::item_iface(_, ms) { ast::item_iface(_, ms) {
let tpt = ty_of_item(cx.tcx, m_collect, it); let tpt = ty_of_item(tcx, m_collect, it);
write_ty(cx.tcx, it.id, tpt.ty); write_ty(tcx, it.id, tpt.ty);
ensure_iface_methods(cx.tcx, it.id); ensure_iface_methods(tcx, it.id);
} }
ast::item_class(tps, members, ctor_id, ctor_decl, ctor_block) { ast::item_class(tps, members, ctor_id, ctor_decl, ctor_block) {
// Write the class type // Write the class type
let {bounds,params} = mk_ty_params(cx.tcx, tps); let {bounds,params} = mk_ty_params(tcx, tps);
let class_ty = ty::mk_class(cx.tcx, local_def(it.id), params); let class_ty = ty::mk_class(tcx, local_def(it.id), params);
let tpt = {bounds: bounds, ty: class_ty}; let tpt = {bounds: bounds, ty: class_ty};
cx.tcx.tcache.insert(local_def(it.id), tpt); tcx.tcache.insert(local_def(it.id), tpt);
write_ty(cx.tcx, it.id, class_ty); write_ty(tcx, it.id, class_ty);
// Write the ctor type // Write the ctor type
let t_ctor = ty::mk_fn(cx.tcx, let t_ctor = ty::mk_fn(tcx,
ty_of_fn_decl(cx.tcx, m_collect, ty_of_fn_decl(tcx, m_collect,
ast::proto_any, ctor_decl)); ast::proto_any, ctor_decl));
write_ty(cx.tcx, ctor_id, t_ctor); write_ty(tcx, ctor_id, t_ctor);
cx.tcx.tcache.insert(local_def(ctor_id), tcx.tcache.insert(local_def(ctor_id),
{bounds: bounds, ty: t_ctor}); {bounds: bounds, ty: t_ctor});
/* FIXME: check for proper public/privateness */ /* FIXME: check for proper public/privateness */
// Write the type of each of the members // Write the type of each of the members
for m in members { for m in members {
convert_class_item(cx, m.node.decl); convert_class_item(tcx, m.node.decl);
} }
} }
_ { _ {
// This call populates the type cache with the converted type // This call populates the type cache with the converted type
// of the item in passing. All we have to do here is to write // of the item in passing. All we have to do here is to write
// it into the node type table. // it into the node type table.
let tpt = ty_of_item(cx.tcx, m_collect, it); let tpt = ty_of_item(tcx, m_collect, it);
write_ty(cx.tcx, it.id, tpt.ty); write_ty(tcx, it.id, tpt.ty);
} }
} }
} }
fn convert_native(cx: @ctxt, i: @ast::native_item) { fn convert_native(tcx: ty::ctxt, i: @ast::native_item) {
// As above, this call populates the type table with the converted // As above, this call populates the type table with the converted
// type of the native item. We simply write it into the node type // type of the native item. We simply write it into the node type
// table. // table.
let tpt = ty_of_native_item(cx.tcx, m_collect, i); let tpt = ty_of_native_item(tcx, m_collect, i);
alt i.node { alt i.node {
ast::native_item_fn(_, _) { ast::native_item_fn(_, _) { write_ty(tcx, i.id, tpt.ty); }
write_ty(cx.tcx, i.id, tpt.ty);
}
} }
} }
fn collect_item_types(tcx: ty::ctxt, crate: @ast::crate) { fn collect_item_types(tcx: ty::ctxt, crate: @ast::crate) {
let cx = @{tcx: tcx}; visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{
let visit = visit_item: bind convert(tcx, _),
visit::mk_simple_visitor(@{visit_item: bind convert(cx, _), visit_native_item: bind convert_native(tcx, _)
visit_native_item: with *visit::default_simple_visitor()
bind convert_native(cx, _) }));
with
*visit::default_simple_visitor()});
visit::visit_crate(*crate, (), visit);
} }
} }
@ -1459,17 +1443,12 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
demand::with_substs(fcx, pat.span, expected, ctor_ty, demand::with_substs(fcx, pat.span, expected, ctor_ty,
expected_tps); expected_tps);
// Get the number of arguments in this enum variant. // Get the number of arguments in this enum variant.
let arg_types = let arg_types = variant_arg_types(fcx.ccx, pat.span,
variant_arg_types(fcx.ccx, pat.span, v_def_ids.var, v_def_ids.var, expected_tps);
expected_tps); let subpats_len = subpats.len(), arg_len = arg_types.len();
let subpats_len = vec::len::<@ast::pat>(subpats); if arg_len > 0u {
if vec::len::<ty::t>(arg_types) > 0u {
// N-ary variant. // N-ary variant.
let arg_len = vec::len::<ty::t>(arg_types);
if arg_len != subpats_len { if arg_len != subpats_len {
// TODO: note definition of enum variant
// TODO (issue #448): Wrap a #fmt string over multiple
// lines...
let s = #fmt["this pattern has %u field%s, but the \ let s = #fmt["this pattern has %u field%s, but the \
corresponding variant has %u field%s", corresponding variant has %u field%s",
subpats_len, subpats_len,
@ -1483,7 +1462,6 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
check_pat(fcx, map, subpat, arg_ty); check_pat(fcx, map, subpat, arg_ty);
} }
} else if subpats_len > 0u { } else if subpats_len > 0u {
// TODO: note definition of enum variant
tcx.sess.span_err tcx.sess.span_err
(pat.span, #fmt["this pattern has %u field%s, \ (pat.span, #fmt["this pattern has %u field%s, \
but the corresponding \ but the corresponding \
@ -1494,11 +1472,9 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
} }
} }
_ { _ {
// FIXME: Switch expected and actual in this message? I
// can never tell.
tcx.sess.span_err tcx.sess.span_err
(pat.span, (pat.span,
#fmt["mismatched types: expected `%s` but found enum", #fmt["mismatched types: expected enum but found `%s`",
ty_to_str(tcx, expected)]); ty_to_str(tcx, expected)]);
} }
} }
@ -2536,7 +2512,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
// field // field
// For now, this code assumes the class is defined in the local // For now, this code assumes the class is defined in the local
// crate // crate
// TODO: handle field references to classes in external crate // FIXME: handle field references to classes in external crate
let err = "Class ID is not bound to a class"; let err = "Class ID is not bound to a class";
let field_ty = alt fcx.ccx.tcx.items.find(base_id.node) { let field_ty = alt fcx.ccx.tcx.items.find(base_id.node) {
some(ast_map::node_item(i,_)) { some(ast_map::node_item(i,_)) {
@ -2551,7 +2527,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
_ { fcx.ccx.tcx.sess.span_bug(expr.span, err); } _ { fcx.ccx.tcx.sess.span_bug(expr.span, err); }
}; };
// (2) look up what field's type is, and return it // (2) look up what field's type is, and return it
// TODO: actually instantiate any type params // FIXME: actually instantiate any type params
write_ty(tcx, id, field_ty); write_ty(tcx, id, field_ty);
handled = true; handled = true;
} }