From 7c3d78013ae8b327b1a0828b3643d5b781114d17 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 13 Dec 2011 15:28:22 +0100 Subject: [PATCH] Reorganize some code in typeck This should cut down a lot on the amount of closures being allocated, and removes some duplicated code. --- src/comp/middle/typeck.rs | 538 +++++++++++++++++--------------------- 1 file changed, 233 insertions(+), 305 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index feaa1215d87..0bef6035016 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -48,9 +48,6 @@ type fn_ctxt = ccx: @crate_ctxt}; -// Used for ast_ty_to_ty() below. -type ty_getter = fn@(ast::def_id) -> ty::ty_param_kinds_and_ty; - fn lookup_local(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> int { alt fcx.locals.find(id) { some(x) { x } @@ -229,11 +226,32 @@ fn default_arg_mode_for_ty(tcx: ty::ctxt, m: ast::mode, _ { m } } } -fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, &&ast_ty: @ast::ty) - -> ty::t { - fn ast_arg_to_arg(tcx: ty::ctxt, getter: ty_getter, arg: ast::ty_arg) + +tag mode { m_collect; m_check; m_check_tyvar(@fn_ctxt); } + +fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t { + fn getter(tcx: ty::ctxt, mode: mode, id: ast::def_id) + -> ty::ty_param_kinds_and_ty { + alt mode { + m_check. | m_check_tyvar(_) { ty::lookup_item_type(tcx, id) } + m_collect. { + if id.crate != ast::local_crate { csearch::get_type(tcx, id) } + else { + alt tcx.items.find(id.node) { + some(ast_map::node_item(item)) { + ty_of_item(tcx, mode, item) + } + some(ast_map::node_native_item(native_item)) { + ty_of_native_item(tcx, mode, native_item) + } + } + } + } + } + } + fn ast_arg_to_arg(tcx: ty::ctxt, mode: mode, arg: ast::ty_arg) -> {mode: ty::mode, ty: ty::t} { - let ty = ast_ty_to_ty(tcx, getter, arg.node.ty); + let ty = ast_ty_to_ty(tcx, mode, arg.node.ty); ret {mode: default_arg_mode_for_ty(tcx, arg.node.mode, ty), ty: ty}; } alt tcx.ast_ty_to_ty_cache.find(ast_ty) { @@ -248,15 +266,15 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, &&ast_ty: @ast::ty) } /* go on */ tcx.ast_ty_to_ty_cache.insert(ast_ty, none::); - fn ast_mt_to_mt(tcx: ty::ctxt, getter: ty_getter, mt: ast::mt) -> ty::mt { - ret {ty: ast_ty_to_ty(tcx, getter, mt.ty), mut: mt.mut}; + fn ast_mt_to_mt(tcx: ty::ctxt, mode: mode, mt: ast::mt) -> ty::mt { + ret {ty: ast_ty_to_ty(tcx, mode, mt.ty), mut: mt.mut}; } - fn instantiate(tcx: ty::ctxt, sp: span, getter: ty_getter, + fn instantiate(tcx: ty::ctxt, sp: span, mode: mode, 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_kinds_and_ty = getter(id); + let ty_param_kinds_and_ty = getter(tcx, mode, id); if vec::len(ty_param_kinds_and_ty.kinds) == 0u { ret ty_param_kinds_and_ty.ty; } @@ -268,7 +286,7 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, &&ast_ty: @ast::ty) polymorphic type"); } for ast_ty: @ast::ty in args { - param_bindings += [ast_ty_to_ty(tcx, getter, ast_ty)]; + param_bindings += [ast_ty_to_ty(tcx, mode, ast_ty)]; } let typ = ty::substitute_type_params(tcx, param_bindings, @@ -286,25 +304,25 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, &&ast_ty: @ast::ty) ast::ty_float(ft) { typ = ty::mk_mach_float(tcx, ft); } ast::ty_str. { typ = ty::mk_str(tcx); } ast::ty_box(mt) { - typ = ty::mk_box(tcx, ast_mt_to_mt(tcx, getter, mt)); + typ = ty::mk_box(tcx, ast_mt_to_mt(tcx, mode, mt)); } ast::ty_uniq(mt) { - typ = ty::mk_uniq(tcx, ast_mt_to_mt(tcx, getter, mt)); + typ = ty::mk_uniq(tcx, ast_mt_to_mt(tcx, mode, mt)); } ast::ty_vec(mt) { - typ = ty::mk_vec(tcx, ast_mt_to_mt(tcx, getter, mt)); + typ = ty::mk_vec(tcx, ast_mt_to_mt(tcx, mode, mt)); } ast::ty_ptr(mt) { - typ = ty::mk_ptr(tcx, ast_mt_to_mt(tcx, getter, mt)); + typ = ty::mk_ptr(tcx, ast_mt_to_mt(tcx, mode, mt)); } ast::ty_tup(fields) { - let flds = vec::map(bind ast_ty_to_ty(tcx, getter, _), fields); + let flds = vec::map(bind ast_ty_to_ty(tcx, mode, _), fields); typ = ty::mk_tup(tcx, flds); } ast::ty_rec(fields) { let flds: [field] = []; for f: ast::ty_field in fields { - let tm = ast_mt_to_mt(tcx, getter, f.node.mt); + let tm = ast_mt_to_mt(tcx, mode, f.node.mt); flds += [{ident: f.node.ident, mt: tm}]; } typ = ty::mk_rec(tcx, flds); @@ -312,9 +330,9 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, &&ast_ty: @ast::ty) ast::ty_fn(proto, inputs, output, cf, constrs) { let i = []; for ta: ast::ty_arg in inputs { - i += [ast_arg_to_arg(tcx, getter, ta)]; + i += [ast_arg_to_arg(tcx, mode, ta)]; } - let out_ty = ast_ty_to_ty(tcx, getter, output); + let out_ty = ast_ty_to_ty(tcx, mode, output); let out_constrs = []; for constr: @ast::constr in constrs { @@ -325,9 +343,9 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, &&ast_ty: @ast::ty) ast::ty_path(path, id) { alt tcx.def_map.find(id) { some(ast::def_ty(id)) { - typ = instantiate(tcx, ast_ty.span, getter, id, path.node.types); + typ = instantiate(tcx, ast_ty.span, mode, id, path.node.types); } - some(ast::def_native_ty(id)) { typ = getter(id).ty; } + some(ast::def_native_ty(id)) { typ = getter(tcx, mode, id).ty; } some(ast::def_ty_param(id, k)) { typ = ty::mk_param(tcx, id, k); } some(_) { tcx.sess.span_fatal(ast_ty.span, @@ -344,9 +362,9 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, &&ast_ty: @ast::ty) for m: ast::ty_method in meths { let ins = []; for ta: ast::ty_arg in m.node.inputs { - ins += [ast_arg_to_arg(tcx, getter, ta)]; + ins += [ast_arg_to_arg(tcx, mode, ta)]; } - let out = ast_ty_to_ty(tcx, getter, m.node.output); + let out = ast_ty_to_ty(tcx, mode, m.node.output); let out_constrs = []; for constr: @ast::constr in m.node.constrs { @@ -368,10 +386,14 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, &&ast_ty: @ast::ty) for constr: @ast::ty_constr in cs { out_cs += [ty::ast_constr_to_constr(tcx, constr)]; } - typ = ty::mk_constr(tcx, ast_ty_to_ty(tcx, getter, t), out_cs); + typ = ty::mk_constr(tcx, ast_ty_to_ty(tcx, mode, t), out_cs); } ast::ty_infer. { - tcx.sess.span_bug(ast_ty.span, "found ty_infer in unexpected place"); + alt mode { + m_check_tyvar(fcx) { ret next_ty_var(fcx); } + _ { tcx.sess.span_bug(ast_ty.span, + "found ty_infer in unexpected place"); } + } } } alt cname { @@ -382,16 +404,160 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, &&ast_ty: @ast::ty) ret typ; } +fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item) + -> ty::ty_param_kinds_and_ty { + let no_kinds: [ast::kind] = []; + alt it.node { + ast::item_const(t, _) { + let typ = ast_ty_to_ty(tcx, mode, t); + let tpt = {kinds: no_kinds, ty: typ}; + tcx.tcache.insert(local_def(it.id), tpt); + ret tpt; + } + ast::item_fn(fn_info, tps) { + ret ty_of_fn_decl(tcx, mode, fn_info.decl, fn_info.proto, + tps, some(local_def(it.id))); + } + ast::item_obj(ob, tps, _) { + let t_obj = ty_of_obj(tcx, mode, it.ident, ob, tps); + tcx.tcache.insert(local_def(it.id), t_obj); + ret t_obj; + } + ast::item_ty(t, tps) { + alt tcx.tcache.find(local_def(it.id)) { + some(tpt) { ret tpt; } + none. { } + } + // Tell ast_ty_to_ty() that we want to perform a recursive + // call to resolve any named types. + + let typ = ast_ty_to_ty(tcx, mode, t); + let tpt = {kinds: ty_param_kinds(tps), ty: typ}; + tcx.tcache.insert(local_def(it.id), tpt); + ret tpt; + } + ast::item_res(f, _, tps, _) { + let t_arg = ty_of_arg(tcx, mode, f.decl.inputs[0]); + let t_res = + {kinds: ty_param_kinds(tps), + ty: ty::mk_res(tcx, local_def(it.id), t_arg.ty, + mk_ty_params(tcx, tps))}; + tcx.tcache.insert(local_def(it.id), t_res); + ret t_res; + } + ast::item_tag(_, tps) { + // Create a new generic polytype. + let subtys: [ty::t] = mk_ty_params(tcx, tps); + let t = ty::mk_tag(tcx, local_def(it.id), subtys); + let tpt = {kinds: ty_param_kinds(tps), ty: t}; + tcx.tcache.insert(local_def(it.id), tpt); + ret tpt; + } + ast::item_mod(_) { fail; } + ast::item_native_mod(_) { fail; } + } +} +fn ty_of_native_item(tcx: ty::ctxt, mode: mode, it: @ast::native_item) + -> ty::ty_param_kinds_and_ty { + let no_kinds: [ast::kind] = []; + alt it.node { + ast::native_item_fn(fn_decl, params) { + ret ty_of_native_fn_decl(tcx, mode, fn_decl, params, + ast_util::local_def(it.id)); + } + ast::native_item_ty. { + alt tcx.tcache.find(local_def(it.id)) { + some(tpt) { ret tpt; } + none. { } + } + let t = ty::mk_native(tcx, ast_util::local_def(it.id)); + let tpt = {kinds: no_kinds, ty: t}; + tcx.tcache.insert(local_def(it.id), tpt); + ret tpt; + } + } +} +fn ty_of_arg(tcx: ty::ctxt, mode: mode, a: ast::arg) -> ty::arg { + let ty = ast_ty_to_ty(tcx, mode, a.ty); + {mode: default_arg_mode_for_ty(tcx, a.mode, ty), ty: ty} +} +fn ty_of_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl, + proto: ast::proto, ty_params: [ast::ty_param], + def_id: option::t) -> ty::ty_param_kinds_and_ty { + let input_tys = []; + for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; } + let output_ty = ast_ty_to_ty(tcx, mode, decl.output); + + let out_constrs = []; + for constr: @ast::constr in decl.constraints { + out_constrs += [ty::ast_constr_to_constr(tcx, constr)]; + } + let t_fn = ty::mk_fn(tcx, proto, input_tys, output_ty, + decl.cf, out_constrs); + let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn}; + alt def_id { some(did) { tcx.tcache.insert(did, tpt); } _ { } } + ret tpt; +} +fn ty_of_native_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl, + ty_params: [ast::ty_param], def_id: ast::def_id) + -> ty::ty_param_kinds_and_ty { + let input_tys = []; + for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(tcx, mode, a)]; } + let output_ty = ast_ty_to_ty(tcx, mode, decl.output); + + let t_fn = ty::mk_native_fn(tcx, input_tys, output_ty); + let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn}; + tcx.tcache.insert(def_id, tpt); + ret tpt; +} +fn ty_of_method(tcx: ty::ctxt, mode: mode, m: @ast::method) -> ty::method { + let inputs = vec::map({|i| ty_of_arg(tcx, mode, i)}, + m.node.meth.decl.inputs); + let output = ast_ty_to_ty(tcx, mode, m.node.meth.decl.output); + + let out_constrs = []; + for constr: @ast::constr in m.node.meth.decl.constraints { + out_constrs += [ty::ast_constr_to_constr(tcx, constr)]; + } + ret {proto: m.node.meth.proto, + ident: m.node.ident, + inputs: inputs, + output: output, + cf: m.node.meth.decl.cf, + constrs: out_constrs}; +} +fn ty_of_obj(tcx: ty::ctxt, mode: mode, id: ast::ident, ob: ast::_obj, + ty_params: [ast::ty_param]) -> ty::ty_param_kinds_and_ty { + let methods = ty_of_obj_methods(tcx, mode, ob); + let t_obj = ty::mk_obj(tcx, ty::sort_methods(methods)); + t_obj = ty::rename(tcx, t_obj, id); + ret {kinds: ty_param_kinds(ty_params), ty: t_obj}; +} +fn ty_of_obj_methods(tcx: ty::ctxt, mode: mode, object: ast::_obj) + -> [ty::method] { + vec::map({|m| ty_of_method(tcx, mode, m)}, object.methods) +} +fn ty_of_obj_ctor(tcx: ty::ctxt, mode: mode, id: ast::ident, ob: ast::_obj, + ctor_id: ast::node_id, ty_params: [ast::ty_param]) + -> ty::ty_param_kinds_and_ty { + let t_obj = ty_of_obj(tcx, mode, id, ob, ty_params); + let t_inputs: [arg] = []; + for f: ast::obj_field in ob.fields { + let t_field = ast_ty_to_ty(tcx, mode, f.ty); + t_inputs += [{mode: ast::by_copy, ty: t_field}]; + } + let t_fn = ty::mk_fn(tcx, ast::proto_shared(ast::sugar_normal), + t_inputs, t_obj.ty, + ast::return_val, []); + let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn}; + tcx.tcache.insert(local_def(ctor_id), tpt); + ret tpt; +} // A convenience function to use a crate_ctxt to resolve names for // ast_ty_to_ty. fn ast_ty_to_ty_crate(ccx: @crate_ctxt, &&ast_ty: @ast::ty) -> ty::t { - fn getter(ccx: @crate_ctxt, id: ast::def_id) -> - ty::ty_param_kinds_and_ty { - ret ty::lookup_item_type(ccx.tcx, id); - } - let f = bind getter(ccx, _); - ret ast_ty_to_ty(ccx.tcx, f, ast_ty); + ret ast_ty_to_ty(ccx.tcx, m_check, ast_ty); } // A wrapper around ast_ty_to_ty_crate that handles ty_infer. @@ -402,14 +568,6 @@ fn ast_ty_to_ty_crate_infer(ccx: @crate_ctxt, &&ast_ty: @ast::ty) -> _ { some(ast_ty_to_ty_crate(ccx, ast_ty)) } } } -// A wrapper around ast_ty_to_ty_infer that generates a new type variable if -// there isn't a fixed type. -fn ast_ty_to_ty_crate_tyvar(fcx: @fn_ctxt, &&ast_ty: @ast::ty) -> ty::t { - alt ast_ty_to_ty_crate_infer(fcx.ccx, ast_ty) { - some(ty) { ty } - none. { next_ty_var(fcx) } - } -} // Functions that write types into the node type table. @@ -428,7 +586,7 @@ mod write { // Writes a type parameter count and type pair into the node type table. // This function allows for the possibility of type variables, which will - // be rewritten later during the fixup phase. + // be rewritten later during the fixup mode. fn ty_fixup(fcx: @fn_ctxt, node_id: ast::node_id, tpot: ty_param_substs_opt_and_ty) { inner(fcx.ccx.tcx.node_types, node_id, tpot); @@ -459,6 +617,21 @@ mod write { } } +fn mk_ty_params(tcx: ty::ctxt, atps: [ast::ty_param]) -> [ty::t] { + let tps = []; + let i = 0u; + for atp: ast::ty_param in atps { + tps += [ty::mk_param(tcx, i, ty_param_kind(atp))]; + i += 1u; + } + ret tps; +} + +fn ty_param_kinds(tps: [ast::ty_param]) -> [ast::kind] { + let k: [ast::kind] = []; + for p: ast::ty_param in tps { k += [ty_param_kind(p)]; } + ret k; +} // Item collection - a pair of bootstrap passes: // @@ -477,209 +650,12 @@ mod write { mod collect { type ctxt = {tcx: ty::ctxt}; - fn mk_ty_params(cx: @ctxt, atps: [ast::ty_param]) -> [ty::t] { - let tps = []; - let i = 0u; - for atp: ast::ty_param in atps { - tps += [ty::mk_param(cx.tcx, i, ty_param_kind(atp))]; - i += 1u; - } - ret tps; - } - - fn ty_param_kinds(tps: [ast::ty_param]) -> [ast::kind] { - let k: [ast::kind] = []; - for p: ast::ty_param in tps { k += [ty_param_kind(p)]; } - ret k; - } - - fn ty_of_fn_decl(cx: @ctxt, convert: fn@(&&@ast::ty) -> ty::t, - ty_of_arg: fn@(ast::arg) -> arg, decl: ast::fn_decl, - proto: ast::proto, ty_params: [ast::ty_param], - def_id: option::t) -> - ty::ty_param_kinds_and_ty { - let input_tys = []; - for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(a)]; } - let output_ty = convert(decl.output); - - let out_constrs = []; - for constr: @ast::constr in decl.constraints { - out_constrs += [ty::ast_constr_to_constr(cx.tcx, constr)]; - } - let t_fn = - ty::mk_fn(cx.tcx, proto, input_tys, output_ty, - decl.cf, out_constrs); - let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn}; - alt def_id { some(did) { cx.tcx.tcache.insert(did, tpt); } _ { } } - ret tpt; - } - fn ty_of_native_fn_decl(cx: @ctxt, convert: fn@(&&@ast::ty) -> ty::t, - ty_of_arg: fn@(ast::arg) -> arg, - decl: ast::fn_decl, - ty_params: [ast::ty_param], def_id: ast::def_id) - -> ty::ty_param_kinds_and_ty { - let input_tys = []; - for a: ast::arg in decl.inputs { input_tys += [ty_of_arg(a)]; } - let output_ty = convert(decl.output); - - let t_fn = ty::mk_native_fn(cx.tcx, input_tys, output_ty); - let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn}; - cx.tcx.tcache.insert(def_id, tpt); - ret tpt; - } - fn getter(cx: @ctxt, id: ast::def_id) -> ty::ty_param_kinds_and_ty { - if id.crate != ast::local_crate { - // This is a type we need to load in from the crate reader. - ret csearch::get_type(cx.tcx, id); - } - let it = cx.tcx.items.find(id.node); - let tpt; - alt it { - some(ast_map::node_item(item)) { tpt = ty_of_item(cx, item); } - some(ast_map::node_native_item(native_item)) { - tpt = ty_of_native_item(cx, native_item); - } - _ { cx.tcx.sess.fatal("internal error " + std::int::str(id.node)); } - } - ret tpt; - } - fn ty_of_arg(cx: @ctxt, a: ast::arg) -> ty::arg { - let ty = ast_ty_to_ty(cx.tcx, bind getter(cx, _), a.ty); - {mode: default_arg_mode_for_ty(cx.tcx, a.mode, ty), ty: ty} - } - fn ty_of_method(cx: @ctxt, m: @ast::method) -> ty::method { - let get = bind getter(cx, _); - let convert = bind ast_ty_to_ty(cx.tcx, get, _); - - let inputs = []; - for a: ast::arg in m.node.meth.decl.inputs { - inputs += [ty_of_arg(cx, a)]; - } - - let output = convert(m.node.meth.decl.output); - - let out_constrs = []; - for constr: @ast::constr in m.node.meth.decl.constraints { - out_constrs += [ty::ast_constr_to_constr(cx.tcx, constr)]; - } - ret {proto: m.node.meth.proto, - ident: m.node.ident, - inputs: inputs, - output: output, - cf: m.node.meth.decl.cf, - constrs: out_constrs}; - } - fn ty_of_obj(cx: @ctxt, id: ast::ident, ob: ast::_obj, - ty_params: [ast::ty_param]) -> ty::ty_param_kinds_and_ty { - let methods = get_obj_method_types(cx, ob); - let t_obj = ty::mk_obj(cx.tcx, ty::sort_methods(methods)); - t_obj = ty::rename(cx.tcx, t_obj, id); - ret {kinds: ty_param_kinds(ty_params), ty: t_obj}; - } - fn ty_of_obj_ctor(cx: @ctxt, id: ast::ident, ob: ast::_obj, - ctor_id: ast::node_id, ty_params: [ast::ty_param]) -> - ty::ty_param_kinds_and_ty { - let t_obj = ty_of_obj(cx, id, ob, ty_params); - - let t_inputs: [arg] = []; - for f: ast::obj_field in ob.fields { - let g = bind getter(cx, _); - let t_field = ast_ty_to_ty(cx.tcx, g, f.ty); - t_inputs += [{mode: ast::by_copy, ty: t_field}]; - } - - let t_fn = - ty::mk_fn(cx.tcx, ast::proto_shared(ast::sugar_normal), - t_inputs, t_obj.ty, - ast::return_val, []); - let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn}; - cx.tcx.tcache.insert(local_def(ctor_id), tpt); - ret tpt; - } - fn ty_of_item(cx: @ctxt, it: @ast::item) -> ty::ty_param_kinds_and_ty { - let get = bind getter(cx, _); - let convert = bind ast_ty_to_ty(cx.tcx, get, _); - let no_kinds: [ast::kind] = []; - alt it.node { - ast::item_const(t, _) { - let typ = convert(t); - let tpt = {kinds: no_kinds, ty: typ}; - cx.tcx.tcache.insert(local_def(it.id), tpt); - ret tpt; - } - ast::item_fn(fn_info, tps) { - let f = bind ty_of_arg(cx, _); - ret ty_of_fn_decl(cx, convert, f, fn_info.decl, fn_info.proto, - tps, some(local_def(it.id))); - } - ast::item_obj(ob, tps, _) { - let t_obj = ty_of_obj(cx, it.ident, ob, tps); - cx.tcx.tcache.insert(local_def(it.id), t_obj); - ret t_obj; - } - ast::item_ty(t, tps) { - alt cx.tcx.tcache.find(local_def(it.id)) { - some(tpt) { ret tpt; } - none. { } - } - // Tell ast_ty_to_ty() that we want to perform a recursive - // call to resolve any named types. - - let typ = convert(t); - let tpt = {kinds: ty_param_kinds(tps), ty: typ}; - cx.tcx.tcache.insert(local_def(it.id), tpt); - ret tpt; - } - ast::item_res(f, _, tps, _) { - let t_arg = ty_of_arg(cx, f.decl.inputs[0]); - let t_res = - {kinds: ty_param_kinds(tps), - ty: ty::mk_res(cx.tcx, local_def(it.id), t_arg.ty, - mk_ty_params(cx, tps))}; - cx.tcx.tcache.insert(local_def(it.id), t_res); - ret t_res; - } - ast::item_tag(_, tps) { - // Create a new generic polytype. - let subtys: [ty::t] = mk_ty_params(cx, tps); - let t = ty::mk_tag(cx.tcx, local_def(it.id), subtys); - let tpt = {kinds: ty_param_kinds(tps), ty: t}; - cx.tcx.tcache.insert(local_def(it.id), tpt); - ret tpt; - } - ast::item_mod(_) { fail; } - ast::item_native_mod(_) { fail; } - } - } - fn ty_of_native_item(cx: @ctxt, it: @ast::native_item) - -> ty::ty_param_kinds_and_ty { - let no_kinds: [ast::kind] = []; - alt it.node { - ast::native_item_fn(fn_decl, params) { - let get = bind getter(cx, _); - let convert = bind ast_ty_to_ty(cx.tcx, get, _); - let f = bind ty_of_arg(cx, _); - ret ty_of_native_fn_decl(cx, convert, f, fn_decl, params, - ast_util::local_def(it.id)); - } - ast::native_item_ty. { - alt cx.tcx.tcache.find(local_def(it.id)) { - some(tpt) { ret tpt; } - none. { } - } - let t = ty::mk_native(cx.tcx, ast_util::local_def(it.id)); - let tpt = {kinds: no_kinds, ty: t}; - cx.tcx.tcache.insert(local_def(it.id), tpt); - ret tpt; - } - } - } fn get_tag_variant_types(cx: @ctxt, tag_id: ast::def_id, variants: [ast::variant], ty_params: [ast::ty_param]) { // Create a set of parameter types shared among all the variants. - let ty_param_tys: [ty::t] = mk_ty_params(cx, ty_params); + let ty_param_tys: [ty::t] = mk_ty_params(cx.tcx, ty_params); for variant: ast::variant in variants { // Nullary tag constructors get turned into constants; n-ary tag // constructors get turned into functions. @@ -690,11 +666,9 @@ mod collect { } else { // As above, tell ast_ty_to_ty() that trans_ty_item_to_ty() // should be called to resolve named types. - - let f = bind getter(cx, _); let args: [arg] = []; for va: ast::variant_arg in variant.node.args { - let arg_ty = ast_ty_to_ty(cx.tcx, f, va.ty); + let arg_ty = ast_ty_to_ty(cx.tcx, m_collect, va.ty); args += [{mode: ast::by_copy, ty: arg_ty}]; } let tag_t = ty::mk_tag(cx.tcx, tag_id, ty_param_tys); @@ -709,13 +683,6 @@ mod collect { write::ty_only(cx.tcx, variant.node.id, result_ty); } } - fn get_obj_method_types(cx: @ctxt, object: ast::_obj) -> [ty::method] { - let meths = []; - for m: @ast::method in object.methods { - meths += [ty_of_method(cx, m)]; - } - ret meths; - } fn convert(cx: @ctxt, it: @ast::item) { alt it.node { ast::item_mod(_) { @@ -725,24 +692,23 @@ mod collect { // do nothing, as native modules have no types. } ast::item_tag(variants, ty_params) { - let tpt = ty_of_item(cx, it); + let tpt = ty_of_item(cx.tcx, m_collect, it); write::ty_only(cx.tcx, it.id, tpt.ty); get_tag_variant_types(cx, local_def(it.id), variants, ty_params); } ast::item_obj(object, ty_params, ctor_id) { // Now we need to call ty_of_obj_ctor(); this is the type that // we write into the table for this item. - ty_of_item(cx, it); - - let tpt = - ty_of_obj_ctor(cx, it.ident, object, ctor_id, ty_params); + ty_of_item(cx.tcx, m_collect, it); + let tpt = ty_of_obj_ctor(cx.tcx, m_collect, it.ident, object, + ctor_id, ty_params); write::ty_only(cx.tcx, ctor_id, tpt.ty); // Write the methods into the type table. // // FIXME: Inefficient; this ends up calling // get_obj_method_types() twice. (The first time was above in // ty_of_obj().) - let method_types = get_obj_method_types(cx, object); + let method_types = ty_of_obj_methods(cx.tcx, m_collect, object); let i = 0u; while i < vec::len::<@ast::method>(object.methods) { write::ty_only(cx.tcx, object.methods[i].node.id, @@ -763,10 +729,10 @@ mod collect { } } ast::item_res(f, dtor_id, tps, ctor_id) { - let t_arg = ty_of_arg(cx, f.decl.inputs[0]); + let t_arg = ty_of_arg(cx.tcx, m_collect, f.decl.inputs[0]); let t_res = ty::mk_res(cx.tcx, local_def(it.id), t_arg.ty, - mk_ty_params(cx, tps)); + mk_ty_params(cx.tcx, tps)); let t_ctor = ty::mk_fn(cx.tcx, ast::proto_shared(ast::sugar_normal), [{mode: ast::by_copy with t_arg}], t_res, @@ -786,7 +752,7 @@ mod collect { // This call populates the type cache with the converted type // of the item in passing. All we have to do here is to write // it into the node type table. - let tpt = ty_of_item(cx, it); + let tpt = ty_of_item(cx.tcx, m_collect, it); write::ty_only(cx.tcx, it.id, tpt.ty); } } @@ -795,7 +761,7 @@ mod collect { // As above, this call populates the type table with the converted // type of the native item. We simply write it into the node type // table. - let tpt = ty_of_native_item(cx, i); + let tpt = ty_of_native_item(cx.tcx, m_collect, i); alt i.node { ast::native_item_ty. { // FIXME: Native types have no annotation. Should they? --pcw @@ -1936,15 +1902,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, write::ty_only_fixup(fcx, id, result_ty); } ast::expr_fn(f) { - let convert = bind ast_ty_to_ty_crate_tyvar(fcx, _); - let ty_of_arg = lambda (a: ast::arg) -> ty::arg { - let tt = ast_ty_to_ty_crate_tyvar(fcx, a.ty); - ret {mode: default_arg_mode_for_ty(fcx.ccx.tcx, a.mode, tt), - ty: tt}; - }; let cx = @{tcx: tcx}; - let fty = collect::ty_of_fn_decl(cx, convert, ty_of_arg, f.decl, - f.proto, [], none).ty; + let fty = ty_of_fn_decl(cx.tcx, m_check_tyvar(fcx), f.decl, + f.proto, [], none).ty; write::ty_only_fixup(fcx, id, fty); @@ -2241,41 +2201,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, let fields: [ast::anon_obj_field] = []; alt ao.fields { none. { } some(v) { fields = v; } } - // FIXME: These next three functions are largely ripped off from - // similar ones in collect::. Is there a better way to do this? - fn ty_of_arg(ccx: @crate_ctxt, a: ast::arg) -> ty::arg { - let ty = ast_ty_to_ty_crate(ccx, a.ty); - ret {mode: default_arg_mode_for_ty(ccx.tcx, a.mode, ty), ty: ty}; - } - - fn ty_of_method(ccx: @crate_ctxt, m: @ast::method) -> ty::method { - let convert = bind ast_ty_to_ty_crate(ccx, _); - - let inputs = []; - for aa: ast::arg in m.node.meth.decl.inputs { - inputs += [ty_of_arg(ccx, aa)]; - } - - let output = convert(m.node.meth.decl.output); - - let out_constrs = []; - for constr: @ast::constr in m.node.meth.decl.constraints { - out_constrs += [ty::ast_constr_to_constr(ccx.tcx, constr)]; - } - - ret {proto: m.node.meth.proto, - ident: m.node.ident, - inputs: inputs, - output: output, - cf: m.node.meth.decl.cf, - constrs: out_constrs}; - } - let method_types: [ty::method] = []; { // Outer methods. for m: @ast::method in ao.methods { - method_types += [ty_of_method(fcx.ccx, m)]; + method_types += [ty_of_method(fcx.ccx.tcx, m_check, m)]; } // Inner methods. @@ -2326,7 +2256,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, if str::eq(om.node.ident, m.ident) { // We'd better be overriding with one of the same // type. Check to make sure. - let new_type = ty_of_method(ccx, om); + let new_type = ty_of_method(ccx.tcx, m_check, om); if new_type != m { ccx.tcx.sess.span_fatal (om.span, "attempted to override method " @@ -2517,22 +2447,20 @@ fn check_pred_expr(fcx: @fn_ctxt, e: @ast::expr) -> bool { _ { fcx.ccx.tcx.sess.span_err(operator.span, "Impure function as operator \ -in constraint"); + in constraint"); } } for operand: @ast::expr in operands { if !ast_util::is_constraint_arg(operand) { let s = - "Constraint args must be \ -slot variables or literals"; + "Constraint args must be slot variables or literals"; fcx.ccx.tcx.sess.span_err(e.span, s); } } } _ { - let s = - "In a constraint, expected the \ -constraint name to be an explicit name"; + let s = "In a constraint, expected the \ + constraint name to be an explicit name"; fcx.ccx.tcx.sess.span_err(e.span, s); } }