typeck.rs 93.9 KB
Newer Older
1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
import front::ast;
import front::ast::ann;
import front::ast::mutability;
import front::creader;
import driver::session;
import util::common;
import util::common::span;
import util::common::new_def_hash;
import util::common::log_expr_err;
import middle::ty;
import middle::ty::ann_to_type;
import middle::ty::arg;
import middle::ty::bind_params_in_type;
import middle::ty::block_ty;
import middle::ty::expr_ty;
import middle::ty::field;
import middle::ty::method;
import middle::ty::mo_val;
import middle::ty::mo_alias;
21
import middle::ty::node_type_table;
22 23
import middle::ty::pat_ty;
import middle::ty::path_to_str;
24
import middle::ty::ty_param_substs_opt_and_ty;
25
import pretty::ppaux::ty_to_str;
26 27
import middle::ty::ty_param_count_and_ty;
import middle::ty::ty_nil;
28 29
import middle::ty::unify::ures_ok;
import middle::ty::unify::ures_err;
30 31 32
import middle::ty::unify::fixup_result;
import middle::ty::unify::fix_ok;
import middle::ty::unify::fix_err;
33
import std::int;
34
import std::str;
35
import std::ufind;
36 37
import std::uint;
import std::vec;
38 39 40 41 42 43
import std::map;
import std::map::hashmap;
import std::option;
import std::option::none;
import std::option::some;
import std::option::from_maybe;
44
import middle::tstate::ann::ts_ann;
45 46

type ty_table = hashmap[ast::def_id, ty::t];
47

48
type fn_purity_table = hashmap[ast::def_id, ast::purity];
49

50 51
type obj_info = rec(vec[ast::obj_field] obj_fields, ast::def_id this_obj);

52 53 54 55 56 57 58 59 60 61 62 63 64 65
type crate_ctxt =
    rec(mutable vec[obj_info] obj_infos,
        @fn_purity_table fn_purity_table,
        ty::ctxt tcx);

type fn_ctxt =
    rec(ty::t ret_ty,
        ast::purity purity,
        @ty::unify::var_bindings var_bindings,
        hashmap[ast::def_id, int] locals,
        hashmap[ast::def_id, ast::ident] local_names,
        mutable int next_var_id,
        mutable vec[uint] fixups,
        @crate_ctxt ccx);
66

67

68
// Used for ast_ty_to_ty() below.
69
type ty_getter = fn(&ast::def_id) -> ty::ty_param_count_and_ty ;
70

71

72
// Returns the type parameter count and the type for the given definition.
73 74
fn ty_param_count_and_ty_for_def(&@fn_ctxt fcx, &span sp, &ast::def defn) ->
   ty_param_count_and_ty {
75
    alt (defn) {
76
        case (ast::def_arg(?id)) {
77 78 79
            assert (fcx.locals.contains_key(id));
            auto typ = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(id));
            ret tup(0u, typ);
80
        }
81
        case (ast::def_local(?id)) {
82 83 84
            assert (fcx.locals.contains_key(id));
            auto typ = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(id));
            ret tup(0u, typ);
85
        }
86
        case (ast::def_obj_field(?id)) {
87 88 89
            assert (fcx.locals.contains_key(id));
            auto typ = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(id));
            ret tup(0u, typ);
90
        }
91
        case (ast::def_fn(?id)) { ret ty::lookup_item_type(fcx.ccx.tcx, id); }
92
        case (ast::def_native_fn(?id)) {
93
            ret ty::lookup_item_type(fcx.ccx.tcx, id);
94
        }
95
        case (ast::def_const(?id)) {
96
            ret ty::lookup_item_type(fcx.ccx.tcx, id);
97
        }
98
        case (ast::def_variant(_, ?vid)) {
99
            ret ty::lookup_item_type(fcx.ccx.tcx, vid);
100
        }
101
        case (ast::def_binding(?id)) {
102 103 104
            assert (fcx.locals.contains_key(id));
            auto typ = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(id));
            ret tup(0u, typ);
105
        }
106
        case (ast::def_obj(?id)) {
107
            ret ty::lookup_item_type(fcx.ccx.tcx, id);
108
        }
109
        case (ast::def_mod(_)) {
110
            // Hopefully part of a path.
111
            // TODO: return a type that's more poisonous, perhaps?
112

113
            ret tup(0u, ty::mk_nil(fcx.ccx.tcx));
114
        }
115
        case (ast::def_ty(_)) {
116
            fcx.ccx.tcx.sess.span_err(sp, "expected value but found type");
117
        }
118 119
        case (_) {
            // FIXME: handle other names.
120

121
            fcx.ccx.tcx.sess.unimpl("definition variant");
122 123
        }
    }
124 125
}

126

127
// Instantiates the given path, which must refer to an item with the given
128
// number of type parameters and type.
129
fn instantiate_path(&@fn_ctxt fcx, &ast::path pth, &ty_param_count_and_ty tpt,
130
                    &span sp) -> ty_param_substs_opt_and_ty {
131
    auto ty_param_count = tpt._0;
132 133 134
    auto bind_result =
        bind_params_in_type(fcx.ccx.tcx, bind next_ty_var_id(fcx), tpt._1,
                            ty_param_count);
135 136
    auto ty_param_vars = bind_result._0;
    auto t = bind_result._1;
137
    auto ty_substs_opt;
138
    auto ty_substs_len = vec::len[@ast::ty](pth.node.types);
139
    if (ty_substs_len > 0u) {
140
        let vec[ty::t] ty_substs = [];
141 142
        auto i = 0u;
        while (i < ty_substs_len) {
143 144
            // TODO: Report an error if the number of type params in the item
            // and the supplied number of type params don't match.
145

146
            auto ty_var = ty::mk_var(fcx.ccx.tcx, ty_param_vars.(i));
147
            auto ty_subst = ast_ty_to_ty_crate(fcx.ccx, pth.node.types.(i));
148 149
            auto res_ty = demand::simple(fcx, pth.span, ty_var, ty_subst);
            ty_substs += [res_ty];
150 151
            i += 1u;
        }
152
        ty_substs_opt = some[vec[ty::t]](ty_substs);
153
        if (ty_param_count == 0u) {
154 155 156
            fcx.ccx.tcx.sess.span_err(sp,
                                      "this item does not take type " +
                                          "parameters");
157
            fail;
158 159
        }
    } else {
160
        // We will acquire the type parameters through unification.
161

162
        let vec[ty::t] ty_substs = [];
163 164
        auto i = 0u;
        while (i < ty_param_count) {
165
            ty_substs += [ty::mk_var(fcx.ccx.tcx, ty_param_vars.(i))];
166
            i += 1u;
167
        }
168
        ty_substs_opt = some[vec[ty::t]](ty_substs);
169
    }
170
    ret tup(ty_substs_opt, tpt._1);
171 172
}

173
fn ast_mode_to_mode(ast::mode mode) -> ty::mode {
174 175
    auto ty_mode;
    alt (mode) {
176
        case (ast::val) { ty_mode = mo_val; }
177
        case (ast::alias(?mut)) { ty_mode = mo_alias(mut); }
178 179 180 181
    }
    ret ty_mode;
}

182 183 184

// Type tests
fn structurally_resolved_type(&@fn_ctxt fcx, &span sp, ty::t typ) -> ty::t {
185 186
    auto r =
        ty::unify::resolve_type_structure(fcx.ccx.tcx, fcx.var_bindings, typ);
187
    alt (r) {
188
        case (fix_ok(?typ_s)) { ret typ_s; }
189
        case (fix_err(_)) {
190 191 192
            fcx.ccx.tcx.sess.span_err(sp,
                                      "the type of this value must be " +
                                          "known in this context");
193 194 195 196
        }
    }
}

197

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
// Returns the one-level-deep structure of the given type.
fn structure_of(&@fn_ctxt fcx, &span sp, ty::t typ) -> ty::sty {
    ret ty::struct(fcx.ccx.tcx, structurally_resolved_type(fcx, sp, typ));
}

fn type_is_integral(&@fn_ctxt fcx, &span sp, ty::t typ) -> bool {
    auto typ_s = structurally_resolved_type(fcx, sp, typ);
    ret ty::type_is_integral(fcx.ccx.tcx, typ_s);
}

fn type_is_scalar(&@fn_ctxt fcx, &span sp, ty::t typ) -> bool {
    auto typ_s = structurally_resolved_type(fcx, sp, typ);
    ret ty::type_is_scalar(fcx.ccx.tcx, typ_s);
}


214 215
// Parses the programmer's textual representation of a type into our internal
// notion of a type. `getter` is a function that returns the type
216 217
// corresponding to a definition ID:
fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
218
    alt (tcx.ast_ty_to_ty_cache.find(ast_ty)) {
219
        case (some[option::t[ty::t]](some[ty::t](?ty))) { ret ty; }
220
        case (some[option::t[ty::t]](none)) {
221 222 223 224
            tcx.sess.span_err(ast_ty.span,
                              "illegal recursive type " +
                              "(insert a tag in the cycle, " +
                              "if this is desired)");
225
        }
226 227 228
        case (none[option::t[ty::t]]) { }
    } /* go on */

229
    tcx.ast_ty_to_ty_cache.insert(ast_ty, none[ty::t]);
230 231
    fn ast_arg_to_arg(&ty::ctxt tcx, &ty_getter getter, &ast::ty_arg arg) ->
       rec(ty::mode mode, ty::t ty) {
232 233
        auto ty_mode = ast_mode_to_mode(arg.node.mode);
        ret rec(mode=ty_mode, ty=ast_ty_to_ty(tcx, getter, arg.node.ty));
234
    }
235
    fn ast_mt_to_mt(&ty::ctxt tcx, &ty_getter getter, &ast::mt mt) -> ty::mt {
236
        ret rec(ty=ast_ty_to_ty(tcx, getter, mt.ty), mut=mt.mut);
237
    }
238 239
    fn instantiate(&ty::ctxt tcx, &span sp, &ty_getter getter,
                   &ast::def_id id, &vec[@ast::ty] args) -> ty::t {
240 241
        // TODO: maybe record cname chains so we can do
        // "foo = int" like OCaml?
242

243 244
        auto params_opt_and_ty = getter(id);
        if (params_opt_and_ty._0 == 0u) { ret params_opt_and_ty._1; }
245 246
        // The typedef is type-parametric. Do the type substitution.
        //
247

248
        let vec[ty::t] param_bindings = [];
249
        for (@ast::ty ast_ty in args) {
250
            param_bindings += [ast_ty_to_ty(tcx, getter, ast_ty)];
251
        }
252
        if (vec::len(param_bindings) !=
253 254 255 256
                ty::count_ty_params(tcx, params_opt_and_ty._1)) {
            tcx.sess.span_err(sp,
                              "Wrong number of type arguments for a" +
                                  " polymorphic tag");
257
        }
258 259
        auto typ =
            ty::substitute_type_params(tcx, param_bindings,
260 261
                                       params_opt_and_ty._1);
        ret typ;
262
    }
263
    auto mut = ast::imm;
264
    auto typ;
265 266
    auto cname = none[str];
    alt (ast_ty.node) {
267 268 269 270 271 272
        case (ast::ty_nil) { typ = ty::mk_nil(tcx); }
        case (ast::ty_bot) { typ = ty::mk_bot(tcx); }
        case (ast::ty_bool) { typ = ty::mk_bool(tcx); }
        case (ast::ty_int) { typ = ty::mk_int(tcx); }
        case (ast::ty_uint) { typ = ty::mk_uint(tcx); }
        case (ast::ty_float) { typ = ty::mk_float(tcx); }
273
        case (ast::ty_machine(?tm)) { typ = ty::mk_mach(tcx, tm); }
274 275 276
        case (ast::ty_char) { typ = ty::mk_char(tcx); }
        case (ast::ty_str) { typ = ty::mk_str(tcx); }
        case (ast::ty_istr) { typ = ty::mk_istr(tcx); }
277 278
        case (ast::ty_box(?mt)) {
            typ = ty::mk_box(tcx, ast_mt_to_mt(tcx, getter, mt));
279
        }
280 281
        case (ast::ty_vec(?mt)) {
            typ = ty::mk_vec(tcx, ast_mt_to_mt(tcx, getter, mt));
282
        }
283 284 285
        case (ast::ty_ivec(?mt)) {
            typ = ty::mk_ivec(tcx, ast_mt_to_mt(tcx, getter, mt));
        }
286 287 288
        case (ast::ty_ptr(?mt)) {
            typ = ty::mk_ptr(tcx, ast_mt_to_mt(tcx, getter, mt));
        }
289
        case (ast::ty_task) { typ = ty::mk_task(tcx); }
290 291
        case (ast::ty_port(?t)) {
            typ = ty::mk_port(tcx, ast_ty_to_ty(tcx, getter, t));
292
        }
293 294
        case (ast::ty_chan(?t)) {
            typ = ty::mk_chan(tcx, ast_ty_to_ty(tcx, getter, t));
295
        }
296
        case (ast::ty_tup(?fields)) {
297
            let vec[ty::mt] flds = [];
298
            for (ast::mt field in fields) {
299
                vec::push[ty::mt](flds, ast_mt_to_mt(tcx, getter, field));
300
            }
301
            typ = ty::mk_tup(tcx, flds);
302
        }
303
        case (ast::ty_rec(?fields)) {
304
            let vec[field] flds = [];
305
            for (ast::ty_field f in fields) {
306 307
                auto tm = ast_mt_to_mt(tcx, getter, f.node.mt);
                vec::push[field](flds, rec(ident=f.node.ident, mt=tm));
308
            }
309
            typ = ty::mk_rec(tcx, flds);
310
        }
311
        case (ast::ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
312
            auto f = bind ast_arg_to_arg(tcx, getter, _);
313
            auto i = vec::map[ast::ty_arg, arg](f, inputs);
314
            auto out_ty = ast_ty_to_ty(tcx, getter, output);
315
            typ = ty::mk_fn(tcx, proto, i, out_ty, cf, constrs);
316
        }
317
        case (ast::ty_path(?path, ?ann)) {
P
Patrick Walton 已提交
318
            alt (tcx.def_map.get(ann.id)) {
319
                case (ast::def_ty(?id)) {
320 321 322
                    typ =
                        instantiate(tcx, ast_ty.span, getter, id,
                                    path.node.types);
323
                }
324 325
                case (ast::def_native_ty(?id)) { typ = getter(id)._1; }
                case (ast::def_obj(?id)) {
326 327 328
                    typ =
                        instantiate(tcx, ast_ty.span, getter, id,
                                    path.node.types);
329
                }
330
                case (ast::def_ty_arg(?id)) { typ = ty::mk_param(tcx, id); }
331
                case (_) {
332
                    tcx.sess.span_err(ast_ty.span,
333
                                      "found type name used as a variable");
334
                }
335 336 337
            }
            cname = some(path_to_str(path));
        }
338
        case (ast::ty_obj(?meths)) {
339
            let vec[ty::method] tmeths = [];
340
            auto f = bind ast_arg_to_arg(tcx, getter, _);
341
            for (ast::ty_method m in meths) {
342 343
                auto ins = vec::map[ast::ty_arg, arg](f, m.node.inputs);
                auto out = ast_ty_to_ty(tcx, getter, m.node.output);
344
                let ty::method new_m =
345 346 347 348 349 350
                    rec(proto=m.node.proto,
                        ident=m.node.ident,
                        inputs=ins,
                        output=out,
                        cf=m.node.cf,
                        constrs=m.node.constrs);
351
                vec::push[ty::method](tmeths, new_m);
352
            }
353
            typ = ty::mk_obj(tcx, ty::sort_methods(tmeths));
354
        }
355
    }
356
    alt (cname) {
357 358
        case (none) {/* no-op */ }
        case (some(?cname_str)) { typ = ty::rename(tcx, typ, cname_str); }
359
    }
360
    tcx.ast_ty_to_ty_cache.insert(ast_ty, some(typ));
361
    ret typ;
362 363
}

364

365
// A convenience function to use a crate_ctxt to resolve names for
366
// ast_ty_to_ty.
367 368
fn ast_ty_to_ty_crate(@crate_ctxt ccx, &@ast::ty ast_ty) -> ty::t {
    fn getter(@crate_ctxt ccx, &ast::def_id id) -> ty::ty_param_count_and_ty {
369
        ret ty::lookup_item_type(ccx.tcx, id);
370
    }
371
    auto f = bind getter(ccx, _);
372
    ret ast_ty_to_ty(ccx.tcx, f, ast_ty);
373 374
}

375

376 377 378 379
// Functions that write types into the node type table.
mod write {
    fn inner(&node_type_table ntt, uint node_id,
             &ty_param_substs_opt_and_ty tpot) {
M
Marijn Haverbeke 已提交
380
        auto ntt_ = *ntt;
381 382 383 384
        vec::grow_set(ntt_,
                      node_id,
                      none[ty_param_substs_opt_and_ty],
                      some[ty_param_substs_opt_and_ty](tpot));
M
Marijn Haverbeke 已提交
385
        *ntt = ntt_;
386
    }
387

388
    // Writes a type parameter count and type pair into the node type table.
389
    fn ty(&ty::ctxt tcx, uint node_id, &ty_param_substs_opt_and_ty tpot) {
390
        assert (!ty::type_contains_vars(tcx, tpot._1));
391
        ret inner(tcx.node_types, node_id, tpot);
392 393 394 395 396
    }

    // 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.
397
    fn ty_fixup(@fn_ctxt fcx, uint node_id,
398
                &ty_param_substs_opt_and_ty tpot) {
399 400 401
        inner(fcx.ccx.tcx.node_types, node_id, tpot);
        if (ty::type_contains_vars(fcx.ccx.tcx, tpot._1)) {
            fcx.fixups += [node_id];
402 403
        }
    }
404

405
    // Writes a type with no type parameters into the node type table.
406
    fn ty_only(&ty::ctxt tcx, uint node_id, ty::t typ) {
407
        ret ty(tcx, node_id, tup(none[vec[ty::t]], typ));
408 409 410 411
    }

    // Writes a type with no type parameters into the node type table. This
    // function allows for the possibility of type variables.
412
    fn ty_only_fixup(@fn_ctxt fcx, uint node_id, ty::t typ) {
413
        ret ty_fixup(fcx, node_id, tup(none[vec[ty::t]], typ));
414 415 416
    }

    // Writes a nil type into the node type table.
417
    fn nil_ty(&ty::ctxt tcx, uint node_id) {
418
        ret ty(tcx, node_id, tup(none[vec[ty::t]], ty::mk_nil(tcx)));
419 420 421
    }

    // Writes the bottom type into the node type table.
422
    fn bot_ty(&ty::ctxt tcx, uint node_id) {
423
        ret ty(tcx, node_id, tup(none[vec[ty::t]], ty::mk_bot(tcx)));
424
    }
425 426
}

427

428 429
// Item collection - a pair of bootstrap passes:
//
430
// (1) Collect the IDs of all type items (typedefs) and store them in a table.
431
//
432 433 434
// (2) Translate the AST fragments that describe types to determine a type for
//     each item. When we encounter a named type, we consult the table built
//     in pass 1 to find its item, and recursively translate it.
435 436 437
//
// We then annotate the AST with the resulting types and return the annotated
// AST, along with a table mapping item IDs to their types.
438 439 440 441
//
// 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.
442
mod collect {
443
    type ctxt = rec(ty::ctxt tcx);
444

445 446 447 448 449 450
    fn ty_of_fn_decl(&@ctxt cx, &fn(&@ast::ty) -> ty::t  convert,
                     &fn(&ast::arg) -> arg  ty_of_arg, &ast::fn_decl decl,
                     ast::proto proto, &vec[ast::ty_param] ty_params,
                     &option::t[ast::def_id] def_id) ->
       ty::ty_param_count_and_ty {
        auto input_tys = vec::map[ast::arg, arg](ty_of_arg, decl.inputs);
451
        auto output_ty = convert(decl.output);
452 453 454
        auto t_fn =
            ty::mk_fn(cx.tcx, proto, input_tys, output_ty, decl.cf,
                      decl.constraints);
455
        auto ty_param_count = vec::len[ast::ty_param](ty_params);
456
        auto tpt = tup(ty_param_count, t_fn);
457 458
        alt (def_id) {
            case (some(?did)) { cx.tcx.tcache.insert(did, tpt); }
459
            case (_) { }
460
        }
461 462
        ret tpt;
    }
463 464 465
    fn ty_of_native_fn_decl(&@ctxt cx, &fn(&@ast::ty) -> ty::t  convert,
                            &fn(&ast::arg) -> arg  ty_of_arg,
                            &ast::fn_decl decl, ast::native_abi abi,
466
                            &vec[ast::ty_param] ty_params,
467 468 469
                            &ast::def_id def_id) ->
       ty::ty_param_count_and_ty {
        auto input_tys = vec::map[ast::arg, arg](ty_of_arg, decl.inputs);
470
        auto output_ty = convert(decl.output);
471
        auto t_fn = ty::mk_native_fn(cx.tcx, abi, input_tys, output_ty);
472
        auto ty_param_count = vec::len[ast::ty_param](ty_params);
473
        auto tpt = tup(ty_param_count, t_fn);
474
        cx.tcx.tcache.insert(def_id, tpt);
475 476
        ret tpt;
    }
477
    fn getter(@ctxt cx, &ast::def_id id) -> ty::ty_param_count_and_ty {
478
        if (id._0 != cx.tcx.sess.get_targ_crate_num()) {
479
            // This is a type we need to load in from the crate reader.
480

481
            ret creader::get_type(cx.tcx, id);
482
        }
483
        auto it = cx.tcx.items.get(id);
484
        auto tpt;
485
        alt (it) {
486 487
            case (ty::any_item_rust(?item)) { tpt = ty_of_item(cx, item); }
            case (ty::any_item_native(?native_item, ?abi)) {
488
                tpt = ty_of_native_item(cx, native_item, abi);
489 490
            }
        }
491
        ret tpt;
492
    }
L
Lindsey Kuper 已提交
493
    fn ty_of_arg(@ctxt cx, &ast::arg a) -> ty::arg {
494
        auto ty_mode = ast_mode_to_mode(a.mode);
495
        auto f = bind getter(cx, _);
496 497 498 499 500
        auto tt = ast_ty_to_ty(cx.tcx, f, a.ty);
        if (ty::type_has_dynamic_size(cx.tcx, tt)) {
            alt (ty_mode) {
                case (mo_val) {
                    cx.tcx.sess.span_err(a.ty.span,
501 502
                                         "Dynamically sized arguments \
                                          must be passed by alias");
503 504 505 506 507
                }
                case (_) { }
            }
        }
        ret rec(mode=ty_mode, ty=tt);
508
    }
L
Lindsey Kuper 已提交
509
    fn ty_of_method(@ctxt cx, &@ast::method m) -> ty::method {
510
        auto get = bind getter(cx, _);
511
        auto convert = bind ast_ty_to_ty(cx.tcx, get, _);
512
        auto f = bind ty_of_arg(cx, _);
513
        auto inputs = vec::map[ast::arg, arg](f, m.node.meth.decl.inputs);
514
        auto output = convert(m.node.meth.decl.output);
515 516 517 518 519
        ret rec(proto=m.node.meth.proto,
                ident=m.node.ident,
                inputs=inputs,
                output=output,
                cf=m.node.meth.decl.cf,
520
                constrs=m.node.meth.decl.constraints);
521
    }
522
    fn ty_of_obj(@ctxt cx, &ast::ident id, &ast::_obj obj_info,
523
                 &vec[ast::ty_param] ty_params) -> ty::ty_param_count_and_ty {
524
        auto methods = get_obj_method_types(cx, obj_info);
525 526
        auto t_obj = ty::mk_obj(cx.tcx, ty::sort_methods(methods));
        t_obj = ty::rename(cx.tcx, t_obj, id);
527
        auto ty_param_count = vec::len[ast::ty_param](ty_params);
528
        ret tup(ty_param_count, t_obj);
529
    }
530 531 532
    fn ty_of_obj_ctor(@ctxt cx, &ast::ident id, &ast::_obj obj_info,
                      &ast::def_id ctor_id, &vec[ast::ty_param] ty_params) ->
       ty::ty_param_count_and_ty {
533
        auto t_obj = ty_of_obj(cx, id, obj_info, ty_params);
534
        let vec[arg] t_inputs = [];
535
        for (ast::obj_field f in obj_info.fields) {
536
            auto g = bind getter(cx, _);
537
            auto t_field = ast_ty_to_ty(cx.tcx, g, f.ty);
538
            vec::push(t_inputs, rec(mode=ty::mo_alias(false), ty=t_field));
539
        }
540
        let vec[@ast::constr] constrs = [];
541 542 543
        auto t_fn =
            ty::mk_fn(cx.tcx, ast::proto_fn, t_inputs, t_obj._1, ast::return,
                      constrs);
544
        auto tpt = tup(t_obj._0, t_fn);
545
        cx.tcx.tcache.insert(ctor_id, tpt);
546
        ret tpt;
547
    }
548
    fn ty_of_item(&@ctxt cx, &@ast::item it) -> ty::ty_param_count_and_ty {
549
        auto get = bind getter(cx, _);
550
        auto convert = bind ast_ty_to_ty(cx.tcx, get, _);
551
        alt (it.node) {
552
            case (ast::item_const(?ident, ?t, _, _, ?def_id, _)) {
553
                auto typ = convert(t);
554
                auto tpt = tup(0u, typ);
555
                cx.tcx.tcache.insert(def_id, tpt);
556
                ret tpt;
557
            }
558
            case (ast::item_fn(?ident, ?fn_info, ?tps, _, ?def_id, _)) {
559 560
                auto f = bind ty_of_arg(cx, _);
                ret ty_of_fn_decl(cx, convert, f, fn_info.decl, fn_info.proto,
561
                                  tps, some(def_id));
562
            }
563
            case (ast::item_obj(?ident, ?obj_info, ?tps, _, ?odid, _)) {
564
                auto t_obj = ty_of_obj(cx, ident, obj_info, tps);
565
                cx.tcx.tcache.insert(odid.ty, t_obj);
566
                ret t_obj;
567
            }
568
            case (ast::item_ty(?ident, ?t, ?tps, _, ?def_id, _)) {
569
                alt (cx.tcx.tcache.find(def_id)) {
570 571
                    case (some(?tpt)) { ret tpt; }
                    case (none) { }
572 573 574
                }
                // Tell ast_ty_to_ty() that we want to perform a recursive
                // call to resolve any named types.
575

576
                auto typ = convert(t);
577
                auto ty_param_count = vec::len[ast::ty_param](tps);
578
                auto tpt = tup(ty_param_count, typ);
579
                cx.tcx.tcache.insert(def_id, tpt);
580
                ret tpt;
581
            }
582
            case (ast::item_tag(_, _, ?tps, _, ?def_id, _)) {
583
                // Create a new generic polytype.
584

585
                let vec[ty::t] subtys = [];
586
                auto i = 0u;
587
                for (ast::ty_param tp in tps) {
588
                    subtys += [ty::mk_param(cx.tcx, i)];
589
                    i += 1u;
590
                }
591
                auto t = ty::mk_tag(cx.tcx, def_id, subtys);
592
                auto ty_param_count = vec::len[ast::ty_param](tps);
593
                auto tpt = tup(ty_param_count, t);
594
                cx.tcx.tcache.insert(def_id, tpt);
595
                ret tpt;
596
            }
597
            case (ast::item_mod(_, _, _, _)) { fail; }
598
            case (ast::item_native_mod(_, _, _, _)) { fail; }
599 600
        }
    }
601 602
    fn ty_of_native_item(&@ctxt cx, &@ast::native_item it,
                         ast::native_abi abi) -> ty::ty_param_count_and_ty {
603
        alt (it.node) {
604 605
            case (ast::native_item_fn(?ident, ?lname, ?fn_decl, ?params,
                                      ?def_id, _)) {
606
                auto get = bind getter(cx, _);
607
                auto convert = bind ast_ty_to_ty(cx.tcx, get, _);
608 609 610
                auto f = bind ty_of_arg(cx, _);
                ret ty_of_native_fn_decl(cx, convert, f, fn_decl, abi, params,
                                         def_id);
611
            }
612
            case (ast::native_item_ty(_, ?def_id)) {
613
                alt (cx.tcx.tcache.find(def_id)) {
614 615
                    case (some(?tpt)) { ret tpt; }
                    case (none) { }
616
                }
617
                auto t = ty::mk_native(cx.tcx);
618
                auto tpt = tup(0u, t);
619
                cx.tcx.tcache.insert(def_id, tpt);
620
                ret tpt;
621 622 623
            }
        }
    }
624 625
    fn get_tag_variant_types(&@ctxt cx, &ast::def_id tag_id,
                             &vec[ast::variant] variants,
626
                             &vec[ast::ty_param] ty_params) {
627
        // Create a set of parameter types shared among all the variants.
628

629
        let vec[ty::t] ty_param_tys = [];
630
        auto i = 0u;
631
        for (ast::ty_param tp in ty_params) {
632
            ty_param_tys += [ty::mk_param(cx.tcx, i)];
633
            i += 1u;
634
        }
635
        auto ty_param_count = vec::len[ast::ty_param](ty_params);
636
        for (ast::variant variant in variants) {
637
            // Nullary tag constructors get turned into constants; n-ary tag
P
Patrick Walton 已提交
638
            // constructors get turned into functions.
639

P
Patrick Walton 已提交
640
            auto result_ty;
641
            if (vec::len[ast::variant_arg](variant.node.args) == 0u) {
642
                result_ty = ty::mk_tag(cx.tcx, tag_id, ty_param_tys);
P
Patrick Walton 已提交
643 644 645 646
            } else {
                // As above, tell ast_ty_to_ty() that trans_ty_item_to_ty()
                // should be called to resolve named types.

647
                auto f = bind getter(cx, _);
648
                let vec[arg] args = [];
649
                for (ast::variant_arg va in variant.node.args) {
650
                    auto arg_ty = ast_ty_to_ty(cx.tcx, f, va.ty);
651
                    args += [rec(mode=ty::mo_alias(false), ty=arg_ty)];
P
Patrick Walton 已提交
652
                }
653
                auto tag_t = ty::mk_tag(cx.tcx, tag_id, ty_param_tys);
654
                // FIXME: this will be different for constrained types
655

656
                let vec[@ast::constr] res_constrs = [];
657 658 659
                result_ty =
                    ty::mk_fn(cx.tcx, ast::proto_fn, args, tag_t, ast::return,
                              res_constrs);
P
Patrick Walton 已提交
660
            }
661
            auto tpt = tup(ty_param_count, result_ty);
662 663
            cx.tcx.tcache.insert(variant.node.id, tpt);
            write::ty_only(cx.tcx, variant.node.ann.id, result_ty);
P
Patrick Walton 已提交
664 665
        }
    }
L
Lindsey Kuper 已提交
666
    fn get_obj_method_types(&@ctxt cx, &ast::_obj object) -> vec[ty::method] {
667 668
        ret vec::map[@ast::method,
                     method](bind ty_of_method(cx, _), object.methods);
669
    }
670
    fn collect(ty::item_table id_to_ty_item, &@ast::item i) {
671
        alt (i.node) {
672
            case (ast::item_ty(_, _, _, _, ?def_id, _)) {
673
                id_to_ty_item.insert(def_id, ty::any_item_rust(i));
674
            }
675
            case (ast::item_tag(_, _, _, _, ?def_id, _)) {
676
                id_to_ty_item.insert(def_id, ty::any_item_rust(i));
677
            }
678
            case (ast::item_obj(_, _, _, _, ?odid, _)) {
679
                id_to_ty_item.insert(odid.ty, ty::any_item_rust(i));
680
            }
681
            case (_) {/* empty */ }
682 683
        }
    }
684
    fn collect_native(ty::item_table id_to_ty_item, &@ast::native_item i) {
685
        alt (i.node) {
686
            case (ast::native_item_ty(_, ?def_id)) {
687
                // The abi of types is not used.
688
                auto abi = ast::native_abi_cdecl;
689
                id_to_ty_item.insert(def_id,
690
                                     ty::any_item_native(i, abi));
691
            }
692
            case (_) {/* no-op */ }
693 694
        }
    }
695 696 697
    fn convert(@ctxt cx, @mutable option::t[ast::native_abi] abi,
               &@ast::item it) {
        alt (it.node) {
698
            case (ast::item_mod(_, _, _, _)) {
699
                // ignore item_mod, it has no type.
700

701
            }
702
            case (ast::item_native_mod(_, ?native_mod, _, _)) {
703 704
                // Propagate the native ABI down to convert_native() below,
                // but otherwise do nothing, as native modules have no types.
705

706 707
                *abi = some[ast::native_abi](native_mod.abi);
            }
708
            case (ast::item_tag(_, ?variants, ?ty_params, _, ?tag_id, ?ann)) {
709
                auto tpt = ty_of_item(cx, it);
710
                write::ty_only(cx.tcx, ann.id, tpt._1);
711 712
                get_tag_variant_types(cx, tag_id, variants, ty_params);
            }
713 714
            case (ast::item_obj(?ident, ?object, ?ty_params, _, ?odid, ?ann))
                 {
715 716
                // This calls ty_of_obj().

717
                auto t_obj = ty_of_item(cx, it);
718 719 720
                // Now we need to call ty_of_obj_ctor(); this is the type that
                // we write into the table for this item.

721 722 723
                auto tpt =
                    ty_of_obj_ctor(cx, ident, object, odid.ctor, ty_params);
                write::ty_only(cx.tcx, ann.id, tpt._1);
724 725 726 727 728
                // 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().)
729

730 731
                auto method_types = get_obj_method_types(cx, object);
                auto i = 0u;
732
                while (i < vec::len[@ast::method](object.methods)) {
733
                    write::ty_only(cx.tcx, object.methods.(i).node.ann.id,
734
                                   ty::method_ty_to_fn_ty(cx.tcx,
735
                                                          method_types.(i)));
736 737 738 739
                    i += 1u;
                }
                // Write in the types of the object fields.
                //
740
                // FIXME: We want to use uint::range() here, but that causes
741
                // an assertion in trans.
742

743 744
                auto args = ty::ty_fn_args(cx.tcx, tpt._1);
                i = 0u;
745
                while (i < vec::len[ty::arg](args)) {
746
                    auto fld = object.fields.(i);
747
                    write::ty_only(cx.tcx, fld.ann.id, args.(i).ty);
748 749 750 751 752
                    i += 1u;
                }

                // Finally, write in the type of the destructor.
                alt (object.dtor) {
753
                    case (none) {/* nothing to do */ }
754
                    case (some(?m)) {
755
                        let vec[@ast::constr] constrs = [];
756 757 758 759 760
                        let vec[arg] res_inputs = [];
                        auto t =
                            ty::mk_fn(cx.tcx, ast::proto_fn, res_inputs,
                                      ty::mk_nil(cx.tcx), ast::return,
                                      constrs);
761
                        write::ty_only(cx.tcx, m.node.ann.id, t);
762 763 764 765
                    }
                }
            }
            case (_) {
766 767 768
                // 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.
769

770
                auto tpt = ty_of_item(cx, it);
771
                write::ty_only(cx.tcx, ty::item_ann(it).id, tpt._1);
772 773 774 775 776 777 778 779 780
            }
        }
    }
    fn convert_native(@ctxt cx, @mutable option::t[ast::native_abi] abi,
                      &@ast::native_item i) {
        // 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.

781 782
        auto tpt =
            ty_of_native_item(cx, i, option::get[ast::native_abi]({ *abi }));
783
        alt (i.node) {
784
            case (ast::native_item_ty(_, _)) {
785
                // FIXME: Native types have no annotation. Should they? --pcw
786

787
            }
788
            case (ast::native_item_fn(_, _, _, _, _, ?a)) {
789
                write::ty_only(cx.tcx, a.id, tpt._1);
790 791
            }
        }
792
    }
793
    fn collect_item_types(&ty::ctxt tcx, &@ast::crate crate) {
794
        // First pass: collect all type item IDs.
795

796 797 798 799 800
        auto module = crate.node.module;
        auto visit =
            rec(visit_item_pre=bind collect(tcx.items, _),
                visit_native_item_pre=bind collect_native(tcx.items, _)
                with walk::default_visitor());
801
        walk::walk_crate(visit, *crate);
802 803 804
        // We have to propagate the surrounding ABI to the native items
        // contained within the native module.

805
        auto abi = @mutable none[ast::native_abi];
806
        auto cx = @rec(tcx=tcx);
807 808 809 810
        visit =
            rec(visit_item_pre=bind convert(cx, abi, _),
                visit_native_item_pre=bind convert_native(cx, abi, _)
                with walk::default_visitor());
811
        walk::walk_crate(visit, *crate);
812
    }
813 814
}

815 816 817

// Type unification

818
// TODO: rename to just "unify"
819
mod unify {
820 821
    fn simple(&@fn_ctxt fcx, &ty::t expected, &ty::t actual) ->
       ty::unify::result {
822
        ret ty::unify::unify(expected, actual, fcx.var_bindings, fcx.ccx.tcx);
823
    }
824 825
}

826
tag autoderef_kind { AUTODEREF_OK; NO_AUTODEREF; }
827

828
fn strip_boxes(&@fn_ctxt fcx, &span sp, &ty::t t) -> ty::t {
829 830
    auto t1 = t;
    while (true) {
831
        alt (structure_of(fcx, sp, t1)) {
832
            case (ty::ty_box(?inner)) { t1 = inner.ty; }
833 834 835 836 837 838
            case (_) { ret t1; }
        }
    }
    fail;
}

839
fn add_boxes(&@crate_ctxt ccx, uint n, &ty::t t) -> ty::t {
840
    auto t1 = t;
841
    while (n != 0u) { t1 = ty::mk_imm_box(ccx.tcx, t1); n -= 1u; }
842 843 844
    ret t1;
}

845
fn count_boxes(&@fn_ctxt fcx, &span sp, &ty::t t) -> uint {
846 847 848
    auto n = 0u;
    auto t1 = t;
    while (true) {
849
        alt (structure_of(fcx, sp, t1)) {
850
            case (ty::ty_box(?inner)) { n += 1u; t1 = inner.ty; }
851 852 853 854 855 856
            case (_) { ret n; }
        }
    }
    fail;
}

857 858 859 860 861 862 863 864
fn resolve_type_vars_if_possible(&@fn_ctxt fcx, ty::t typ) -> ty::t {
    alt (ty::unify::fixup_vars(fcx.ccx.tcx, fcx.var_bindings, typ)) {
        case (fix_ok(?new_type)) { ret new_type; }
        case (fix_err(_)) { ret typ; }
    }
}


865 866
// Demands - procedures that require that two types unify and emit an error
// message if they don't.
867
type ty_param_substs_and_ty = tup(vec[ty::t], ty::t);
868

869
mod demand {
870 871
    fn simple(&@fn_ctxt fcx, &span sp, &ty::t expected, &ty::t actual) ->
       ty::t {
872
        let vec[ty::t] tps = [];
873
        ret full(fcx, sp, expected, actual, tps, NO_AUTODEREF)._1;
874
    }
875
    fn autoderef(&@fn_ctxt fcx, &span sp, &ty::t expected, &ty::t actual,
876
                 autoderef_kind adk) -> ty::t {
877
        let vec[ty::t] tps = [];
878
        ret full(fcx, sp, expected, actual, tps, adk)._1;
879
    }
880

881 882
    // Requires that the two types unify, and prints an error message if they
    // don't. Returns the unified type and the type parameter substitutions.
883
    fn full(&@fn_ctxt fcx, &span sp, &ty::t expected, &ty::t actual,
884 885
            &vec[ty::t] ty_param_substs_0, autoderef_kind adk) ->
       ty_param_substs_and_ty {
886 887 888 889
        auto expected_1 = expected;
        auto actual_1 = actual;
        auto implicit_boxes = 0u;
        if (adk == AUTODEREF_OK) {
890 891 892
            expected_1 = strip_boxes(fcx, sp, expected_1);
            actual_1 = strip_boxes(fcx, sp, actual_1);
            implicit_boxes = count_boxes(fcx, sp, actual);
893
        }
894
        let vec[mutable ty::t] ty_param_substs = [mutable ];
895
        let vec[int] ty_param_subst_var_ids = [];
896
        for (ty::t ty_param_subst in ty_param_substs_0) {
897 898
            // Generate a type variable and unify it with the type parameter
            // substitution. We will then pull out these type variables.
899

900 901 902 903
            auto t_0 = next_ty_var(fcx);
            ty_param_substs += [mutable t_0];
            ty_param_subst_var_ids += [ty::ty_var_id(fcx.ccx.tcx, t_0)];
            simple(fcx, sp, ty_param_subst, t_0);
904
        }
905
        alt (unify::simple(fcx, expected_1, actual_1)) {
906
            case (ures_ok(?t)) {
907
                let vec[ty::t] result_ty_param_substs = [];
908
                for (int var_id in ty_param_subst_var_ids) {
909
                    auto tp_subst = ty::mk_var(fcx.ccx.tcx, var_id);
910
                    result_ty_param_substs += [tp_subst];
911
                }
912
                ret tup(result_ty_param_substs,
913
                        add_boxes(fcx.ccx, implicit_boxes, t));
914
            }
915
            case (ures_err(?err)) {
916 917
                auto e_err = resolve_type_vars_if_possible(fcx, expected_1);
                auto a_err = resolve_type_vars_if_possible(fcx, actual_1);
918 919 920 921 922 923 924
                fcx.ccx.tcx.sess.span_err(sp,
                                          "mismatched types: expected " +
                                              ty_to_str(fcx.ccx.tcx, e_err) +
                                              " but found " +
                                              ty_to_str(fcx.ccx.tcx, a_err) +
                                              " (" + ty::type_err_to_str(err)
                                              + ")");
925 926
                // TODO: In the future, try returning "expected", reporting
                // the error, and continue.
927

928
            }
929 930 931 932
        }
    }
}

933

934
// Returns true if the two types unify and false if they don't.
935 936
fn are_compatible(&@fn_ctxt fcx, &ty::t expected, &ty::t actual) -> bool {
    alt (unify::simple(fcx, expected, actual)) {
937 938
        case (ures_ok(_)) { ret true; }
        case (ures_err(_)) { ret false; }
939 940 941
    }
}

942

943
// Returns the types of the arguments to a tag variant.
944 945
fn variant_arg_types(&@crate_ctxt ccx, &span sp, &ast::def_id vid,
                     &vec[ty::t] tag_ty_params) -> vec[ty::t] {
946
    auto ty_param_count = vec::len[ty::t](tag_ty_params);
947
    let vec[ty::t] result = [];
948
    auto tpt = ty::lookup_item_type(ccx.tcx, vid);
949
    alt (ty::struct(ccx.tcx, tpt._1)) {
950
        case (ty::ty_fn(_, ?ins, _, _, _)) {
951

952
            // N-ary variant.
953
            for (ty::arg arg in ins) {
954 955 956
                auto arg_ty =
                    ty::substitute_type_params(ccx.tcx, tag_ty_params,
                                               arg.ty);
957
                result += [arg_ty];
958 959 960 961
            }
        }
        case (_) {
            // Nullary variant. Do nothing, as there are no arguments.
962

963 964
        }
    }
965
    /* result is a vector of the *expected* types of all the fields */
966

967 968 969
    ret result;
}

970

971 972 973 974 975 976
// Type resolution: the phase that finds all the types in the AST with
// unresolved type variables and replaces "ty_var" types with their
// substitutions.
//
// TODO: inefficient since not all types have vars in them. It would be better
// to maintain a list of fixups.
977
mod writeback {
978 979
    fn resolve_type_vars_in_type(&@fn_ctxt fcx, &span sp, ty::t typ) ->
       ty::t {
980 981 982 983
        if (!ty::type_contains_vars(fcx.ccx.tcx, typ)) { ret typ; }
        alt (ty::unify::fixup_vars(fcx.ccx.tcx, fcx.var_bindings, typ)) {
            case (fix_ok(?new_type)) { ret new_type; }
            case (fix_err(?vid)) {
984
                fcx.ccx.tcx.sess.span_err(sp,
985 986
                                          "cannot determine a type \
                                           for this expression");
987
            }
988
        }
989
    }
990 991 992 993 994 995 996 997 998 999 1000 1001
    fn resolve_type_vars_for_node(&@fn_ctxt fcx, &span sp, &ast::ann ann) {
        auto tpot = ty::ann_to_ty_param_substs_opt_and_ty(fcx.ccx.tcx, ann);
        auto new_ty = resolve_type_vars_in_type(fcx, sp, tpot._1);
        auto new_substs_opt;
        alt (tpot._0) {
            case (none[vec[ty::t]]) { new_substs_opt = none[vec[ty::t]]; }
            case (some[vec[ty::t]](?substs)) {
                let vec[ty::t] new_substs = [];
                for (ty::t subst in substs) {
                    new_substs += [resolve_type_vars_in_type(fcx, sp, subst)];
                }
                new_substs_opt = some[vec[ty::t]](new_substs);
1002
            }
P
Patrick Walton 已提交
1003
        }
1004
        write::ty(fcx.ccx.tcx, ann.id, tup(new_substs_opt, new_ty));
P
Patrick Walton 已提交
1005
    }
1006
    fn visit_stmt_pre(@fn_ctxt fcx, &@ast::stmt s) {
1007
        resolve_type_vars_for_node(fcx, s.span, ty::stmt_ann(s));
1008 1009
    }
    fn visit_expr_pre(@fn_ctxt fcx, &@ast::expr e) {
1010
        resolve_type_vars_for_node(fcx, e.span, ty::expr_ann(e));
1011 1012
    }
    fn visit_block_pre(@fn_ctxt fcx, &ast::block b) {
1013
        resolve_type_vars_for_node(fcx, b.span, b.node.a);
1014
    }
1015 1016
    fn visit_pat_pre(@fn_ctxt fcx, &@ast::pat p) {
        resolve_type_vars_for_node(fcx, p.span, ty::pat_ann(p));
1017
    }
1018 1019
    fn visit_local_pre(@fn_ctxt fcx, &@ast::local l) {
        auto var_id = fcx.locals.get(l.node.id);
1020 1021 1022
        auto fix_rslt =
            ty::unify::resolve_type_var(fcx.ccx.tcx, fcx.var_bindings,
                                        var_id);
1023 1024 1025 1026 1027 1028
        alt (fix_rslt) {
            case (fix_ok(?lty)) {
                write::ty_only(fcx.ccx.tcx, l.node.ann.id, lty);
            }
            case (fix_err(_)) {
                fcx.ccx.tcx.sess.span_err(l.span,
1029 1030
                                          "cannot determine a type \
                                           for this local variable");
1031
            }
1032
        }
1033
    }
1034
    fn resolve_type_vars_in_block(&@fn_ctxt fcx, &ast::block block) {
1035
        // A trick to ignore any contained items.
1036

1037 1038 1039 1040 1041 1042 1043 1044
        auto ignore = @mutable false;
        fn visit_item_pre(@mutable bool ignore, &@ast::item item) {
            *ignore = true;
        }
        fn visit_item_post(@mutable bool ignore, &@ast::item item) {
            *ignore = false;
        }
        fn keep_going(@mutable bool ignore) -> bool { ret !*ignore; }
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
        auto visit =
            rec(keep_going=bind keep_going(ignore),
                visit_item_pre=bind visit_item_pre(ignore, _),
                visit_item_post=bind visit_item_post(ignore, _),
                visit_stmt_pre=bind visit_stmt_pre(fcx, _),
                visit_expr_pre=bind visit_expr_pre(fcx, _),
                visit_block_pre=bind visit_block_pre(fcx, _),
                visit_pat_pre=bind visit_pat_pre(fcx, _),
                visit_local_pre=bind visit_local_pre(fcx, _)
                with walk::default_visitor());
1055 1056
        walk::walk_block(visit, block);
    }
1057 1058
}

1059

1060 1061
// Local variable gathering. We gather up all locals and create variable IDs
// for them before typechecking the function.
1062 1063 1064 1065 1066
type gather_result =
    rec(@ty::unify::var_bindings var_bindings,
        hashmap[ast::def_id, int] locals,
        hashmap[ast::def_id, ast::ident] local_names,
        int next_var_id);
1067 1068 1069 1070 1071 1072 1073 1074

fn gather_locals(&@crate_ctxt ccx, &ast::fn_decl decl, &ast::block body,
                 &ast::ann ann) -> gather_result {
    fn next_var_id(@mutable int nvi) -> int {
        auto rv = *nvi;
        *nvi += 1;
        ret rv;
    }
1075 1076 1077 1078
    fn assign(&ty::ctxt tcx, &@ty::unify::var_bindings var_bindings,
              &hashmap[ast::def_id, int] locals,
              &hashmap[ast::def_id, ast::ident] local_names, @mutable int nvi,
              ast::def_id lid, &ast::ident ident, option::t[ty::t] ty_opt) {
1079 1080 1081 1082
        auto var_id = next_var_id(nvi);
        locals.insert(lid, var_id);
        local_names.insert(lid, ident);
        alt (ty_opt) {
1083
            case (none[ty::t]) {/* nothing to do */ }
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
            case (some[ty::t](?typ)) {
                ty::unify::unify(ty::mk_var(tcx, var_id), typ, var_bindings,
                                 tcx);
            }
        }
    }
    auto vb = ty::unify::mk_var_bindings();
    auto locals = new_def_hash[int]();
    auto local_names = new_def_hash[ast::ident]();
    auto nvi = @mutable 0;
    // Add object fields, if any.
1095

1096 1097 1098 1099 1100 1101 1102 1103
    alt (get_obj_info(ccx)) {
        case (option::some(?oinfo)) {
            for (ast::obj_field f in oinfo.obj_fields) {
                auto field_ty = ty::ann_to_type(ccx.tcx, f.ann);
                assign(ccx.tcx, vb, locals, local_names, nvi, f.id, f.ident,
                       some[ty::t](field_ty));
            }
        }
1104
        case (option::none) {/* no fields */ }
1105 1106
    }
    // Add formal parameters.
1107

1108 1109 1110 1111 1112 1113 1114 1115
    auto args = ty::ty_fn_args(ccx.tcx, ty::ann_to_type(ccx.tcx, ann));
    auto i = 0u;
    for (ty::arg arg in args) {
        assign(ccx.tcx, vb, locals, local_names, nvi, decl.inputs.(i).id,
               decl.inputs.(i).ident, some[ty::t](arg.ty));
        i += 1u;
    }
    // Add explicitly-declared locals.
1116 1117 1118 1119 1120

    fn visit_local_pre(@crate_ctxt ccx, @ty::unify::var_bindings vb,
                       hashmap[ast::def_id, int] locals,
                       hashmap[ast::def_id, ast::ident] local_names,
                       @mutable int nvi, &@ast::local local) {
1121 1122 1123
        alt (local.node.ty) {
            case (none) {
                // Auto slot.
1124 1125 1126

                assign(ccx.tcx, vb, locals, local_names, nvi, local.node.id,
                       local.node.ident, none[ty::t]);
1127 1128 1129
            }
            case (some(?ast_ty)) {
                // Explicitly typed slot.
1130

1131
                auto local_ty = ast_ty_to_ty_crate(ccx, ast_ty);
1132 1133
                assign(ccx.tcx, vb, locals, local_names, nvi, local.node.id,
                       local.node.ident, some[ty::t](local_ty));
1134 1135 1136 1137
            }
        }
    }
    // Add pattern bindings.
1138 1139 1140 1141 1142

    fn visit_pat_pre(@crate_ctxt ccx, @ty::unify::var_bindings vb,
                     hashmap[ast::def_id, int] locals,
                     hashmap[ast::def_id, ast::ident] local_names,
                     @mutable int nvi, &@ast::pat p) {
1143 1144 1145 1146 1147
        alt (p.node) {
            case (ast::pat_bind(?ident, ?did, _)) {
                assign(ccx.tcx, vb, locals, local_names, nvi, did, ident,
                       none[ty::t]);
            }
1148
            case (_) {/* no-op */ }
1149 1150 1151
        }
    }
    auto visit =
1152
        rec(visit_local_pre=bind visit_local_pre(ccx, vb, locals, local_names,
1153
                                                 nvi, _),
1154 1155 1156 1157
            visit_pat_pre=bind visit_pat_pre(ccx, vb, locals, local_names,
                                             nvi, _)
            with walk::default_visitor());
    walk::walk_block(visit, body);
1158 1159 1160 1161
    ret rec(var_bindings=vb,
            locals=locals,
            local_names=local_names,
            next_var_id=*nvi);
1162 1163 1164
}


1165
// AST fragment utilities
1166
fn replace_expr_type(&@fn_ctxt fcx, &@ast::expr expr,
1167
                     &tup(vec[ty::t], ty::t) new_tyt) {
1168
    auto new_tps;
1169
    if (ty::expr_has_ty_params(fcx.ccx.tcx, expr)) {
1170
        new_tps = some[vec[ty::t]](new_tyt._0);
1171
    } else { new_tps = none[vec[ty::t]]; }
1172 1173 1174 1175 1176 1177 1178 1179
    write::ty_fixup(fcx, ty::expr_ann(expr).id, tup(new_tps, new_tyt._1));
}

fn replace_node_type_only(&ty::ctxt tcx, uint fixup, ty::t new_t) {
    auto fixup_opt = tcx.node_types.(fixup);
    auto tps = option::get[ty::ty_param_substs_opt_and_ty](fixup_opt)._0;
    tcx.node_types.(fixup) =
        some[ty::ty_param_substs_opt_and_ty](tup(tps, new_t));
1180 1181 1182
}


1183
// AST fragment checking
1184
fn check_lit(@crate_ctxt ccx, &@ast::lit lit) -> ty::t {
1185
    alt (lit.node) {
1186
        case (ast::lit_str(_, ast::sk_rc)) { ret ty::mk_str(ccx.tcx); }
1187
        case (ast::lit_str(_, ast::sk_unique)) { ret ty::mk_istr(ccx.tcx); }
1188 1189 1190 1191 1192 1193 1194 1195
        case (ast::lit_char(_)) { ret ty::mk_char(ccx.tcx); }
        case (ast::lit_int(_)) { ret ty::mk_int(ccx.tcx); }
        case (ast::lit_float(_)) { ret ty::mk_float(ccx.tcx); }
        case (ast::lit_mach_float(?tm, _)) { ret ty::mk_mach(ccx.tcx, tm); }
        case (ast::lit_uint(_)) { ret ty::mk_uint(ccx.tcx); }
        case (ast::lit_mach_int(?tm, _)) { ret ty::mk_mach(ccx.tcx, tm); }
        case (ast::lit_nil) { ret ty::mk_nil(ccx.tcx); }
        case (ast::lit_bool(_)) { ret ty::mk_bool(ccx.tcx); }
1196 1197 1198
    }
}

1199

1200 1201
// Pattern checking is top-down rather than bottom-up so that bindings get
// their types immediately.
1202
fn check_pat(&@fn_ctxt fcx, &@ast::pat pat, ty::t expected) {
1203
    alt (pat.node) {
1204
        case (ast::pat_wild(?ann)) {
1205
            write::ty_only_fixup(fcx, ann.id, expected);
1206
        }
1207
        case (ast::pat_lit(?lt, ?ann)) {
1208 1209 1210
            auto typ = check_lit(fcx.ccx, lt);
            typ = demand::simple(fcx, pat.span, expected, typ);
            write::ty_only_fixup(fcx, ann.id, typ);
1211
        }
1212
        case (ast::pat_bind(?id, ?def_id, ?ann)) {
1213 1214 1215 1216
            auto vid = fcx.locals.get(def_id);
            auto typ = ty::mk_var(fcx.ccx.tcx, vid);
            typ = demand::simple(fcx, pat.span, expected, typ);
            write::ty_only_fixup(fcx, ann.id, typ);
1217
        }
1218 1219
        case (ast::pat_tag(?path, ?subpats, ?ann)) {
            // Typecheck the path.
1220

1221
            auto v_def = fcx.ccx.tcx.def_map.get(ann.id);
1222
            auto v_def_ids = ast::variant_def_ids(v_def);
1223
            auto tag_tpt = ty::lookup_item_type(fcx.ccx.tcx, v_def_ids._0);
1224
            auto path_tpot = instantiate_path(fcx, path, tag_tpt, pat.span);
1225
            // Take the tag type params out of `expected`.
1226

1227
            auto expected_tps;
1228
            alt (structure_of(fcx, pat.span, expected)) {
1229 1230 1231 1232
                case (ty::ty_tag(_, ?tps)) { expected_tps = tps; }
                case (_) {
                    // FIXME: Switch expected and actual in this message? I
                    // can never tell.
1233

1234
                    fcx.ccx.tcx.sess.span_err(pat.span,
1235 1236 1237 1238
                                              #fmt("mismatched types: \
                                                    expected tag, found %s",
                                                   ty_to_str(fcx.ccx.tcx,
                                                             expected)));
1239
                }
1240 1241 1242
            }
            // Unify with the expected tag type.

1243 1244 1245 1246 1247 1248 1249
            auto ctor_ty =
                ty::ty_param_substs_opt_and_ty_to_monotype(fcx.ccx.tcx,
                                                           path_tpot);
            auto path_tpt =
                demand::full(fcx, pat.span, expected, ctor_ty, expected_tps,
                             NO_AUTODEREF);
            path_tpot = tup(some[vec[ty::t]](path_tpt._0), path_tpt._1);
1250 1251
            // Get the number of arguments in this tag variant.

1252 1253 1254
            auto arg_types =
                variant_arg_types(fcx.ccx, pat.span, v_def_ids._1,
                                  expected_tps);
1255 1256 1257
            auto subpats_len = vec::len[@ast::pat](subpats);
            if (vec::len[ty::t](arg_types) > 0u) {
                // N-ary variant.
1258

1259 1260 1261 1262 1263
                auto arg_len = vec::len[ty::t](arg_types);
                if (arg_len != subpats_len) {
                    // TODO: note definition of tag variant
                    // TODO (issue #448): Wrap a #fmt string over multiple
                    // lines...
1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
                    auto 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_err(pat.span, s);
1274 1275
                }
                // TODO: vec::iter2
1276

1277 1278
                auto i = 0u;
                for (@ast::pat subpat in subpats) {
1279
                    check_pat(fcx, subpat, arg_types.(i));
1280
                    i += 1u;
1281
                }
1282 1283 1284 1285 1286
            } else if (subpats_len > 0u) {
                // TODO: note definition of tag variant
                // TODO (issue #448): Wrap a #fmt string over multiple
                // lines...

1287 1288 1289 1290 1291 1292 1293 1294 1295
                fcx.ccx.tcx.sess.span_err(pat.span,
                                          #fmt("this pattern has %u field%s, \
                                                but the corresponding \
                                                variant has no fields",
                                               subpats_len,
                                               if (subpats_len == 1u) {
                                                   ""
                                               } else { "s" }));
            }
1296
            write::ty_fixup(fcx, ann.id, path_tpot);
1297 1298 1299 1300
        }
    }
}

1301
fn require_impure(&session::session sess, &ast::purity f_purity, &span sp) {
1302
    alt (f_purity) {
1303
        case (ast::impure_fn) { ret; }
1304
        case (ast::pure_fn) {
1305
            sess.span_err(sp,
1306
                          "Found impure expression in pure function decl");
1307 1308 1309 1310
        }
    }
}

1311 1312 1313
fn get_function_purity(@crate_ctxt ccx, &ast::def_id d_id) -> ast::purity {
    let option::t[ast::purity] o = ccx.fn_purity_table.find(d_id);
    ret from_maybe[ast::purity](ast::impure_fn, o);
1314 1315
}

1316 1317
fn require_pure_call(@crate_ctxt ccx, &ast::purity caller_purity,
                     &@ast::expr callee, &span sp) {
1318
    alt (caller_purity) {
1319
        case (ast::impure_fn) { ret; }
1320
        case (ast::pure_fn) {
1321
            alt (callee.node) {
1322
                case (ast::expr_path(_, ?ann)) {
1323
                    auto d_id;
P
Patrick Walton 已提交
1324
                    alt (ccx.tcx.def_map.get(ann.id)) {
1325
                        case (ast::def_fn(?_d_id)) { d_id = _d_id; }
1326
                    }
1327
                    alt (get_function_purity(ccx, d_id)) {
1328 1329 1330 1331 1332
                        case (ast::pure_fn) { ret; }
                        case (_) {
                            ccx.tcx.sess.span_err(sp,
                                                  "Pure function calls \
                                                   impure function");
1333
                        }
1334
                    }
1335 1336
                }
                case (_) {
1337
                    ccx.tcx.sess.span_err(sp,
1338 1339
                                          "Pure function calls \
                                           unknown function");
1340 1341 1342 1343 1344 1345
                }
            }
        }
    }
}

1346
fn require_pure_function(@crate_ctxt ccx, &ast::def_id d_id, &span sp) {
1347
    alt (get_function_purity(ccx, d_id)) {
1348
        case (ast::impure_fn) {
1349 1350
            ccx.tcx.sess.span_err(sp,
                                  "Found non-predicate in check expression");
1351 1352 1353 1354 1355
        }
        case (_) { ret; }
    }
}

1356 1357
fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
    // fcx.ccx.tcx.sess.span_warn(expr.span, "typechecking expr " +
1358
    //                                pretty::pprust::expr_to_str(expr));
1359

1360 1361
    // A generic function to factor out common logic from call and bind
    // expressions.
1362

1363
    fn check_call_or_bind(&@fn_ctxt fcx, &span sp, &@ast::expr f,
1364
                          &vec[option::t[@ast::expr]] args) {
1365 1366
        // Check the function.

1367
        check_expr(fcx, f);
1368
        // Get the function type.
1369

1370
        auto fty = expr_ty(fcx.ccx.tcx, f);
1371
        // Grab the argument types and the return type.
1372

1373
        auto arg_tys;
1374
        alt (structure_of(fcx, sp, fty)) {
1375 1376
            case (ty::ty_fn(_, ?arg_tys_0, _, _, _)) { arg_tys = arg_tys_0; }
            case (ty::ty_native_fn(_, ?arg_tys_0, _)) { arg_tys = arg_tys_0; }
1377
            case (_) {
1378 1379 1380 1381 1382
                fcx.ccx.tcx.sess.span_err(f.span,
                                          "mismatched types: \
                                           expected function or native \
                                           function but found "
                                          + ty_to_str(fcx.ccx.tcx, fty));
1383 1384 1385
            }
        }
        // Check that the correct number of arguments were supplied.
1386

1387 1388 1389 1390
        auto expected_arg_count = vec::len[ty::arg](arg_tys);
        auto supplied_arg_count = vec::len[option::t[@ast::expr]](args);
        if (expected_arg_count != supplied_arg_count) {
            fcx.ccx.tcx.sess.span_err(sp,
1391 1392 1393 1394 1395 1396 1397 1398 1399 1400
                                      #fmt("this function takes %u \
                                            parameter%s but %u parameter%s \
                                            supplied",
                                           expected_arg_count,
                                           if (expected_arg_count == 1u) {
                                               ""
                                           } else { "s" }, supplied_arg_count,
                                           if (supplied_arg_count == 1u) {
                                               " was"
                                           } else { "s were" }));
1401 1402 1403
        }
        // Check the arguments.
        // TODO: iter2
1404

1405
        auto i = 0u;
1406
        for (option::t[@ast::expr] a_opt in args) {
1407
            alt (a_opt) {
1408
                case (some(?a)) {
1409
                    check_expr(fcx, a);
1410 1411
                    demand::simple(fcx, a.span, arg_tys.(i).ty,
                                   expr_ty(fcx.ccx.tcx, a));
1412
                }
1413
                case (none) {/* no-op */ }
1414
            }
1415
            i += 1u;
1416 1417
        }
    }
1418
    // A generic function for checking assignment expressions
1419

1420 1421
    fn check_assignment(&@fn_ctxt fcx, &span sp, &@ast::expr lhs,
                        &@ast::expr rhs, &ast::ann a) {
1422 1423
        check_expr(fcx, lhs);
        check_expr(fcx, rhs);
1424 1425 1426
        auto typ =
            demand::simple(fcx, sp, expr_ty(fcx.ccx.tcx, lhs),
                           expr_ty(fcx.ccx.tcx, rhs));
1427
        write::ty_only_fixup(fcx, a.id, ty::mk_nil(fcx.ccx.tcx));
1428
    }
1429
    // A generic function for checking call expressions
1430

1431 1432
    fn check_call(&@fn_ctxt fcx, &span sp, &@ast::expr f,
                  &vec[@ast::expr] args) {
1433
        let vec[option::t[@ast::expr]] args_opt_0 = [];
1434
        for (@ast::expr arg in args) {
1435
            args_opt_0 += [some[@ast::expr](arg)];
1436 1437
        }
        // Call the generic checker.
1438

1439
        check_call_or_bind(fcx, sp, f, args_opt_0);
1440
    }
1441
    // A generic function for checking for or for-each loops
1442

1443
    fn check_for_or_for_each(&@fn_ctxt fcx, &@ast::local local,
1444 1445
                             &ty::t element_ty, &ast::block body,
                             uint node_id) {
1446
        check_decl_local(fcx, local.node);
1447
        check_block(fcx, body);
1448
        // Unify type of decl with element type of the seq
1449 1450 1451

        demand::simple(fcx, local.span,
                       ty::decl_local_ty(fcx.ccx.tcx, local.node),
1452
                       element_ty);
1453 1454
        auto typ = ty::mk_nil(fcx.ccx.tcx);
        write::ty_only_fixup(fcx, node_id, typ);
1455
    }
1456
    alt (expr.node) {
1457
        case (ast::expr_lit(?lit, ?a)) {
1458 1459
            auto typ = check_lit(fcx.ccx, lit);
            write::ty_only_fixup(fcx, a.id, typ);
1460
        }
1461
        case (ast::expr_binary(?binop, ?lhs, ?rhs, ?a)) {
1462 1463
            check_expr(fcx, lhs);
            check_expr(fcx, rhs);
1464 1465
            auto lhs_t = expr_ty(fcx.ccx.tcx, lhs);
            // FIXME: Binops have a bit more subtlety than this.
1466

1467
            auto t = strip_boxes(fcx, expr.span, lhs_t);
1468
            alt (binop) {
1469 1470 1471 1472 1473 1474
                case (ast::eq) { t = ty::mk_bool(fcx.ccx.tcx); }
                case (ast::lt) { t = ty::mk_bool(fcx.ccx.tcx); }
                case (ast::le) { t = ty::mk_bool(fcx.ccx.tcx); }
                case (ast::ne) { t = ty::mk_bool(fcx.ccx.tcx); }
                case (ast::ge) { t = ty::mk_bool(fcx.ccx.tcx); }
                case (ast::gt) { t = ty::mk_bool(fcx.ccx.tcx); }
1475
                case (_) {/* fall through */ }
1476
            }
1477
            write::ty_only_fixup(fcx, a.id, t);
1478
        }
1479
        case (ast::expr_unary(?unop, ?oper, ?a)) {
1480 1481
            check_expr(fcx, oper);
            auto oper_t = expr_ty(fcx.ccx.tcx, oper);
1482
            alt (unop) {
1483
                case (ast::box(?mut)) {
1484
                    oper_t = ty::mk_box(fcx.ccx.tcx, rec(ty=oper_t, mut=mut));
1485
                }
1486
                case (ast::deref) {
1487
                    alt (structure_of(fcx, expr.span, oper_t)) {
1488
                        case (ty::ty_box(?inner)) { oper_t = inner.ty; }
1489
                        case (_) {
1490 1491 1492
                            auto s = "dereferencing non-box type: " +
                                ty_to_str(fcx.ccx.tcx, oper_t);
                            fcx.ccx.tcx.sess.span_err(expr.span, s);
1493 1494 1495
                        }
                    }
                }
1496 1497
                case (ast::not) {
                    if (!type_is_integral(fcx, oper.span, oper_t) &&
1498 1499
                            structure_of(fcx, oper.span, oper_t) !=
                                ty::ty_bool) {
1500
                        fcx.ccx.tcx.sess.span_err(expr.span,
1501 1502 1503 1504 1505
                                                  #fmt("mismatched types: \
                                                        expected bool or \
                                                        integer but found %s",
                                                       ty_to_str(fcx.ccx.tcx,
                                                                 oper_t)));
1506 1507
                    }
                }
1508
                case (_) { oper_t = strip_boxes(fcx, expr.span, oper_t); }
1509
            }
1510
            write::ty_only_fixup(fcx, a.id, oper_t);
1511
        }
1512
        case (ast::expr_path(?pth, ?old_ann)) {
1513 1514
            auto t = ty::mk_nil(fcx.ccx.tcx);
            auto defn = fcx.ccx.tcx.def_map.get(old_ann.id);
1515
            auto tpt = ty_param_count_and_ty_for_def(fcx, expr.span, defn);
1516
            if (ty::def_has_ty_params(defn)) {
1517 1518
                auto path_tpot = instantiate_path(fcx, pth, tpt, expr.span);
                write::ty_fixup(fcx, old_ann.id, path_tpot);
1519
                ret;
1520 1521 1522
            }
            // The definition doesn't take type parameters. If the programmer
            // supplied some, that's an error.
1523

1524
            if (vec::len[@ast::ty](pth.node.types) > 0u) {
1525
                fcx.ccx.tcx.sess.span_err(expr.span,
1526 1527
                                          "this kind of value does not \
                                           take type parameters");
1528
            }
1529
            write::ty_only_fixup(fcx, old_ann.id, tpt._1);
1530
        }
1531
        case (ast::expr_ext(?p, ?args, ?body, ?expanded, ?a)) {
1532 1533 1534
            check_expr(fcx, expanded);
            auto t = expr_ty(fcx.ccx.tcx, expanded);
            write::ty_only_fixup(fcx, a.id, t);
1535
        }
1536 1537 1538
        case (ast::expr_fail(?a, _)) { write::bot_ty(fcx.ccx.tcx, a.id); }
        case (ast::expr_break(?a)) { write::bot_ty(fcx.ccx.tcx, a.id); }
        case (ast::expr_cont(?a)) { write::bot_ty(fcx.ccx.tcx, a.id); }
1539
        case (ast::expr_ret(?expr_opt, ?a)) {
1540
            alt (expr_opt) {
1541
                case (none) {
1542 1543 1544
                    auto nil = ty::mk_nil(fcx.ccx.tcx);
                    if (!are_compatible(fcx, fcx.ret_ty, nil)) {
                        fcx.ccx.tcx.sess.span_err(expr.span,
1545 1546
                                                  "ret; in function \
                                                   returning non-nil");
1547
                    }
1548
                    write::bot_ty(fcx.ccx.tcx, a.id);
1549
                }
1550
                case (some(?e)) {
1551
                    check_expr(fcx, e);
1552 1553
                    demand::simple(fcx, expr.span, fcx.ret_ty,
                                   expr_ty(fcx.ccx.tcx, e));
1554
                    write::bot_ty(fcx.ccx.tcx, a.id);
1555 1556 1557
                }
            }
        }
1558
        case (ast::expr_put(?expr_opt, ?a)) {
1559
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
1560
            alt (expr_opt) {
1561
                case (none) {
1562 1563
                    auto nil = ty::mk_nil(fcx.ccx.tcx);
                    if (!are_compatible(fcx, fcx.ret_ty, nil)) {
1564 1565 1566
                        fcx.ccx.tcx.sess.span_err(expr.span,
                                                  "put; in iterator \
                                                   yielding non-nil");
1567
                    }
1568
                    write::nil_ty(fcx.ccx.tcx, a.id);
1569
                }
1570
                case (some(?e)) {
1571 1572
                    check_expr(fcx, e);
                    write::nil_ty(fcx.ccx.tcx, a.id);
1573 1574 1575
                }
            }
        }
1576
        case (ast::expr_be(?e, ?a)) {
1577
            // FIXME: prove instead of assert
P
Patrick Walton 已提交
1578

1579
            assert (ast::is_call_expr(e));
1580
            check_expr(fcx, e);
1581
            demand::simple(fcx, e.span, fcx.ret_ty, expr_ty(fcx.ccx.tcx, e));
1582
            write::nil_ty(fcx.ccx.tcx, a.id);
1583
        }
1584
        case (ast::expr_log(?l, ?e, ?a)) {
1585 1586
            auto expr_t = check_expr(fcx, e);
            write::nil_ty(fcx.ccx.tcx, a.id);
1587
        }
1588
        case (ast::expr_check(?e, ?a)) {
1589 1590
            check_expr(fcx, e);
            demand::simple(fcx, expr.span, ty::mk_bool(fcx.ccx.tcx),
1591 1592
                           expr_ty(fcx.ccx.tcx, e));

1593 1594 1595
            /* e must be a call expr where all arguments are either
             literals or slots */
            alt (e.node) {
1596
                case (ast::expr_call(?operator, ?operands, _)) {
1597
                    alt (operator.node) {
1598
                        case (ast::expr_path(?oper_name, ?ann)) {
1599
                            auto d_id;
1600
                            alt (fcx.ccx.tcx.def_map.get(ann.id)) {
1601
                                case (ast::def_fn(?_d_id)) { d_id = _d_id; }
1602
                            }
1603
                            for (@ast::expr operand in operands) {
1604 1605 1606 1607
                                if (!ast::is_constraint_arg(operand)) {
                                    auto s = "Constraint args must be \
                                              slot variables or literals";
                                    fcx.ccx.tcx.sess.span_err(expr.span, s);
1608 1609
                                }
                            }
1610
                            require_pure_function(fcx.ccx, d_id, expr.span);
1611
                            write::nil_ty(fcx.ccx.tcx, a.id);
1612 1613
                        }
                        case (_) {
1614 1615 1616
                            auto s = "In a constraint, expected the \
                                      constraint name to be an explicit name";
                            fcx.ccx.tcx.sess.span_err(expr.span,s);
1617 1618
                        }
                    }
1619 1620
                }
                case (_) {
1621
                    fcx.ccx.tcx.sess.span_err(expr.span,
1622
                                              "check on non-predicate");
1623 1624
                }
            }
1625
        }
1626
        case (ast::expr_assert(?e, ?a)) {
1627 1628 1629 1630
            check_expr(fcx, e);
            auto ety = expr_ty(fcx.ccx.tcx, e);
            demand::simple(fcx, expr.span, ty::mk_bool(fcx.ccx.tcx), ety);
            write::nil_ty(fcx.ccx.tcx, a.id);
1631
        }
1632
        case (ast::expr_move(?lhs, ?rhs, ?a)) {
1633
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
1634
            check_assignment(fcx, expr.span, lhs, rhs, a);
1635
        }
1636
        case (ast::expr_assign(?lhs, ?rhs, ?a)) {
1637
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
1638
            check_assignment(fcx, expr.span, lhs, rhs, a);
1639
        }
1640
        case (ast::expr_assign_op(?op, ?lhs, ?rhs, ?a)) {
1641
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
1642
            check_assignment(fcx, expr.span, lhs, rhs, a);
1643
        }
1644
        case (ast::expr_send(?lhs, ?rhs, ?a)) {
1645 1646 1647 1648 1649
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
            check_expr(fcx, lhs);
            check_expr(fcx, rhs);
            auto rhs_t = expr_ty(fcx.ccx.tcx, rhs);
            auto chan_t = ty::mk_chan(fcx.ccx.tcx, rhs_t);
1650
            auto item_t;
1651
            auto lhs_t = expr_ty(fcx.ccx.tcx, lhs);
1652
            alt (structure_of(fcx, expr.span, lhs_t)) {
1653
                case (ty::ty_chan(?it)) { item_t = it; }
1654
                case (_) {
1655 1656 1657 1658 1659
                    auto s = #fmt("mismatched types: expected chan \
                                   but found %s",
                                  ty_to_str(fcx.ccx.tcx,
                                            lhs_t));
                    fcx.ccx.tcx.sess.span_err(expr.span,s);
1660
                }
1661
            }
1662
            write::ty_only_fixup(fcx, a.id, chan_t);
1663
        }
1664
        case (ast::expr_recv(?lhs, ?rhs, ?a)) {
1665 1666 1667
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
            check_expr(fcx, lhs);
            check_expr(fcx, rhs);
1668 1669 1670
            auto item_t = expr_ty(fcx.ccx.tcx, lhs);
            auto port_t = ty::mk_port(fcx.ccx.tcx, item_t);
            demand::simple(fcx, expr.span, port_t, expr_ty(fcx.ccx.tcx, rhs));
1671
            write::ty_only_fixup(fcx, a.id, item_t);
1672
        }
1673
        case (ast::expr_if(?cond, ?thn, ?elsopt, ?a)) {
1674 1675
            check_expr(fcx, cond);
            check_block(fcx, thn);
1676 1677 1678 1679 1680 1681 1682 1683 1684 1685
            auto if_t =
                alt (elsopt) {
                    case (some(?els)) {
                        check_expr(fcx, els);
                        auto thn_t = block_ty(fcx.ccx.tcx, thn);
                        auto elsopt_t = expr_ty(fcx.ccx.tcx, els);
                        demand::simple(fcx, expr.span, thn_t, elsopt_t);
                        if (!ty::type_is_bot(fcx.ccx.tcx, elsopt_t)) {
                            elsopt_t
                        } else { thn_t }
1686
                    }
1687 1688
                    case (none) { ty::mk_nil(fcx.ccx.tcx) }
                };
1689
            write::ty_only_fixup(fcx, a.id, if_t);
1690
        }
1691
        case (ast::expr_for(?decl, ?seq, ?body, ?a)) {
1692
            check_expr(fcx, seq);
1693
            auto elt_ty;
1694
            alt (structure_of(fcx, expr.span, expr_ty(fcx.ccx.tcx, seq))) {
1695
                case (ty::ty_vec(?vec_elt_ty)) { elt_ty = vec_elt_ty.ty; }
1696
                case (ty::ty_str) {
1697
                    elt_ty = ty::mk_mach(fcx.ccx.tcx, util::common::ty_u8);
1698 1699
                }
                case (_) {
1700
                    fcx.ccx.tcx.sess.span_err(expr.span,
1701 1702
                                              "type of for loop iterator \
                                               is not a vector or string");
1703 1704
                }
            }
1705
            check_for_or_for_each(fcx, decl, elt_ty, body, a.id);
1706
        }
1707
        case (ast::expr_for_each(?decl, ?seq, ?body, ?a)) {
1708
            check_expr(fcx, seq);
1709 1710
            check_for_or_for_each(fcx, decl, expr_ty(fcx.ccx.tcx, seq), body,
                                  a.id);
1711
        }
1712
        case (ast::expr_while(?cond, ?body, ?a)) {
1713 1714
            check_expr(fcx, cond);
            check_block(fcx, body);
1715 1716
            demand::simple(fcx, cond.span, ty::mk_bool(fcx.ccx.tcx),
                           expr_ty(fcx.ccx.tcx, cond));
1717 1718
            auto typ = ty::mk_nil(fcx.ccx.tcx);
            write::ty_only_fixup(fcx, a.id, typ);
1719
        }
1720
        case (ast::expr_do_while(?body, ?cond, ?a)) {
1721 1722 1723 1724
            check_expr(fcx, cond);
            check_block(fcx, body);
            auto typ = block_ty(fcx.ccx.tcx, body);
            write::ty_only_fixup(fcx, a.id, typ);
1725
        }
1726
        case (ast::expr_alt(?expr, ?arms, ?a)) {
1727
            check_expr(fcx, expr);
1728 1729
            // Typecheck the patterns first, so that we get types for all the
            // bindings.
1730

1731
            auto pattern_ty = ty::expr_ty(fcx.ccx.tcx, expr);
1732
            let vec[@ast::pat] pats = [];
1733
            for (ast::arm arm in arms) {
1734
                check_pat(fcx, arm.pat, pattern_ty);
1735
                pats += [arm.pat];
1736 1737 1738
            }
            // Now typecheck the blocks.

1739
            auto result_ty = next_ty_var(fcx);
1740
            let vec[ast::block] blocks = [];
1741
            for (ast::arm arm in arms) {
1742 1743
                check_block(fcx, arm.block);
                auto bty = block_ty(fcx.ccx.tcx, arm.block);
1744

1745
                // Failing alt arms don't need to have a matching type
1746
                if (!ty::type_is_bot(fcx.ccx.tcx, bty)) {
1747 1748
                    result_ty =
                        demand::simple(fcx, arm.block.span, result_ty, bty);
1749
                }
1750
            }
1751
            write::ty_only_fixup(fcx, a.id, result_ty);
1752
        }
1753
        case (ast::expr_fn(?f, ?a)) {
1754 1755 1756
            auto cx = @rec(tcx=fcx.ccx.tcx);
            auto convert =
                bind ast_ty_to_ty(cx.tcx, bind collect::getter(cx, _), _);
1757
            auto ty_of_arg = bind collect::ty_of_arg(cx, _);
1758 1759 1760
            auto fty =
                collect::ty_of_fn_decl(cx, convert, ty_of_arg, f.decl,
                                       f.proto, [], none)._1;
1761 1762 1763
            write::ty_only_fixup(fcx, a.id, fty);
            check_fn(fcx.ccx, f.decl, f.proto, f.body, a);
        }
1764
        case (ast::expr_block(?b, ?a)) {
1765
            check_block(fcx, b);
1766
            alt (b.node.expr) {
1767
                case (some(?expr)) {
1768 1769
                    auto typ = expr_ty(fcx.ccx.tcx, expr);
                    write::ty_only_fixup(fcx, a.id, typ);
1770
                }
1771
                case (none) {
1772 1773
                    auto typ = ty::mk_nil(fcx.ccx.tcx);
                    write::ty_only_fixup(fcx, a.id, typ);
1774 1775 1776
                }
            }
        }
1777
        case (ast::expr_bind(?f, ?args, ?a)) {
1778
            // Call the generic checker.
G
Graydon Hoare 已提交
1779

1780
            check_call_or_bind(fcx, expr.span, f, args);
1781
            // Pull the argument and return types out.
1782

B
Brian Anderson 已提交
1783
            auto proto_1;
1784
            let vec[ty::arg] arg_tys_1 = [];
B
Brian Anderson 已提交
1785
            auto rt_1;
1786
            auto fty = expr_ty(fcx.ccx.tcx, f);
1787
            auto t_1;
1788
            alt (structure_of(fcx, expr.span, fty)) {
1789
                case (ty::ty_fn(?proto, ?arg_tys, ?rt, ?cf, ?constrs)) {
1790 1791
                    proto_1 = proto;
                    rt_1 = rt;
1792 1793 1794 1795
                    // FIXME:
                    // probably need to munge the constrs to drop constraints
                    // for any bound args

1796 1797
                    // For each blank argument, add the type of that argument
                    // to the resulting function type.
1798

1799
                    auto i = 0u;
1800
                    while (i < vec::len[option::t[@ast::expr]](args)) {
1801
                        alt (args.(i)) {
1802 1803
                            case (some(_)) {/* no-op */ }
                            case (none) { arg_tys_1 += [arg_tys.(i)]; }
1804 1805
                        }
                        i += 1u;
G
Graydon Hoare 已提交
1806
                    }
1807 1808 1809
                    t_1 =
                        ty::mk_fn(fcx.ccx.tcx, proto_1, arg_tys_1, rt_1, cf,
                                  constrs);
G
Graydon Hoare 已提交
1810
                }
1811
                case (_) {
1812
                    log_err "LHS of bind expr didn't have a function type?!";
1813 1814
                    fail;
                }
G
Graydon Hoare 已提交
1815
            }
1816
            write::ty_only_fixup(fcx, a.id, t_1);
G
Graydon Hoare 已提交
1817
        }
1818
        case (ast::expr_call(?f, ?args, ?a)) {
1819 1820
            /* here we're kind of hosed, as f can be any expr
             need to restrict it to being an explicit expr_path if we're
1821
            inside a pure function, and need an environment mapping from
1822 1823
            function name onto purity-designation */

1824
            require_pure_call(fcx.ccx, fcx.purity, f, expr.span);
1825
            check_call(fcx, expr.span, f, args);
1826
            // Pull the return type out of the type of the function.
1827

1828
            auto rt_1;
1829
            auto fty = ty::expr_ty(fcx.ccx.tcx, f);
1830
            alt (structure_of(fcx, expr.span, fty)) {
1831 1832
                case (ty::ty_fn(_, _, ?rt, _, _)) { rt_1 = rt; }
                case (ty::ty_native_fn(_, _, ?rt)) { rt_1 = rt; }
1833
                case (_) {
1834
                    log_err "LHS of call expr didn't have a function type?!";
1835 1836
                    fail;
                }
1837
            }
1838
            write::ty_only_fixup(fcx, a.id, rt_1);
1839
        }
1840
        case (ast::expr_self_method(?id, ?a)) {
1841
            auto t = ty::mk_nil(fcx.ccx.tcx);
1842
            let ty::t this_obj_ty;
1843
            let option::t[obj_info] this_obj_info = get_obj_info(fcx.ccx);
L
Lindsey Kuper 已提交
1844
            alt (this_obj_info) {
1845 1846 1847
                case (
                     // If we're inside a current object, grab its type.
                     some(?obj_info)) {
L
Lindsey Kuper 已提交
1848 1849 1850 1851
                    // FIXME: In the case of anonymous objects with methods
                    // containing self-calls, this lookup fails because
                    // obj_info.this_obj is not in the type cache

1852 1853 1854 1855
                    this_obj_ty =
                        ty::lookup_item_type(fcx.ccx.tcx,
                                             obj_info.this_obj)._1;
                }
1856
                case (none) { fail; }
L
Lindsey Kuper 已提交
1857
            }
1858
            // Grab this method's type out of the current object type.
1859

1860
            alt (structure_of(fcx, expr.span, this_obj_ty)) {
1861 1862
                case (ty::ty_obj(?methods)) {
                    for (ty::method method in methods) {
1863
                        if (method.ident == id) {
1864
                            t = ty::method_ty_to_fn_ty(fcx.ccx.tcx, method);
1865 1866 1867 1868 1869
                        }
                    }
                }
                case (_) { fail; }
            }
1870 1871
            write::ty_only_fixup(fcx, a.id, t);
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
1872
        }
1873
        case (ast::expr_spawn(_, _, ?f, ?args, ?a)) {
1874
            check_call(fcx, expr.span, f, args);
1875 1876 1877
            auto fty = expr_ty(fcx.ccx.tcx, f);
            auto ret_ty = ty::ret_ty_of_fn_ty(fcx.ccx.tcx, fty);
            demand::simple(fcx, f.span, ty::mk_nil(fcx.ccx.tcx), ret_ty);
1878 1879
            // FIXME: Other typechecks needed

1880 1881
            auto typ = ty::mk_task(fcx.ccx.tcx);
            write::ty_only_fixup(fcx, a.id, typ);
1882
        }
1883
        case (ast::expr_cast(?e, ?t, ?a)) {
1884 1885
            check_expr(fcx, e);
            auto t_1 = ast_ty_to_ty_crate(fcx.ccx, t);
1886
            // FIXME: there are more forms of cast to support, eventually.
1887 1888 1889

            if (!(type_is_scalar(fcx, expr.span, expr_ty(fcx.ccx.tcx, e)) &&
                      type_is_scalar(fcx, expr.span, t_1))) {
1890
                fcx.ccx.tcx.sess.span_err(expr.span,
1891 1892 1893 1894 1895
                                          "non-scalar cast: " +
                                              ty_to_str(fcx.ccx.tcx,
                                                        expr_ty(fcx.ccx.tcx,
                                                                e)) + " as " +
                                              ty_to_str(fcx.ccx.tcx, t_1));
1896
            }
1897
            write::ty_only_fixup(fcx, a.id, t_1);
1898
        }
1899
        case (ast::expr_vec(?args, ?mut, ?kind, ?a)) {
1900
            let ty::t t;
1901
            if (vec::len[@ast::expr](args) == 0u) {
1902
                t = next_ty_var(fcx);
G
Graydon Hoare 已提交
1903
            } else {
1904 1905
                check_expr(fcx, args.(0));
                t = expr_ty(fcx.ccx.tcx, args.(0));
G
Graydon Hoare 已提交
1906
            }
1907
            for (@ast::expr e in args) {
1908 1909 1910
                check_expr(fcx, e);
                auto expr_t = expr_ty(fcx.ccx.tcx, e);
                demand::simple(fcx, expr.span, t, expr_t);
G
Graydon Hoare 已提交
1911
            }
1912 1913 1914 1915 1916 1917 1918 1919 1920
            auto typ;
            alt (kind) {
                case (ast::sk_rc) {
                    typ = ty::mk_vec(fcx.ccx.tcx, rec(ty=t, mut=mut));
                }
                case (ast::sk_unique) {
                    typ = ty::mk_ivec(fcx.ccx.tcx, rec(ty=t, mut=mut));
                }
            }
1921
            write::ty_only_fixup(fcx, a.id, typ);
G
Graydon Hoare 已提交
1922
        }
1923
        case (ast::expr_tup(?elts, ?a)) {
1924
            let vec[ty::mt] elts_mt = [];
1925
            for (ast::elt e in elts) {
1926 1927
                check_expr(fcx, e.expr);
                auto ety = expr_ty(fcx.ccx.tcx, e.expr);
1928
                elts_mt += [rec(ty=ety, mut=e.mut)];
G
Graydon Hoare 已提交
1929
            }
1930 1931
            auto typ = ty::mk_tup(fcx.ccx.tcx, elts_mt);
            write::ty_only_fixup(fcx, a.id, typ);
G
Graydon Hoare 已提交
1932
        }
1933
        case (ast::expr_rec(?fields, ?base, ?a)) {
1934
            alt (base) {
1935
                case (none) {/* no-op */ }
1936
                case (some(?b_0)) { check_expr(fcx, b_0); }
1937
            }
1938
            let vec[field] fields_t = [];
1939
            for (ast::field f in fields) {
1940 1941
                check_expr(fcx, f.node.expr);
                auto expr_t = expr_ty(fcx.ccx.tcx, f.node.expr);
1942
                auto expr_mt = rec(ty=expr_t, mut=f.node.mut);
1943 1944
                vec::push[field](fields_t,
                                 rec(ident=f.node.ident, mt=expr_mt));
1945
            }
G
Graydon Hoare 已提交
1946
            alt (base) {
1947
                case (none) {
1948 1949
                    auto typ = ty::mk_rec(fcx.ccx.tcx, fields_t);
                    write::ty_only_fixup(fcx, a.id, typ);
G
Graydon Hoare 已提交
1950
                }
1951
                case (some(?bexpr)) {
1952 1953
                    check_expr(fcx, bexpr);
                    auto bexpr_t = expr_ty(fcx.ccx.tcx, bexpr);
1954
                    let vec[field] base_fields = [];
1955
                    alt (structure_of(fcx, expr.span, bexpr_t)) {
1956
                        case (ty::ty_rec(?flds)) { base_fields = flds; }
G
Graydon Hoare 已提交
1957
                        case (_) {
1958 1959 1960
                            fcx.ccx.tcx.sess.span_err(expr.span,
                                                      "record update \
                                                       non-record base");
G
Graydon Hoare 已提交
1961 1962
                        }
                    }
1963
                    write::ty_only_fixup(fcx, a.id, bexpr_t);
1964
                    for (ty::field f in fields_t) {
G
Graydon Hoare 已提交
1965
                        auto found = false;
1966
                        for (ty::field bf in base_fields) {
1967
                            if (str::eq(f.ident, bf.ident)) {
1968
                                demand::simple(fcx, expr.span, f.mt.ty,
1969
                                               bf.mt.ty);
G
Graydon Hoare 已提交
1970 1971 1972 1973
                                found = true;
                            }
                        }
                        if (!found) {
1974 1975 1976 1977
                            fcx.ccx.tcx.sess.span_err(expr.span,
                                                      "unknown field in \
                                                       record update: "
                                                      + f.ident);
G
Graydon Hoare 已提交
1978 1979 1980 1981
                        }
                    }
                }
            }
1982
        }
1983
        case (ast::expr_field(?base, ?field, ?a)) {
1984 1985
            check_expr(fcx, base);
            auto base_t = expr_ty(fcx.ccx.tcx, base);
1986 1987
            base_t = strip_boxes(fcx, expr.span, base_t);
            alt (structure_of(fcx, expr.span, base_t)) {
1988
                case (ty::ty_tup(?args)) {
1989 1990
                    let uint ix =
                        ty::field_num(fcx.ccx.tcx.sess, expr.span, field);
1991
                    if (ix >= vec::len[ty::mt](args)) {
1992
                        fcx.ccx.tcx.sess.span_err(expr.span,
1993
                                                  "bad index on tuple");
G
Graydon Hoare 已提交
1994
                    }
1995
                    write::ty_only_fixup(fcx, a.id, args.(ix).ty);
G
Graydon Hoare 已提交
1996
                }
1997
                case (ty::ty_rec(?fields)) {
1998 1999 2000
                    let uint ix =
                        ty::field_idx(fcx.ccx.tcx.sess, expr.span, field,
                                      fields);
L
Lindsey Kuper 已提交
2001
                    if (ix >= vec::len[ty::field](fields)) {
2002
                        fcx.ccx.tcx.sess.span_err(expr.span,
2003
                                                  "bad index on record");
2004
                    }
2005
                    write::ty_only_fixup(fcx, a.id, fields.(ix).mt.ty);
2006
                }
2007
                case (ty::ty_obj(?methods)) {
2008 2009 2010
                    let uint ix =
                        ty::method_idx(fcx.ccx.tcx.sess, expr.span, field,
                                       methods);
L
Lindsey Kuper 已提交
2011
                    if (ix >= vec::len[ty::method](methods)) {
2012
                        fcx.ccx.tcx.sess.span_err(expr.span,
2013
                                                  "bad index on obj");
G
Graydon Hoare 已提交
2014 2015
                    }
                    auto meth = methods.(ix);
2016 2017 2018
                    auto t =
                        ty::mk_fn(fcx.ccx.tcx, meth.proto, meth.inputs,
                                  meth.output, meth.cf, meth.constrs);
2019
                    write::ty_only_fixup(fcx, a.id, t);
G
Graydon Hoare 已提交
2020
                }
G
Graydon Hoare 已提交
2021
                case (_) {
2022
                    fcx.ccx.tcx.sess.span_unimpl(expr.span,
2023 2024 2025 2026
                                                 "base type for expr_field \
                                                  in typeck::check_expr: "
                                                 + ty_to_str(fcx.ccx.tcx,
                                                             base_t));
G
Graydon Hoare 已提交
2027 2028 2029
                }
            }
        }
2030
        case (ast::expr_index(?base, ?idx, ?a)) {
2031 2032
            check_expr(fcx, base);
            auto base_t = expr_ty(fcx.ccx.tcx, base);
2033
            base_t = strip_boxes(fcx, expr.span, base_t);
2034 2035
            check_expr(fcx, idx);
            auto idx_t = expr_ty(fcx.ccx.tcx, idx);
2036 2037
            if (!type_is_integral(fcx, idx.span, idx_t)) {
                fcx.ccx.tcx.sess.span_err(idx.span,
2038 2039 2040
                                          "mismatched types: expected \
                                           integer but found "
                                          + ty_to_str(fcx.ccx.tcx, idx_t));
2041
            }
2042
            alt (structure_of(fcx, expr.span, base_t)) {
2043
                case (ty::ty_vec(?mt)) {
2044 2045 2046
                    write::ty_only_fixup(fcx, a.id, mt.ty);
                }
                case (ty::ty_ivec(?mt)) {
2047
                    write::ty_only_fixup(fcx, a.id, mt.ty);
G
Graydon Hoare 已提交
2048
                }
2049
                case (ty::ty_str) {
2050 2051 2052 2053
                    auto typ = ty::mk_mach(fcx.ccx.tcx, common::ty_u8);
                    write::ty_only_fixup(fcx, a.id, typ);
                }
                case (ty::ty_istr) {
2054 2055
                    auto typ = ty::mk_mach(fcx.ccx.tcx, common::ty_u8);
                    write::ty_only_fixup(fcx, a.id, typ);
G
Graydon Hoare 已提交
2056 2057
                }
                case (_) {
2058 2059 2060 2061
                    fcx.ccx.tcx.sess.span_err(expr.span,
                                              "vector-indexing bad type: " +
                                                  ty_to_str(fcx.ccx.tcx,
                                                            base_t));
G
Graydon Hoare 已提交
2062 2063 2064
                }
            }
        }
2065
        case (ast::expr_port(?a)) {
2066 2067 2068
            auto t = next_ty_var(fcx);
            auto pt = ty::mk_port(fcx.ccx.tcx, t);
            write::ty_only_fixup(fcx, a.id, pt);
2069
        }
2070
        case (ast::expr_chan(?x, ?a)) {
2071 2072
            check_expr(fcx, x);
            auto port_t = expr_ty(fcx.ccx.tcx, x);
2073
            alt (structure_of(fcx, expr.span, port_t)) {
2074
                case (ty::ty_port(?subtype)) {
2075 2076
                    auto ct = ty::mk_chan(fcx.ccx.tcx, subtype);
                    write::ty_only_fixup(fcx, a.id, ct);
2077 2078
                }
                case (_) {
2079
                    fcx.ccx.tcx.sess.span_err(expr.span,
2080 2081 2082
                                              "bad port type: " +
                                                  ty_to_str(fcx.ccx.tcx,
                                                            port_t));
2083 2084 2085
                }
            }
        }
L
Lindsey Kuper 已提交
2086 2087 2088 2089 2090
        case (ast::expr_anon_obj(?anon_obj, ?tps, ?obj_def_ids, ?a)) {
            // TODO: We probably need to do more work here to be able to
            // handle additional methods that use 'self'

            // We're entering an object, so gather up the info we need.
2091

L
Lindsey Kuper 已提交
2092 2093
            let vec[ast::obj_field] fields = [];
            alt (anon_obj.fields) {
2094 2095
                case (none) { }
                case (some(?v)) { fields = v; }
L
Lindsey Kuper 已提交
2096 2097
            }
            let ast::def_id di = obj_def_ids.ty;
2098
            vec::push[obj_info](fcx.ccx.obj_infos,
L
Lindsey Kuper 已提交
2099 2100
                                rec(obj_fields=fields, this_obj=di));
            // Typecheck 'with_obj', if it exists.
2101

L
Lindsey Kuper 已提交
2102 2103
            let option::t[@ast::expr] with_obj = none[@ast::expr];
            alt (anon_obj.with_obj) {
2104 2105
                case (none) { }
                case (some(?e)) {
2106
                    // This had better have object type.  TODO: report an
L
Lindsey Kuper 已提交
2107 2108
                    // error if the user is trying to extend a non-object
                    // with_obj.
2109

2110
                    check_expr(fcx, e);
L
Lindsey Kuper 已提交
2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122
                }
            }
            // 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(@crate_ctxt ccx, &ast::arg a) -> ty::arg {
                auto ty_mode = ast_mode_to_mode(a.mode);
                ret rec(mode=ty_mode, ty=ast_ty_to_ty_crate(ccx, a.ty));
            }
            fn ty_of_method(@crate_ctxt ccx, &@ast::method m) -> ty::method {
                auto convert = bind ast_ty_to_ty_crate(ccx, _);
                auto f = bind ty_of_arg(ccx, _);
2123 2124
                auto inputs =
                    vec::map[ast::arg, arg](f, m.node.meth.decl.inputs);
L
Lindsey Kuper 已提交
2125
                auto output = convert(m.node.meth.decl.output);
2126 2127 2128 2129 2130
                ret rec(proto=m.node.meth.proto,
                        ident=m.node.ident,
                        inputs=inputs,
                        output=output,
                        cf=m.node.meth.decl.cf,
2131
                        constrs=m.node.meth.decl.constraints);
L
Lindsey Kuper 已提交
2132 2133
            }
            fn get_anon_obj_method_types(@crate_ctxt ccx,
2134 2135 2136 2137 2138
                                         &ast::anon_obj anon_obj) ->
               vec[ty::method] {
                ret vec::map[@ast::method,
                             method](bind ty_of_method(ccx, _),
                                     anon_obj.methods);
L
Lindsey Kuper 已提交
2139
            }
2140
            auto method_types = get_anon_obj_method_types(fcx.ccx, anon_obj);
2141
            auto ot = ty::mk_obj(fcx.ccx.tcx, ty::sort_methods(method_types));
2142
            write::ty_only_fixup(fcx, a.id, ot);
2143 2144
            // Write the methods into the node type table.  (This happens in
            // collect::convert for regular objects.)
2145

2146 2147 2148 2149 2150 2151 2152 2153
            auto i = 0u;
            while (i < vec::len[@ast::method](anon_obj.methods)) {
                write::ty_only(fcx.ccx.tcx, anon_obj.methods.(i).node.ann.id,
                               ty::method_ty_to_fn_ty(fcx.ccx.tcx,
                                                      method_types.(i)));
                i += 1u;
            }
            // Typecheck the methods.
2154

2155 2156 2157 2158
            for (@ast::method method in anon_obj.methods) {
                check_method(fcx.ccx, method);
            }
            auto t = next_ty_var(fcx);
L
Lindsey Kuper 已提交
2159
            // Now remove the info from the stack.
2160

2161
            vec::pop[obj_info](fcx.ccx.obj_infos);
L
Lindsey Kuper 已提交
2162
        }
2163
        case (_) {
2164
            fcx.ccx.tcx.sess.unimpl("expr type in typeck::check_expr");
2165
        }
2166 2167 2168
    }
}

2169 2170 2171 2172 2173 2174 2175 2176
fn next_ty_var_id(@fn_ctxt fcx) -> int {
    auto id = fcx.next_var_id;
    fcx.next_var_id += 1;
    ret id;
}

fn next_ty_var(&@fn_ctxt fcx) -> ty::t {
    ret ty::mk_var(fcx.ccx.tcx, next_ty_var_id(fcx));
2177 2178
}

2179 2180 2181 2182
fn get_obj_info(&@crate_ctxt ccx) -> option::t[obj_info] {
    ret vec::last[obj_info](ccx.obj_infos);
}

2183
fn check_decl_initializer(&@fn_ctxt fcx, &ast::def_id lid,
2184
                          &ast::initializer init) {
2185 2186
    check_expr(fcx, init.expr);
    auto lty = ty::mk_var(fcx.ccx.tcx, fcx.locals.get(lid));
2187 2188
    alt (init.op) {
        case (ast::init_assign) {
2189 2190
            demand::simple(fcx, init.expr.span, lty,
                           expr_ty(fcx.ccx.tcx, init.expr));
2191
        }
2192
        case (ast::init_move) {
2193 2194
            demand::simple(fcx, init.expr.span, lty,
                           expr_ty(fcx.ccx.tcx, init.expr));
2195
        }
2196
        case (ast::init_recv) {
2197
            auto port_ty = ty::mk_port(fcx.ccx.tcx, lty);
2198 2199
            demand::simple(fcx, init.expr.span, port_ty,
                           expr_ty(fcx.ccx.tcx, init.expr));
2200 2201 2202 2203
        }
    }
}

2204 2205 2206 2207
fn check_decl_local(&@fn_ctxt fcx, &@ast::local_ local) -> @ast::local_ {
    auto a_res = local.ann;
    alt (fcx.locals.find(local.id)) {
        case (none) {
2208 2209
            fcx.ccx.tcx.sess.bug("check_decl_local: local id not found " +
                                     local.ident);
2210 2211 2212
        }
        case (some(?i)) {
            auto t = ty::mk_var(fcx.ccx.tcx, i);
2213
            write::ty_only_fixup(fcx, a_res.id, t);
2214
            auto initopt = local.init;
2215
            alt (local.init) {
2216
                case (some(?init)) {
2217
                    check_decl_initializer(fcx, local.id, init);
2218
                }
2219
                case (_) {/* fall through */ }
2220
            }
2221
            ret @rec(init=initopt, ann=a_res with *local);
2222 2223 2224 2225
        }
    }
}

2226 2227
fn check_stmt(&@fn_ctxt fcx, &@ast::stmt stmt) {
    auto node_id;
2228
    alt (stmt.node) {
2229
        case (ast::stmt_decl(?decl, ?a)) {
2230
            node_id = a.id;
2231
            alt (decl.node) {
2232
                case (ast::decl_local(?l)) { check_decl_local(fcx, l); }
2233
                case (ast::decl_item(_)) {/* ignore for now */ }
2234 2235
            }
        }
2236
        case (ast::stmt_expr(?expr, ?a)) {
2237
            node_id = a.id;
2238
            check_expr(fcx, expr);
2239 2240
        }
    }
2241
    write::nil_ty(fcx.ccx.tcx, node_id);
2242 2243
}

2244 2245
fn check_block(&@fn_ctxt fcx, &ast::block block) {
    for (@ast::stmt s in block.node.stmts) { check_stmt(fcx, s); }
2246
    alt (block.node.expr) {
2247
        case (none) { write::nil_ty(fcx.ccx.tcx, block.node.a.id); }
2248
        case (some(?e)) {
2249 2250 2251
            check_expr(fcx, e);
            auto ety = expr_ty(fcx.ccx.tcx, e);
            write::ty_only_fixup(fcx, block.node.a.id, ety);
2252 2253
        }
    }
2254 2255
}

2256
fn check_const(&@crate_ctxt ccx, &span sp, &@ast::expr e, &ast::ann ann) {
2257 2258
    // FIXME: this is kinda a kludge; we manufacture a fake function context
    // and statement context for checking the initializer expression.
2259

2260
    auto rty = ann_to_type(ccx.tcx, ann);
2261
    let vec[uint] fixups = [];
2262 2263 2264 2265 2266 2267 2268 2269 2270
    let @fn_ctxt fcx =
        @rec(ret_ty=rty,
             purity=ast::pure_fn,
             var_bindings=ty::unify::mk_var_bindings(),
             locals=new_def_hash[int](),
             local_names=new_def_hash[ast::ident](),
             mutable next_var_id=0,
             mutable fixups=fixups,
             ccx=ccx);
2271
    check_expr(fcx, e);
2272 2273
}

2274
fn check_fn(&@crate_ctxt ccx, &ast::fn_decl decl, ast::proto proto,
2275 2276 2277
            &ast::block body, &ast::ann ann) {
    auto gather_result = gather_locals(ccx, decl, body, ann);
    let vec[uint] fixups = [];
2278 2279 2280 2281 2282 2283 2284 2285 2286
    let @fn_ctxt fcx =
        @rec(ret_ty=ast_ty_to_ty_crate(ccx, decl.output),
             purity=decl.purity,
             var_bindings=gather_result.var_bindings,
             locals=gather_result.locals,
             local_names=gather_result.local_names,
             mutable next_var_id=gather_result.next_var_id,
             mutable fixups=fixups,
             ccx=ccx);
2287
    // TODO: Make sure the type of the block agrees with the function type.
2288

2289
    check_block(fcx, body);
2290
    alt (decl.purity) {
2291
        case (ast::pure_fn) {
2292

2293 2294
            // per the previous comment, this just checks that the declared
            // type is bool, and trusts that that's the actual return type.
2295
            if (!ty::type_is_bool(ccx.tcx, fcx.ret_ty)) {
2296 2297
                ccx.tcx.sess.span_err(body.span,
                                      "Non-boolean return type in pred");
2298 2299
            }
        }
2300
        case (_) { }
2301
    }
2302
    writeback::resolve_type_vars_in_block(fcx, body);
2303
}
2304

2305
fn check_method(&@crate_ctxt ccx, &@ast::method method) {
2306 2307
    auto m = method.node.meth;
    check_fn(ccx, m.decl, m.proto, m.body, method.node.ann);
2308 2309
}

2310 2311
fn check_item(@crate_ctxt ccx, &@ast::item it) {
    alt (it.node) {
2312
        case (ast::item_const(_, _, ?e, _, _, ?a)) {
2313 2314
            check_const(ccx, it.span, e, a);
        }
2315
        case (ast::item_fn(_, ?f, _, _, _, ?a)) {
2316
            check_fn(ccx, f.decl, f.proto, f.body, a);
2317
        }
2318
        case (ast::item_obj(_, ?ob, _, _, ?obj_def_ids, _)) {
2319
            // We're entering an object, so gather up the info we need.
2320

2321
            let ast::def_id di = obj_def_ids.ty;
2322 2323 2324
            vec::push[obj_info](ccx.obj_infos,
                                rec(obj_fields=ob.fields, this_obj=di));
            // Typecheck the methods.
2325

2326 2327 2328 2329 2330
            for (@ast::method method in ob.methods) {
                check_method(ccx, method);
            }
            option::may[@ast::method](bind check_method(ccx, _), ob.dtor);
            // Now remove the info from the stack.
2331

2332
            vec::pop[obj_info](ccx.obj_infos);
2333
        }
2334
        case (_) {/* nothing to do */ }
2335 2336 2337
    }
}

2338 2339
fn mk_fn_purity_table(&@ast::crate crate) -> @fn_purity_table {
    auto res = @new_def_hash[ast::purity]();
2340
    fn do_one(@fn_purity_table t, &@ast::item i) {
2341
        alt (i.node) {
2342
            case (ast::item_fn(_, ?f, _, _, ?d_id, _)) {
2343 2344
                t.insert(d_id, f.decl.purity);
            }
2345
            case (_) { }
2346 2347
        }
    }
2348
    auto do_one_fn = bind do_one(res, _);
2349
    auto v = walk::default_visitor();
2350
    auto add_fn_entry_visitor = rec(visit_item_post=do_one_fn with v);
2351
    walk::walk_crate(add_fn_entry_visitor, *crate);
2352 2353
    ret res;
}
2354

2355
fn check_crate(&ty::ctxt tcx, &@ast::crate crate) {
2356
    collect::collect_item_types(tcx, crate);
2357
    let vec[obj_info] obj_infos = [];
2358
    auto fpt = mk_fn_purity_table(crate); // use a variation on collect
2359

2360 2361 2362 2363 2364
    auto ccx =
        @rec(mutable obj_infos=obj_infos, fn_purity_table=fpt, tcx=tcx);
    auto visit =
        rec(visit_item_pre=bind check_item(ccx, _)
            with walk::default_visitor());
2365
    walk::walk_crate(visit, *crate);
2366
}
2367 2368 2369 2370 2371 2372 2373
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
2374
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
2375 2376
// End:
//