Substitute type parameters more eagerly

This simplifies the typechecker a bit (no more ty_param_substs_opt_and_ty)
and is needed for another experiment I'm playing with. I hope it also
makes compilation faster (the bots will tell).
This commit is contained in:
Marijn Haverbeke 2012-01-30 17:28:30 +01:00
parent 964bd485c6
commit 86d473ad1f
10 changed files with 201 additions and 304 deletions

View File

@ -8,7 +8,7 @@ import syntax::ast_util::local_def;
import common::*;
import middle::trans::common::crate_ctxt;
import middle::ty;
import middle::ty::node_id_to_monotype;
import middle::ty::node_id_to_type;
import front::attr;
export encode_metadata;
@ -243,7 +243,7 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer,
encode_name(ebml_w, variant.node.name);
encode_enum_id(ebml_w, local_def(id));
encode_type(ecx, ebml_w,
node_id_to_monotype(ecx.ccx.tcx, variant.node.id));
node_id_to_type(ecx.ccx.tcx, variant.node.id));
if vec::len::<variant_arg>(variant.node.args) > 0u {
encode_symbol(ecx, ebml_w, variant.node.id);
}
@ -287,7 +287,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'c' as u8);
encode_type(ecx, ebml_w, node_id_to_monotype(tcx, item.id));
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_symbol(ecx, ebml_w, item.id);
ebml::end_tag(ebml_w);
}
@ -301,7 +301,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
impure_fn { 'f' }
} as u8);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_monotype(tcx, item.id));
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_symbol(ecx, ebml_w, item.id);
ebml::end_tag(ebml_w);
}
@ -320,7 +320,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'y' as u8);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_monotype(tcx, item.id));
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
ebml::end_tag(ebml_w);
}
@ -329,7 +329,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 't' as u8);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_monotype(tcx, item.id));
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
for v: variant in variants {
encode_variant_id(ebml_w, local_def(v.node.id));
@ -338,7 +338,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_enum_variant_info(ecx, ebml_w, item.id, variants, index, tps);
}
item_res(_, tps, _, _, ctor_id) {
let fn_ty = node_id_to_monotype(tcx, ctor_id);
let fn_ty = node_id_to_type(tcx, ctor_id);
ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, local_def(ctor_id));
@ -363,7 +363,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'i' as u8);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_monotype(tcx, item.id));
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
for m in methods {
ebml::start_tag(ebml_w, tag_item_method);
@ -389,7 +389,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_family(ebml_w, 'f' as u8);
encode_type_param_bounds(ebml_w, ecx, tps + m.tps);
encode_type(ecx, ebml_w,
node_id_to_monotype(tcx, m.id));
node_id_to_type(tcx, m.id));
encode_name(ebml_w, m.ident);
encode_symbol(ecx, ebml_w, m.id);
ebml::end_tag(ebml_w);
@ -400,7 +400,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'I' as u8);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_monotype(tcx, item.id));
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
let i = 0u;
for mty in *ty::iface_methods(tcx, local_def(item.id)) {
@ -435,7 +435,7 @@ fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
encode_def_id(ebml_w, local_def(nitem.id));
encode_family(ebml_w, letter);
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, nitem.id));
encode_type(ecx, ebml_w, node_id_to_type(ecx.ccx.tcx, nitem.id));
encode_symbol(ecx, ebml_w, nitem.id);
}
}

View File

@ -59,7 +59,7 @@ fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map,
// closure.
fn with_appropriate_checker(cx: ctx, id: node_id,
b: fn(fn@(ctx, ty::t, sp: span))) {
let fty = ty::node_id_to_monotype(cx.tcx, id);
let fty = ty::node_id_to_type(cx.tcx, id);
alt ty::ty_fn_proto(cx.tcx, fty) {
proto_uniq { b(check_send); }
proto_box { b(check_copy); }
@ -168,8 +168,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
}
}
expr_path(_) {
let substs = ty::node_id_to_ty_param_substs_opt_and_ty(cx.tcx, e.id);
alt substs.substs {
alt cx.tcx.node_type_substs.find(e.id) {
some(ts) {
let did = ast_util::def_id_of_def(cx.tcx.def_map.get(e.id));
let bounds = ty::lookup_item_type(cx.tcx, did).bounds;

View File

@ -64,7 +64,7 @@ fn find_last_uses(c: @crate, def_map: resolve::def_map,
}
fn ex_is_blockish(cx: ctx, id: node_id) -> bool {
alt ty::struct(cx.tcx, ty::node_id_to_monotype(cx.tcx, id)) {
alt ty::struct(cx.tcx, ty::node_id_to_type(cx.tcx, id)) {
ty::ty_fn({proto: p, _}) if is_blockish(p) { true }
_ { false }
}

View File

@ -268,7 +268,7 @@ fn is_immutable_def(cx: @ctx, def: def) -> option::t<str> {
def_arg(_, mode_infer) { some("argument") }
def_self(_) { some("self argument") }
def_upvar(_, inner, node_id) {
let ty = ty::node_id_to_monotype(cx.tcx, node_id);
let ty = ty::node_id_to_type(cx.tcx, node_id);
let proto = ty::ty_fn_proto(cx.tcx, ty);
ret alt proto {
proto_any | proto_block { is_immutable_def(cx, *inner) }

View File

@ -419,7 +419,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
let rec_fields = collect_record_fields(m, col);
// Separate path for extracting and binding record fields
if vec::len(rec_fields) > 0u {
let rec_ty = ty::node_id_to_monotype(ccx.tcx, pat_id);
let rec_ty = ty::node_id_to_type(ccx.tcx, pat_id);
let fields =
alt ty::struct(ccx.tcx, rec_ty) { ty::ty_rec(fields) { fields } };
let rec_vals = [];
@ -437,7 +437,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
}
if any_tup_pat(m, col) {
let tup_ty = ty::node_id_to_monotype(ccx.tcx, pat_id);
let tup_ty = ty::node_id_to_type(ccx.tcx, pat_id);
let n_tup_elts =
alt ty::struct(ccx.tcx, tup_ty) {
ty::ty_tup(elts) { vec::len(elts) }
@ -492,7 +492,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
}
lit(l) {
test_val = Load(bcx, val);
let pty = ty::node_id_to_monotype(ccx.tcx, pat_id);
let pty = ty::node_id_to_type(ccx.tcx, pat_id);
kind = ty::type_is_integral(ccx.tcx, pty) ? switch : compare;
}
range(_, _) {
@ -709,7 +709,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
alt normalize_pat(bcx_tcx(bcx), pat).node {
ast::pat_ident(_,inner) {
if make_copy || ccx.copy_map.contains_key(pat.id) {
let ty = ty::node_id_to_monotype(ccx.tcx, pat.id);
let ty = ty::node_id_to_type(ccx.tcx, pat.id);
// FIXME: Could constrain pat_bind to make this
// check unnecessary.
check (type_has_static_size(ccx, ty));
@ -737,7 +737,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
}
}
ast::pat_rec(fields, _) {
let rec_ty = ty::node_id_to_monotype(ccx.tcx, pat.id);
let rec_ty = ty::node_id_to_type(ccx.tcx, pat.id);
let rec_fields =
alt ty::struct(ccx.tcx, rec_ty) { ty::ty_rec(fields) { fields } };
for f: ast::field_pat in fields {
@ -749,7 +749,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
}
}
ast::pat_tup(elems) {
let tup_ty = ty::node_id_to_monotype(ccx.tcx, pat.id);
let tup_ty = ty::node_id_to_type(ccx.tcx, pat.id);
let i = 0u;
for elem in elems {
// how to get rid of this check?

View File

@ -2048,7 +2048,7 @@ fn trans_lit(cx: @block_ctxt, lit: ast::lit, dest: dest) -> @block_ctxt {
// Converts an annotation to a type
fn node_id_type(cx: @crate_ctxt, id: ast::node_id) -> ty::t {
ret ty::node_id_to_monotype(cx.tcx, id);
ret ty::node_id_to_type(cx.tcx, id);
}
fn trans_unary(bcx: @block_ctxt, op: ast::unop, e: @ast::expr,
@ -2057,7 +2057,7 @@ fn trans_unary(bcx: @block_ctxt, op: ast::unop, e: @ast::expr,
alt bcx_ccx(bcx).method_map.find(un_expr.id) {
some(origin) {
let callee_id = ast_util::op_expr_callee_id(un_expr);
let fty = ty::node_id_to_monotype(bcx_tcx(bcx), callee_id);
let fty = ty::node_id_to_type(bcx_tcx(bcx), callee_id);
ret trans_call_inner(bcx, fty, {|bcx|
impl::trans_method_callee(bcx, callee_id, e, origin)
}, [], un_expr.id, dest);
@ -2195,7 +2195,7 @@ fn trans_assign_op(bcx: @block_ctxt, ex: @ast::expr, op: ast::binop,
alt bcx_ccx(bcx).method_map.find(ex.id) {
some(origin) {
let callee_id = ast_util::op_expr_callee_id(ex);
let fty = ty::node_id_to_monotype(bcx_tcx(bcx), callee_id);
let fty = ty::node_id_to_type(bcx_tcx(bcx), callee_id);
ret trans_call_inner(bcx, fty, {|bcx|
// FIXME provide the already-computed address, not the expr
impl::trans_method_callee(bcx, callee_id, dst, origin)
@ -2317,7 +2317,7 @@ fn trans_binary(bcx: @block_ctxt, op: ast::binop, lhs: @ast::expr,
alt bcx_ccx(bcx).method_map.find(ex.id) {
some(origin) {
let callee_id = ast_util::op_expr_callee_id(ex);
let fty = ty::node_id_to_monotype(bcx_tcx(bcx), callee_id);
let fty = ty::node_id_to_type(bcx_tcx(bcx), callee_id);
ret trans_call_inner(bcx, fty, {|bcx|
impl::trans_method_callee(bcx, callee_id, lhs, origin)
}, [rhs], ex.id, dest);
@ -2681,7 +2681,7 @@ fn trans_var(cx: @block_ctxt, def: ast::def, id: ast::node_id)
assert (ccx.consts.contains_key(did.node));
ret lval_no_env(cx, ccx.consts.get(did.node), owned);
} else {
let tp = ty::node_id_to_monotype(ccx.tcx, id);
let tp = ty::node_id_to_type(ccx.tcx, id);
let val = trans_external_path(cx, did, {bounds: @[], ty: tp});
ret lval_no_env(cx, load_if_immediate(cx, val, tp), owned_imm);
}
@ -3544,7 +3544,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
// If it is here, it's not an lval, so this is a user-defined index op
let origin = bcx_ccx(bcx).method_map.get(e.id);
let callee_id = ast_util::op_expr_callee_id(e);
let fty = ty::node_id_to_monotype(tcx, callee_id);
let fty = ty::node_id_to_type(tcx, callee_id);
ret trans_call_inner(bcx, fty, {|bcx|
impl::trans_method_callee(bcx, callee_id, base, origin)
}, [idx], e.id, dest);

View File

@ -417,7 +417,7 @@ fn build_closure(bcx0: @block_ctxt,
vec::iter(cap_vars) { |cap_var|
let lv = trans_local_var(bcx, cap_var.def);
let nid = ast_util::def_id_of_def(cap_var.def).node;
let ty = ty::node_id_to_monotype(tcx, nid);
let ty = ty::node_id_to_type(tcx, nid);
alt cap_var.mode {
capture::cap_ref {
assert ck == ty::ck_block;

View File

@ -46,7 +46,7 @@ fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method],
alt cx.ccx.item_ids.find(m.id) {
some(llfn) {
trans_fn(extend_path(sub_cx, m.ident), m.span, m.decl, m.body,
llfn, impl_self(ty::node_id_to_monotype(cx.ccx.tcx, id)),
llfn, impl_self(ty::node_id_to_type(cx.ccx.tcx, id)),
tps + m.tps, m.id);
}
}

View File

@ -22,10 +22,8 @@ import util::ppaux::ty_constr_to_str;
import util::ppaux::mode_str;
import syntax::print::pprust::*;
export node_id_to_monotype;
export node_id_to_type;
export node_id_to_type_params;
export node_id_to_ty_param_substs_opt_and_ty;
export arg;
export args_eq;
export ast_constr_to_constr;
@ -103,7 +101,6 @@ export new_ty_hash;
export enum_variants;
export iface_methods, store_iface_methods, impl_iface;
export enum_variant_with_id;
export ty_param_substs_opt_and_ty;
export ty_param_bounds_and_ty;
export ty_bool;
export ty_bot;
@ -136,7 +133,6 @@ export ty_var;
export ty_named;
export same_type;
export ty_var_id;
export ty_param_substs_opt_and_ty_to_monotype;
export ty_fn_args;
export type_constr;
export type_contains_params;
@ -212,6 +208,7 @@ type ctxt =
sess: session::session,
def_map: resolve::def_map,
node_types: node_type_table,
node_type_substs: hashmap<node_id, [t]>,
items: ast_map::map,
freevars: freevars::freevar_map,
tcache: type_cache,
@ -369,12 +366,7 @@ const idx_first_others: uint = 20u;
type type_store = interner::interner<@raw_t>;
// substs is a list of actuals that correspond to ty's
// formal parameters
type ty_param_substs_opt_and_ty = {substs: option::t<[ty::t]>, ty: ty::t};
type node_type_table =
@smallintmap::smallintmap<ty::ty_param_substs_opt_and_ty>;
type node_type_table = @smallintmap::smallintmap<t>;
fn populate_type_store(cx: ctxt) {
intern(cx, ty_nil);
@ -415,8 +407,6 @@ fn new_ty_hash<V: copy>() -> map::hashmap<t, V> { map::new_uint_hash() }
fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
freevars: freevars::freevar_map) -> ctxt {
let ntt: node_type_table =
@smallintmap::mk::<ty::ty_param_substs_opt_and_ty>();
fn eq_raw_ty(&&a: @raw_t, &&b: @raw_t) -> bool {
ret a.hash == b.hash && a.struct == b.struct;
}
@ -425,7 +415,8 @@ fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
@{ts: ts,
sess: s,
def_map: dm,
node_types: ntt,
node_types: @smallintmap::mk(),
node_type_substs: map::new_int_hash(),
items: amap,
freevars: freevars,
tcache: new_def_hash(),
@ -1442,55 +1433,21 @@ fn constrs_eq(cs: [@constr], ds: [@constr]) -> bool {
ret true;
}
// Type lookups
fn node_id_to_ty_param_substs_opt_and_ty(cx: ctxt, id: ast::node_id) ->
ty_param_substs_opt_and_ty {
// Pull out the node type table.
alt smallintmap::find(*cx.node_types, id as uint) {
none {
cx.sess.bug("node_id_to_ty_param_substs_opt_and_ty() called on " +
"an untyped node (" + int::to_str(id, 10u) +
")");
}
some(tpot) { ret tpot; }
}
}
fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
ret node_id_to_ty_param_substs_opt_and_ty(cx, id).ty;
smallintmap::get(*cx.node_types, id as uint)
}
fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> [t] {
alt node_id_to_ty_param_substs_opt_and_ty(cx, id).substs {
alt cx.node_type_substs.find(id) {
none { ret []; }
some(tps) { ret tps; }
some(ts) { ret ts; }
}
}
fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
ret vec::len(node_id_to_type_params(cx, id)) > 0u;
ret cx.node_type_substs.contains_key(id);
}
// Returns a type with type parameter substitutions performed if applicable
fn ty_param_substs_opt_and_ty_to_monotype(cx: ctxt,
tpot: ty_param_substs_opt_and_ty) ->
t {
alt tpot.substs {
none { ret tpot.ty; }
some(tps) { ret substitute_type_params(cx, tps, tpot.ty); }
}
}
// Returns the type of an annotation, with type parameter substitutions
// performed if applicable
fn node_id_to_monotype(cx: ctxt, id: ast::node_id) -> t {
let tpot = node_id_to_ty_param_substs_opt_and_ty(cx, id);
ret ty_param_substs_opt_and_ty_to_monotype(cx, tpot);
}
// Returns the number of distinct type parameters in the given type.
fn count_ty_params(cx: ctxt, ty: t) -> uint {
fn counter(cx: ctxt, param_indices: @mutable [uint], ty: t) {
@ -1587,7 +1544,7 @@ fn block_ty(cx: ctxt, b: ast::blk) -> t {
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
fn pat_ty(cx: ctxt, pat: @ast::pat) -> t {
ret node_id_to_monotype(cx, pat.id);
ret node_id_to_type(cx, pat.id);
}
@ -1598,7 +1555,7 @@ fn pat_ty(cx: ctxt, pat: @ast::pat) -> t {
// instead of "fn(t) -> T with T = int". If this isn't what you want, see
// expr_ty_params_and_ty() below.
fn expr_ty(cx: ctxt, expr: @ast::expr) -> t {
ret node_id_to_monotype(cx, expr.id);
ret node_id_to_type(cx, expr.id);
}
fn expr_ty_params_and_ty(cx: ctxt, expr: @ast::expr) -> {params: [t], ty: t} {
@ -1740,7 +1697,6 @@ mod unify {
}
);
alt smallintmap::find(vb.types, root_a) {
none {
alt smallintmap::find(vb.types, root_b) {
@ -2534,7 +2490,6 @@ fn type_err_to_str(err: ty::type_err) -> str {
// Replaces type parameters in the given type using the given list of
// substitions.
fn substitute_type_params(cx: ctxt, substs: [ty::t], typ: t) -> t {
if !type_contains_params(cx, typ) { ret typ; }
// Precondition? idx < vec::len(substs)
fn substituter(_cx: ctxt, substs: @[ty::t], idx: uint, _did: def_id)
@ -2603,7 +2558,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
ast_map::node_item(@{node: ast::item_enum(variants, _), _}) {
let disr_val = -1;
@vec::map(variants, {|variant|
let ctor_ty = node_id_to_monotype(cx, variant.node.id);
let ctor_ty = node_id_to_type(cx, variant.node.id);
let arg_tys = if vec::len(variant.node.args) > 0u {
vec::map(ty_fn_args(cx, ctor_ty), {|a| a.ty})
} else { [] };

View File

@ -10,7 +10,7 @@ import pat_util::*;
import middle::ty;
import middle::ty::{node_id_to_type, arg, block_ty,
expr_ty, field, node_type_table, mk_nil,
ty_param_substs_opt_and_ty, ty_param_bounds_and_ty};
ty_param_bounds_and_ty};
import util::ppaux::ty_to_str;
import middle::ty::unify::{ures_ok, ures_err, fix_ok, fix_err};
import core::{int, vec, str, option};
@ -137,33 +137,35 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
// Instantiates the given path, which must refer to an item with the given
// number of type parameters and type.
fn instantiate_path(fcx: @fn_ctxt, pth: @ast::path,
tpt: ty_param_bounds_and_ty, sp: span)
-> ty_param_substs_opt_and_ty {
tpt: ty_param_bounds_and_ty, sp: span,
id: ast::node_id) {
let ty_param_count = vec::len(*tpt.bounds);
let vars = vec::init_fn(ty_param_count, {|_i| next_ty_var(fcx)});
let ty_substs_len = vec::len(pth.node.types);
if ty_substs_len > 0u {
let param_var_len = vec::len(vars);
if param_var_len == 0u {
if ty_param_count == 0u {
fcx.ccx.tcx.sess.span_fatal
(sp, "this item does not take type parameters");
} else if ty_substs_len > param_var_len {
} else if ty_substs_len > ty_param_count {
fcx.ccx.tcx.sess.span_fatal
(sp, "too many type parameter provided for this item");
} else if ty_substs_len < param_var_len {
} else if ty_substs_len < ty_param_count {
fcx.ccx.tcx.sess.span_fatal
(sp, "not enough type parameters provided for this item");
}
vec::iter2(pth.node.types, vars) {|sub, var|
let ty_subst = ast_ty_to_ty_crate(fcx.ccx, sub);
demand::simple(fcx, pth.span, var, ty_subst);
}
if ty_param_count == 0u {
fcx.ccx.tcx.sess.span_fatal(
sp, "this item does not take type parameters");
}
let substs = vec::map(pth.node.types, {|aty|
ast_ty_to_ty_crate(fcx.ccx, aty)
});
write_ty_substs(fcx.ccx.tcx, id, tpt.ty, substs);
} else if ty_param_count > 0u {
let vars = vec::init_fn(ty_param_count, {|_i| next_ty_var(fcx)});
write_ty_substs(fcx.ccx.tcx, id, tpt.ty, vars);
} else {
write_ty(fcx.ccx.tcx, id, tpt.ty);
}
{substs: some(vars), ty: tpt.ty}
}
// Type tests
@ -547,50 +549,25 @@ fn ast_ty_to_ty_crate_infer(ccx: @crate_ctxt, &&ast_ty: @ast::ty) ->
// Functions that write types into the node type table
mod write {
fn inner(ntt: node_type_table, node_id: ast::node_id,
tpot: ty_param_substs_opt_and_ty) {
smallintmap::insert(*ntt, node_id as uint, tpot);
}
// Writes a type parameter count and type pair into the node type table.
fn ty(tcx: ty::ctxt, node_id: ast::node_id,
tpot: ty_param_substs_opt_and_ty) {
assert (!ty::type_contains_vars(tcx, tpot.ty));
inner(tcx.node_types, node_id, tpot);
}
// 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 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);
if ty::type_contains_vars(fcx.ccx.tcx, tpot.ty) {
fcx.fixups += [node_id];
}
}
// Writes a type with no type parameters into the node type table.
fn ty_only(tcx: ty::ctxt, node_id: ast::node_id, typ: ty::t) {
ty(tcx, node_id, {substs: none::<[ty::t]>, ty: typ});
}
// Writes a type with no type parameters into the node type table. This
// function allows for the possibility of type variables.
fn ty_only_fixup(fcx: @fn_ctxt, node_id: ast::node_id, typ: ty::t) {
ret ty_fixup(fcx, node_id, {substs: none::<[ty::t]>, ty: typ});
}
// Writes a nil type into the node type table.
fn nil_ty(tcx: ty::ctxt, node_id: ast::node_id) {
ret ty(tcx, node_id, {substs: none::<[ty::t]>, ty: ty::mk_nil(tcx)});
}
// Writes the bottom type into the node type table.
fn bot_ty(tcx: ty::ctxt, node_id: ast::node_id) {
ret ty(tcx, node_id, {substs: none::<[ty::t]>, ty: ty::mk_bot(tcx)});
}
fn write_ty(tcx: ty::ctxt, node_id: ast::node_id, ty: ty::t) {
smallintmap::insert(*tcx.node_types, node_id as uint, ty);
}
fn write_substs(tcx: ty::ctxt, node_id: ast::node_id, +substs: [ty::t]) {
tcx.node_type_substs.insert(node_id, substs);
}
fn write_ty_substs(tcx: ty::ctxt, node_id: ast::node_id, ty: ty::t,
+substs: [ty::t]) {
let ty = if ty::type_contains_params(tcx, ty) {
ty::substitute_type_params(tcx, substs, ty)
} else { ty };
write_ty(tcx, node_id, ty);
write_substs(tcx, node_id, substs);
}
fn write_nil(tcx: ty::ctxt, node_id: ast::node_id) {
write_ty(tcx, node_id, ty::mk_nil(tcx));
}
fn write_bot(tcx: ty::ctxt, node_id: ast::node_id) {
write_ty(tcx, node_id, ty::mk_bot(tcx));
}
fn mk_ty_params(tcx: ty::ctxt, atps: [ast::ty_param])
@ -673,7 +650,7 @@ mod collect {
let tpt = {bounds: ty_param_bounds(cx.tcx, m_collect, ty_params),
ty: result_ty};
cx.tcx.tcache.insert(local_def(variant.node.id), tpt);
write::ty_only(cx.tcx, variant.node.id, result_ty);
write_ty(cx.tcx, variant.node.id, result_ty);
}
}
fn convert(cx: @ctxt, it: @ast::item) {
@ -682,7 +659,7 @@ mod collect {
ast::item_mod(_) | ast::item_native_mod(_) {}
ast::item_enum(variants, ty_params) {
let tpt = ty_of_item(cx.tcx, m_collect, it);
write::ty_only(cx.tcx, it.id, tpt.ty);
write_ty(cx.tcx, it.id, tpt.ty);
get_enum_variant_types(cx, tpt.ty, variants, ty_params);
}
ast::item_impl(tps, ifce, selfty, ms) {
@ -696,9 +673,9 @@ mod collect {
cx.tcx.tcache.insert(local_def(m.id),
{bounds: @(*i_bounds + *bounds),
ty: fty});
write::ty_only(cx.tcx, m.id, fty);
write_ty(cx.tcx, m.id, fty);
}
write::ty_only(cx.tcx, it.id, ast_ty_to_ty(cx.tcx, m_collect,
write_ty(cx.tcx, it.id, ast_ty_to_ty(cx.tcx, m_collect,
selfty));
alt ifce {
some(t) {
@ -746,15 +723,15 @@ mod collect {
inputs: [t_arg], output: ty::mk_nil(cx.tcx),
ret_style: ast::return_val, constraints: []
});
write::ty_only(cx.tcx, it.id, t_res);
write::ty_only(cx.tcx, ctor_id, t_ctor);
write_ty(cx.tcx, it.id, t_res);
write_ty(cx.tcx, ctor_id, t_ctor);
cx.tcx.tcache.insert(local_def(ctor_id),
{bounds: bounds, ty: t_ctor});
write::ty_only(cx.tcx, dtor_id, t_dtor);
write_ty(cx.tcx, dtor_id, t_dtor);
}
ast::item_iface(_, ms) {
let tpt = ty_of_item(cx.tcx, m_collect, it);
write::ty_only(cx.tcx, it.id, tpt.ty);
write_ty(cx.tcx, it.id, tpt.ty);
ty::store_iface_methods(cx.tcx, it.id, @vec::map(ms, {|m|
ty_of_ty_method(cx.tcx, m_collect, m)
}));
@ -764,7 +741,7 @@ mod collect {
// 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.tcx, m_collect, it);
write::ty_only(cx.tcx, it.id, tpt.ty);
write_ty(cx.tcx, it.id, tpt.ty);
}
}
}
@ -778,7 +755,7 @@ mod collect {
// FIXME: Native types have no annotation. Should they? --pcw
}
ast::native_item_fn(_, _) {
write::ty_only(cx.tcx, i.id, tpt.ty);
write_ty(cx.tcx, i.id, tpt.ty);
}
}
}
@ -971,28 +948,24 @@ mod writeback {
}
}
fn resolve_type_vars_for_node(wbcx: wb_ctxt, sp: span, id: ast::node_id) {
let fcx = wbcx.fcx;
let tpot = ty::node_id_to_ty_param_substs_opt_and_ty(fcx.ccx.tcx, id);
let new_ty =
alt resolve_type_vars_in_type(fcx, sp, tpot.ty) {
some(t) { t }
none { wbcx.success = false; ret }
};
let new_substs_opt;
alt tpot.substs {
none { new_substs_opt = none; }
let fcx = wbcx.fcx, tcx = fcx.ccx.tcx;
alt resolve_type_vars_in_type(fcx, sp, ty::node_id_to_type(tcx, id)) {
some(t) { write_ty(tcx, id, t); }
none { wbcx.success = false; ret }
}
alt tcx.node_type_substs.find(id) {
some(substs) {
let new_substs: [ty::t] = [];
let new_substs = [];
for subst: ty::t in substs {
alt resolve_type_vars_in_type(fcx, sp, subst) {
some(t) { new_substs += [t]; }
none { wbcx.success = false; ret; }
}
}
new_substs_opt = some(new_substs);
write_substs(tcx, id, new_substs);
}
none {}
}
write::ty(fcx.ccx.tcx, id, {substs: new_substs_opt, ty: new_ty});
}
type wb_ctxt =
@ -1037,7 +1010,7 @@ mod writeback {
ty::unify::resolve_type_var(wbcx.fcx.ccx.tcx, some(l.span),
wbcx.fcx.var_bindings, var_id);
alt fix_rslt {
fix_ok(lty) { write::ty_only(wbcx.fcx.ccx.tcx, l.node.id, lty); }
fix_ok(lty) { write_ty(wbcx.fcx.ccx.tcx, l.node.id, lty); }
fix_err(_) {
wbcx.fcx.ccx.tcx.sess.span_err(l.span,
"cannot determine a type \
@ -1185,53 +1158,48 @@ fn valid_range_bounds(from: @ast::expr, to: @ast::expr) -> bool {
// their types immediately.
fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
expected: ty::t) {
alt normalize_pat(fcx.ccx.tcx, pat).node {
let tcx = fcx.ccx.tcx;
alt normalize_pat(tcx, pat).node {
ast::pat_wild {
alt structure_of(fcx, pat.span, expected) {
ty::ty_enum(_, expected_tps) {
let path_tpt = {substs: some(expected_tps),
ty: expected};
write::ty_fixup(fcx, pat.id, path_tpt);
write_ty_substs(tcx, pat.id, expected,
expected_tps);
}
_ {
write::ty_only_fixup(fcx, pat.id, expected);
write_ty(tcx, pat.id, expected);
}
}
}
ast::pat_lit(lt) {
check_expr_with(fcx, lt, expected);
write::ty_only_fixup(fcx, pat.id, expr_ty(fcx.ccx.tcx, lt));
write_ty(tcx, pat.id, expr_ty(tcx, lt));
}
ast::pat_range(begin, end) {
check_expr_with(fcx, begin, expected);
check_expr_with(fcx, end, expected);
let b_ty = resolve_type_vars_if_possible(fcx, expr_ty(fcx.ccx.tcx,
begin));
if !ty::same_type(fcx.ccx.tcx, b_ty, resolve_type_vars_if_possible(
fcx, expr_ty(fcx.ccx.tcx, end))) {
fcx.ccx.tcx.sess.span_err(pat.span, "mismatched types in range");
} else if !ty::type_is_numeric(fcx.ccx.tcx, b_ty) {
fcx.ccx.tcx.sess.span_err(pat.span,
"non-numeric type used in range");
let b_ty = resolve_type_vars_if_possible(fcx, expr_ty(tcx, begin));
if !ty::same_type(tcx, b_ty, resolve_type_vars_if_possible(
fcx, expr_ty(tcx, end))) {
tcx.sess.span_err(pat.span, "mismatched types in range");
} else if !ty::type_is_numeric(tcx, b_ty) {
tcx.sess.span_err(pat.span, "non-numeric type used in range");
} else if !valid_range_bounds(begin, end) {
fcx.ccx.tcx.sess.span_err(begin.span,
"lower range bound must be less \
than upper");
tcx.sess.span_err(begin.span, "lower range bound must be less \
than upper");
}
write::ty_only_fixup(fcx, pat.id, b_ty);
write_ty(tcx, pat.id, b_ty);
}
ast::pat_ident(name, sub) {
let vid = lookup_local(fcx, pat.span, pat.id);
let typ = ty::mk_var(fcx.ccx.tcx, vid);
let typ = ty::mk_var(tcx, vid);
typ = demand::simple(fcx, pat.span, expected, typ);
let canon_id = map.get(path_to_ident(name));
if canon_id != pat.id {
let ct =
ty::mk_var(fcx.ccx.tcx,
lookup_local(fcx, pat.span, canon_id));
let ct = ty::mk_var(tcx, lookup_local(fcx, pat.span, canon_id));
typ = demand::simple(fcx, pat.span, ct, typ);
}
write::ty_only_fixup(fcx, pat.id, typ);
write_ty(tcx, pat.id, typ);
alt sub {
some(p) { check_pat(fcx, map, p, expected); }
_ {}
@ -1241,23 +1209,15 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
// Typecheck the path.
let v_def = lookup_def(fcx, path.span, pat.id);
let v_def_ids = ast_util::variant_def_ids(v_def);
let enum_tpt = ty::lookup_item_type(fcx.ccx.tcx, v_def_ids.tg);
let path_tpot = instantiate_path(fcx, path, enum_tpt, pat.span);
let ctor_tpt = ty::lookup_item_type(tcx, v_def_ids.tg);
instantiate_path(fcx, path, ctor_tpt, pat.span, pat.id);
// Take the enum type params out of `expected`.
alt structure_of(fcx, pat.span, expected) {
ty::ty_enum(_, expected_tps) {
// Unify with the expected enum type.
let ctor_ty =
ty::ty_param_substs_opt_and_ty_to_monotype(fcx.ccx.tcx,
path_tpot);
let path_tpt =
demand::with_substs(fcx, pat.span, expected, ctor_ty,
expected_tps);
path_tpot =
{substs: some::<[ty::t]>(path_tpt.substs), ty: path_tpt.ty};
let ctor_ty = ty::node_id_to_type(tcx, pat.id);
demand::with_substs(fcx, pat.span, expected, ctor_ty,
expected_tps);
// Get the number of arguments in this enum variant.
let arg_types =
variant_arg_types(fcx.ccx, pat.span, v_def_ids.var,
@ -1265,68 +1225,59 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
let subpats_len = vec::len::<@ast::pat>(subpats);
if vec::len::<ty::t>(arg_types) > 0u {
// N-ary variant.
let arg_len = vec::len::<ty::t>(arg_types);
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 \
corresponding variant has %u field%s",
subpats_len,
if subpats_len == 1u { "" } else { "s" },
arg_len, if arg_len == 1u { "" } else { "s" }];
fcx.ccx.tcx.sess.span_fatal(pat.span, s);
let s = #fmt["this pattern has %u field%s, but the \
corresponding variant has %u field%s",
subpats_len,
if subpats_len == 1u { "" } else { "s" },
arg_len,
if arg_len == 1u { "" } else { "s" }];
tcx.sess.span_fatal(pat.span, s);
}
// TODO: vec::iter2
let i = 0u;
for subpat: @ast::pat in subpats {
check_pat(fcx, map, subpat, arg_types[i]);
i += 1u;
vec::iter2(subpats, arg_types) {|subpat, arg_ty|
check_pat(fcx, map, subpat, arg_ty);
}
} else if subpats_len > 0u {
// TODO: note definition of enum variant
fcx.ccx.tcx.sess.span_fatal
(pat.span,
#fmt["this pattern has %u field%s, \
but the corresponding \
variant has no fields",
subpats_len,
if subpats_len == 1u {
""
} else { "s" }]);
tcx.sess.span_fatal
(pat.span, #fmt["this pattern has %u field%s, \
but the corresponding \
variant has no fields",
subpats_len,
if subpats_len == 1u { "" }
else { "s" }]);
}
write::ty_fixup(fcx, pat.id, path_tpot);
}
_ {
// FIXME: Switch expected and actual in this message? I
// can never tell.
fcx.ccx.tcx.sess.span_fatal
tcx.sess.span_fatal
(pat.span,
#fmt["mismatched types: expected `%s` but found enum",
ty_to_str(fcx.ccx.tcx, expected)]);
ty_to_str(tcx, expected)]);
}
}
write::ty_fixup(fcx, pat.id, path_tpot);
}
ast::pat_rec(fields, etc) {
let ex_fields;
alt structure_of(fcx, pat.span, expected) {
ty::ty_rec(fields) { ex_fields = fields; }
_ {
fcx.ccx.tcx.sess.span_fatal
tcx.sess.span_fatal
(pat.span,
#fmt["mismatched types: expected `%s` but found record",
ty_to_str(fcx.ccx.tcx, expected)]);
ty_to_str(tcx, expected)]);
}
}
let f_count = vec::len(fields);
let ex_f_count = vec::len(ex_fields);
if ex_f_count < f_count || !etc && ex_f_count > f_count {
fcx.ccx.tcx.sess.span_fatal
tcx.sess.span_fatal
(pat.span, #fmt["mismatched types: expected a record \
with %u fields, found one with %u \
fields",
@ -1339,47 +1290,47 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
alt vec::find(ex_fields, bind matches(f.ident, _)) {
some(field) { check_pat(fcx, map, f.pat, field.mt.ty); }
none {
fcx.ccx.tcx.sess.span_fatal(pat.span,
#fmt["mismatched types: did not \
expect a record with a field `%s`",
f.ident]);
tcx.sess.span_fatal(pat.span,
#fmt["mismatched types: did not \
expect a record with a field `%s`",
f.ident]);
}
}
}
write::ty_only_fixup(fcx, pat.id, expected);
write_ty(tcx, pat.id, expected);
}
ast::pat_tup(elts) {
let ex_elts;
alt structure_of(fcx, pat.span, expected) {
ty::ty_tup(elts) { ex_elts = elts; }
_ {
fcx.ccx.tcx.sess.span_fatal
tcx.sess.span_fatal
(pat.span,
#fmt["mismatched types: expected `%s`, found tuple",
ty_to_str(fcx.ccx.tcx, expected)]);
ty_to_str(tcx, expected)]);
}
}
let e_count = vec::len(elts);
if e_count != vec::len(ex_elts) {
fcx.ccx.tcx.sess.span_fatal
tcx.sess.span_fatal
(pat.span, #fmt["mismatched types: expected a tuple \
with %u fields, found one with %u \
fields", vec::len(ex_elts), e_count]);
}
let i = 0u;
for elt in elts { check_pat(fcx, map, elt, ex_elts[i]); i += 1u; }
write::ty_only_fixup(fcx, pat.id, expected);
write_ty(tcx, pat.id, expected);
}
ast::pat_box(inner) {
alt structure_of(fcx, pat.span, expected) {
ty::ty_box(e_inner) {
check_pat(fcx, map, inner, e_inner.ty);
write::ty_only_fixup(fcx, pat.id, expected);
write_ty(tcx, pat.id, expected);
}
_ {
fcx.ccx.tcx.sess.span_fatal(pat.span,
tcx.sess.span_fatal(pat.span,
"mismatched types: expected `" +
ty_to_str(fcx.ccx.tcx, expected) +
ty_to_str(tcx, expected) +
"` found box");
}
}
@ -1388,12 +1339,12 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
alt structure_of(fcx, pat.span, expected) {
ty::ty_uniq(e_inner) {
check_pat(fcx, map, inner, e_inner.ty);
write::ty_only_fixup(fcx, pat.id, expected);
write_ty(tcx, pat.id, expected);
}
_ {
fcx.ccx.tcx.sess.span_fatal(pat.span,
tcx.sess.span_fatal(pat.span,
"mismatched types: expected `" +
ty_to_str(fcx.ccx.tcx, expected) +
ty_to_str(tcx, expected) +
"` found uniq");
}
}
@ -1581,7 +1532,6 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
unify: unifier,
expected: ty::t) {
let tcx = fcx.ccx.tcx;
let fty = ty::mk_fn(tcx, ty_of_fn_decl(tcx, m_check_tyvar(fcx),
proto, decl));
@ -1589,7 +1539,7 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
expr_to_str(expr),
ty_to_str(tcx, fty));
write::ty_only_fixup(fcx, expr.id, fty);
write_ty(tcx, expr.id, fty);
// Unify the type of the function with the expected type before we
// typecheck the body so that we have more information about the
@ -1672,7 +1622,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
rhs: @ast::expr, id: ast::node_id) -> bool {
let t = next_ty_var(fcx);
let bot = check_expr_with(fcx, lhs, t) | check_expr_with(fcx, rhs, t);
write::ty_only_fixup(fcx, id, ty::mk_nil(fcx.ccx.tcx));
write_ty(fcx.ccx.tcx, id, ty::mk_nil(fcx.ccx.tcx));
ret bot;
}
@ -1708,7 +1658,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
}
_ { fcx.ccx.tcx.sess.span_fatal(sp, "calling non-function"); }
};
write::ty_only_fixup(fcx, id, rt_1);
write_ty(fcx.ccx.tcx, id, rt_1);
ret bot;
}
@ -1725,7 +1675,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
demand::simple(fcx, local.span,
ty::node_id_to_type(fcx.ccx.tcx, local.node.id),
element_ty);
write::nil_ty(fcx.ccx.tcx, node_id);
write_nil(fcx.ccx.tcx, node_id);
ret bot;
}
@ -1754,7 +1704,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
(ty::mk_nil(fcx.ccx.tcx), false)
}
};
write::ty_only_fixup(fcx, id, if_t);
write_ty(fcx.ccx.tcx, id, if_t);
ret if_bot;
}
@ -1773,8 +1723,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
alt lookup_method(fcx, isc, opname, self_t, op_ex.span) {
some({method_ty, n_tps: 0u, substs, origin}) {
let callee_id = ast_util::op_expr_callee_id(op_ex);
write::ty_fixup(fcx, callee_id, {substs: some(substs),
ty: method_ty});
write_ty_substs(fcx.ccx.tcx, callee_id, method_ty, substs);
check_call_or_bind(fcx, op_ex.span, method_ty, args);
fcx.ccx.method_map.insert(op_ex.id, origin);
some(ty::ty_fn_ret(fcx.ccx.tcx, method_ty))
@ -1828,7 +1777,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
alt expr.node {
ast::expr_lit(lit) {
let typ = check_lit(fcx.ccx, lit);
write::ty_only_fixup(fcx, id, typ);
write_ty(tcx, id, typ);
}
ast::expr_binary(binop, lhs, rhs) {
let lhs_t = next_ty_var(fcx);
@ -1838,7 +1787,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
if !ast_util::lazy_binop(binop) { bot |= rhs_bot; }
let result = check_binop(fcx, expr, lhs_t, binop, rhs);
write::ty_only_fixup(fcx, id, result);
write_ty(tcx, id, result);
}
ast::expr_assign_op(op, lhs, rhs) {
require_impure(tcx.sess, fcx.purity, expr.span);
@ -1899,15 +1848,14 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
}
}
}
write::ty_only_fixup(fcx, id, oper_t);
write_ty(tcx, id, oper_t);
}
ast::expr_path(pth) {
let defn = lookup_def(fcx, pth.span, id);
let tpt = ty_param_bounds_and_ty_for_def(fcx, expr.span, defn);
if ty::def_has_ty_params(defn) {
let path_tpot = instantiate_path(fcx, pth, tpt, expr.span);
write::ty_fixup(fcx, id, path_tpot);
instantiate_path(fcx, pth, tpt, expr.span, expr.id);
} else {
// The definition doesn't take type parameters. If the programmer
// supplied some, that's an error
@ -1916,7 +1864,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
"this kind of value does not \
take type parameters");
}
write::ty_only_fixup(fcx, id, tpt.ty);
write_ty(tcx, id, tpt.ty);
}
}
ast::expr_mac(_) { tcx.sess.bug("unexpanded macro"); }
@ -1926,10 +1874,10 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
none {/* do nothing */ }
some(e) { check_expr_with(fcx, e, ty::mk_str(tcx)); }
}
write::bot_ty(tcx, id);
write_bot(tcx, id);
}
ast::expr_break { write::bot_ty(tcx, id); bot = true; }
ast::expr_cont { write::bot_ty(tcx, id); bot = true; }
ast::expr_break { write_bot(tcx, id); bot = true; }
ast::expr_cont { write_bot(tcx, id); bot = true; }
ast::expr_ret(expr_opt) {
bot = true;
alt expr_opt {
@ -1942,23 +1890,23 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
}
some(e) { check_expr_with(fcx, e, fcx.ret_ty); }
}
write::bot_ty(tcx, id);
write_bot(tcx, id);
}
ast::expr_be(e) {
// FIXME: prove instead of assert
assert (ast_util::is_call_expr(e));
check_expr_with(fcx, e, fcx.ret_ty);
bot = true;
write::nil_ty(tcx, id);
write_nil(tcx, id);
}
ast::expr_log(_, lv, e) {
bot = check_expr_with(fcx, lv, ty::mk_mach_uint(tcx, ast::ty_u32));
bot |= check_expr(fcx, e);
write::nil_ty(tcx, id);
write_nil(tcx, id);
}
ast::expr_check(_, e) {
bot = check_pred_expr(fcx, e);
write::nil_ty(tcx, id);
write_nil(tcx, id);
}
ast::expr_if_check(cond, thn, elsopt) {
bot =
@ -1970,14 +1918,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
}
ast::expr_assert(e) {
bot = check_expr_with(fcx, e, ty::mk_bool(tcx));
write::nil_ty(tcx, id);
write_nil(tcx, id);
}
ast::expr_copy(a) {
bot = check_expr_with_unifier(fcx, a, unify, expected);
let tpot =
ty::node_id_to_ty_param_substs_opt_and_ty(tcx, a.id);
write::ty_fixup(fcx, id, tpot);
write_ty(tcx, id, ty::node_id_to_type(tcx, a.id));
}
ast::expr_move(lhs, rhs) {
require_impure(tcx.sess, fcx.purity, expr.span);
@ -2014,12 +1959,12 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
ast::expr_while(cond, body) {
bot = check_expr_with(fcx, cond, ty::mk_bool(tcx));
check_block_no_value(fcx, body);
write::ty_only_fixup(fcx, id, ty::mk_nil(tcx));
write_ty(tcx, id, ty::mk_nil(tcx));
}
ast::expr_do_while(body, cond) {
bot = check_expr_with(fcx, cond, ty::mk_bool(tcx)) |
check_block_no_value(fcx, body);
write::ty_only_fixup(fcx, id, block_ty(tcx, body));
write_ty(tcx, id, block_ty(tcx, body));
}
ast::expr_alt(expr, arms) {
bot = check_expr(fcx, expr);
@ -2047,7 +1992,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
}
bot |= !arm_non_bot;
if !arm_non_bot { result_ty = ty::mk_bot(tcx); }
write::ty_only_fixup(fcx, id, result_ty);
write_ty(tcx, id, result_ty);
}
ast::expr_fn(proto, decl, body, captures) {
check_expr_fn_with_unifier(fcx, expr, proto, decl, body,
@ -2069,7 +2014,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
ty_to_str(tcx, expected));
check_expr_fn_with_unifier(fcx, expr, proto, decl, body,
unify, expected);
write::ty_only_fixup(fcx, id, expected);
write_ty(tcx, id, expected);
}
ast::expr_block(b) {
// If this is an unchecked block, turn off purity-checking
@ -2079,7 +2024,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
some(expr) { expr_ty(tcx, expr) }
none { ty::mk_nil(tcx) }
};
write::ty_only_fixup(fcx, id, typ);
write_ty(tcx, id, typ);
}
ast::expr_bind(f, args) {
// Call the generic checker.
@ -2126,7 +2071,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
let ft = ty::mk_fn(tcx, {proto: lower_bound_proto(proto),
inputs: out_args, output: rt,
ret_style: cf, constraints: constrs});
write::ty_only_fixup(fcx, id, ft);
write_ty(tcx, id, ft);
}
ast::expr_call(f, args, _) {
bot = check_call_full(fcx, expr.span, f, args, expr.id);
@ -2162,13 +2107,13 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
}
}
}
write::ty_only_fixup(fcx, id, t_1);
write_ty(tcx, id, t_1);
}
ast::expr_vec(args, mut) {
let t: ty::t = next_ty_var(fcx);
for e: @ast::expr in args { bot |= check_expr_with(fcx, e, t); }
let typ = ty::mk_vec(tcx, {ty: t, mut: mut});
write::ty_only_fixup(fcx, id, typ);
write_ty(tcx, id, typ);
}
ast::expr_tup(elts) {
let elt_ts = [];
@ -2179,7 +2124,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
elt_ts += [ety];
}
let typ = ty::mk_tup(tcx, elt_ts);
write::ty_only_fixup(fcx, id, typ);
write_ty(tcx, id, typ);
}
ast::expr_rec(fields, base) {
alt base { none {/* no-op */ } some(b_0) { check_expr(fcx, b_0); } }
@ -2198,7 +2143,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
none {
fn get_node(f: spanned<field>) -> field { f.node }
let typ = ty::mk_rec(tcx, vec::map(fields_t, get_node));
write::ty_only_fixup(fcx, id, typ);
write_ty(tcx, id, typ);
}
some(bexpr) {
bot |= check_expr(fcx, bexpr);
@ -2211,7 +2156,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
"record update has non-record base");
}
}
write::ty_only_fixup(fcx, id, bexpr_t);
write_ty(tcx, id, bexpr_t);
for f: spanned<ty::field> in fields_t {
let found = false;
for bf: ty::field in base_fields {
@ -2244,7 +2189,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
"can't provide type parameters \
to a field access");
}
write::ty_only_fixup(fcx, id, fields[ix].mt.ty);
write_ty(tcx, id, fields[ix].mt.ty);
handled = true;
}
_ {}
@ -2275,13 +2220,13 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
i += 1u;
}
}
write::ty_fixup(fcx, id, {substs: some(substs), ty: fty});
write_ty_substs(fcx.ccx.tcx, id, fty, substs);
} else if n_tys > 0u {
tcx.sess.span_fatal(expr.span,
"this method does not take type \
parameters");
} else {
write::ty_only_fixup(fcx, id, fty);
write_ty(tcx, id, fty);
}
fcx.ccx.method_map.insert(id, origin);
}
@ -2292,7 +2237,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
field, ty_to_str(tcx, t_err)];
tcx.sess.span_err(expr.span, msg);
// NB: Adding a bogus type to allow typechecking to continue
write::ty_only_fixup(fcx, id, ty::mk_nil(tcx));
write_ty(tcx, id, ty::mk_nil(tcx));
}
}
}
@ -2313,19 +2258,19 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
alt structure_of(fcx, expr.span, base_t) {
ty::ty_vec(mt) {
require_integral(fcx, idx.span, idx_t);
write::ty_only_fixup(fcx, id, mt.ty);
write_ty(tcx, id, mt.ty);
}
ty::ty_str {
require_integral(fcx, idx.span, idx_t);
let typ = ty::mk_mach_uint(tcx, ast::ty_u8);
write::ty_only_fixup(fcx, id, typ);
write_ty(tcx, id, typ);
}
_ {
let resolved = structurally_resolved_type(fcx, expr.span,
raw_base_t);
alt lookup_op_method(fcx, expr, resolved, "[]",
[some(idx)]) {
some(ret_ty) { write::ty_only_fixup(fcx, id, ret_ty); }
some(ret_ty) { write_ty(tcx, id, ret_ty); }
_ {
tcx.sess.span_fatal(
expr.span, "cannot index a value of type `" +
@ -2337,7 +2282,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
}
_ { tcx.sess.unimpl("expr type in typeck::check_expr"); }
}
if bot { write::ty_only_fixup(fcx, expr.id, ty::mk_bot(tcx)); }
if bot { write_ty(tcx, expr.id, ty::mk_bot(tcx)); }
unify(fcx, expr.span, expected, expr_ty(tcx, expr));
ret bot;
@ -2375,7 +2320,7 @@ fn check_decl_local(fcx: @fn_ctxt, local: @ast::local) -> bool {
alt fcx.locals.find(local.node.id) {
some(i) {
let t = ty::mk_var(fcx.ccx.tcx, i);
write::ty_only_fixup(fcx, local.node.id, t);
write_ty(fcx.ccx.tcx, local.node.id, t);
alt local.node.init {
some(init) {
bot = check_decl_initializer(fcx, local.node.id, init);
@ -2411,14 +2356,14 @@ fn check_stmt(fcx: @fn_ctxt, stmt: @ast::stmt) -> bool {
bot = check_expr(fcx, expr);
}
}
write::nil_ty(fcx.ccx.tcx, node_id);
write_nil(fcx.ccx.tcx, node_id);
ret bot;
}
fn check_block_no_value(fcx: @fn_ctxt, blk: ast::blk) -> bool {
let bot = check_block(fcx, blk);
if !bot {
let blkty = ty::node_id_to_monotype(fcx.ccx.tcx, blk.node.id);
let blkty = ty::node_id_to_type(fcx.ccx.tcx, blk.node.id);
let nilty = ty::mk_nil(fcx.ccx.tcx);
demand::simple(fcx, blk.span, nilty, blkty);
}
@ -2448,18 +2393,18 @@ fn check_block(fcx0: @fn_ctxt, blk: ast::blk) -> bool {
bot |= check_stmt(fcx, s);
}
alt blk.node.expr {
none { write::nil_ty(fcx.ccx.tcx, blk.node.id); }
none { write_nil(fcx.ccx.tcx, blk.node.id); }
some(e) {
if bot && !warned {
fcx.ccx.tcx.sess.span_warn(e.span, "unreachable expression");
}
bot |= check_expr(fcx, e);
let ety = expr_ty(fcx.ccx.tcx, e);
write::ty_only_fixup(fcx, blk.node.id, ety);
write_ty(fcx.ccx.tcx, blk.node.id, ety);
}
}
if bot {
write::ty_only_fixup(fcx, blk.node.id, ty::mk_bot(fcx.ccx.tcx));
write_ty(fcx.ccx.tcx, blk.node.id, ty::mk_bot(fcx.ccx.tcx));
}
ret bot;
}
@ -2697,7 +2642,7 @@ fn check_fn(ccx: @crate_ctxt,
let args = ty::ty_fn_args(ccx.tcx, ty::node_id_to_type(ccx.tcx, id));
let i = 0u;
for arg: ty::arg in args {
write::ty_only_fixup(fcx, decl.inputs[i].id, arg.ty);
write_ty(ccx.tcx, decl.inputs[i].id, arg.ty);
i += 1u;
}
@ -2748,7 +2693,7 @@ fn arg_is_argv_ty(tcx: ty::ctxt, a: ty::arg) -> bool {
}
fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id) {
let main_t = ty::node_id_to_monotype(tcx, main_id);
let main_t = ty::node_id_to_type(tcx, main_id);
alt ty::struct(tcx, main_t) {
ty::ty_fn({proto: ast::proto_bare, inputs, output,
ret_style: ast::return_val, constraints}) {
@ -2919,9 +2864,7 @@ mod dict {
let cx = fcx.ccx;
alt ex.node {
ast::expr_path(_) {
let substs = ty::node_id_to_ty_param_substs_opt_and_ty(
cx.tcx, ex.id);
alt substs.substs {
alt cx.tcx.node_type_substs.find(ex.id) {
some(ts) {
let did = ast_util::def_id_of_def(cx.tcx.def_map.get(ex.id));
let item_ty = ty::lookup_item_type(cx.tcx, did);