typeck.rs 101.9 KB
Newer Older
1

2 3 4 5 6 7
import syntax::ast;
import ast::mutability;
import ast::local_def;
import ast::path_to_str;
import ast::respan;
import syntax::walk;
8
import metadata::decoder;
9 10
import driver::session;
import util::common;
11
import syntax::codemap::span;
12
import std::map::new_int_hash;
13 14 15
import util::common::new_def_hash;
import util::common::log_expr_err;
import middle::ty;
16
import middle::ty::node_id_to_type;
17 18 19 20 21 22 23 24
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;
25
import middle::ty::node_type_table;
26
import middle::ty::pat_ty;
27
import middle::ty::ty_param_substs_opt_and_ty;
28
import util::ppaux::ty_to_str;
29 30
import middle::ty::ty_param_count_and_ty;
import middle::ty::ty_nil;
31 32
import middle::ty::unify::ures_ok;
import middle::ty::unify::ures_err;
33 34 35
import middle::ty::unify::fixup_result;
import middle::ty::unify::fix_ok;
import middle::ty::unify::fix_err;
36
import std::int;
37
import std::ivec;
38
import std::str;
39
import std::ufind;
40 41
import std::uint;
import std::vec;
42 43 44 45 46 47
import std::map;
import std::map::hashmap;
import std::option;
import std::option::none;
import std::option::some;
import std::option::from_maybe;
48
import std::smallintmap;
49
import middle::tstate::ann::ts_ann;
50

B
Brian Anderson 已提交
51 52
export check_crate;

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

55
type obj_info = rec(vec[ast::obj_field] obj_fields, ast::node_id this_obj);
56

57 58 59 60 61 62 63 64
type crate_ctxt =
    rec(mutable vec[obj_info] obj_infos,
        ty::ctxt tcx);

type fn_ctxt =
    rec(ty::t ret_ty,
        ast::purity purity,
        @ty::unify::var_bindings var_bindings,
65 66
        hashmap[ast::node_id, int] locals,
        hashmap[ast::node_id, ast::ident] local_names,
67
        mutable int next_var_id,
68
        mutable vec[ast::node_id] fixups,
69
        @crate_ctxt ccx);
70

71

72
// Used for ast_ty_to_ty() below.
73
type ty_getter = fn(&ast::def_id) -> ty::ty_param_count_and_ty ;
74

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
fn lookup_local(&@fn_ctxt fcx, &span sp, ast::node_id id) -> int {
    alt (fcx.locals.find(id)) {
        case (some(?x)) { x }
        case (_) {
            fcx.ccx.tcx.sess.span_fatal(sp, "internal error looking up a \
              local var")
        }
    }
}

fn lookup_def(&@fn_ctxt fcx, &span sp, ast::node_id id) -> ast::def {
    alt (fcx.ccx.tcx.def_map.find(id)) {
        case (some(?x)) { x }
        case (_) {
            fcx.ccx.tcx.sess.span_fatal(sp, "internal error looking up \
              a definition")
        }
    }
}
94

95
// Returns the type parameter count and the type for the given definition.
96 97
fn ty_param_count_and_ty_for_def(&@fn_ctxt fcx, &span sp, &ast::def defn) ->
   ty_param_count_and_ty {
98
    alt (defn) {
99
        case (ast::def_arg(?id)) {
100
            assert (fcx.locals.contains_key(id._1));
101 102
            auto typ = ty::mk_var(fcx.ccx.tcx, 
                                  lookup_local(fcx, sp, id._1));
103
            ret tup(0u, typ);
104
        }
105
        case (ast::def_local(?id)) {
106
            assert (fcx.locals.contains_key(id._1));
107
            auto typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id._1));
108
            ret tup(0u, typ);
109
        }
110
        case (ast::def_obj_field(?id)) {
111
            assert (fcx.locals.contains_key(id._1));
112
            auto typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id._1));
113
            ret tup(0u, typ);
114
        }
115 116 117
        case (ast::def_fn(?id, _)) {
            ret ty::lookup_item_type(fcx.ccx.tcx, id);
        }
118
        case (ast::def_native_fn(?id)) {
119
            ret ty::lookup_item_type(fcx.ccx.tcx, id);
120
        }
121
        case (ast::def_const(?id)) {
122
            ret ty::lookup_item_type(fcx.ccx.tcx, id);
123
        }
124
        case (ast::def_variant(_, ?vid)) {
125
            ret ty::lookup_item_type(fcx.ccx.tcx, vid);
126
        }
127
        case (ast::def_binding(?id)) {
128
            assert (fcx.locals.contains_key(id._1));
129
            auto typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id._1));
130
            ret tup(0u, typ);
131
        }
132
        case (ast::def_mod(_)) {
133
            // Hopefully part of a path.
134
            // TODO: return a type that's more poisonous, perhaps?
135

136
            ret tup(0u, ty::mk_nil(fcx.ccx.tcx));
137
        }
138
        case (ast::def_ty(_)) {
139
            fcx.ccx.tcx.sess.span_fatal(sp, "expected value but found type");
140
        }
141 142
        case (_) {
            // FIXME: handle other names.
143

144
            fcx.ccx.tcx.sess.unimpl("definition variant");
145 146
        }
    }
147 148
}

149

150
// Instantiates the given path, which must refer to an item with the given
151
// number of type parameters and type.
152
fn instantiate_path(&@fn_ctxt fcx, &ast::path pth, &ty_param_count_and_ty tpt,
153
                    &span sp) -> ty_param_substs_opt_and_ty {
154
    auto ty_param_count = tpt._0;
155
    auto bind_result =
156
        bind_params_in_type(sp, fcx.ccx.tcx, bind next_ty_var_id(fcx), tpt._1,
157
                            ty_param_count);
158
    auto ty_param_vars = bind_result._0;
159
    auto ty_substs_opt;
160
    auto ty_substs_len = vec::len[@ast::ty](pth.node.types);
161
    if (ty_substs_len > 0u) {
162
        let ty::t[] ty_substs = ~[];
163 164
        auto i = 0u;
        while (i < ty_substs_len) {
165 166
            // TODO: Report an error if the number of type params in the item
            // and the supplied number of type params don't match.
167

168
            auto ty_var = ty::mk_var(fcx.ccx.tcx, ty_param_vars.(i));
169
            auto ty_subst = ast_ty_to_ty_crate(fcx.ccx, pth.node.types.(i));
170
            auto res_ty = demand::simple(fcx, pth.span, ty_var, ty_subst);
171
            ty_substs += ~[res_ty];
172 173
            i += 1u;
        }
174
        ty_substs_opt = some[ty::t[]](ty_substs);
175
        if (ty_param_count == 0u) {
176
            fcx.ccx.tcx.sess.span_fatal(sp,
177 178
                                      "this item does not take type " +
                                          "parameters");
179
            fail;
180 181
        }
    } else {
182
        // We will acquire the type parameters through unification.
183

184
        let ty::t[] ty_substs = ~[];
185 186
        auto i = 0u;
        while (i < ty_param_count) {
187
            ty_substs += ~[ty::mk_var(fcx.ccx.tcx, ty_param_vars.(i))];
188
            i += 1u;
189
        }
190
        ty_substs_opt = some[ty::t[]](ty_substs);
191
    }
192
    ret tup(ty_substs_opt, tpt._1);
193 194
}

195
fn ast_mode_to_mode(ast::mode mode) -> ty::mode {
196 197
    auto ty_mode;
    alt (mode) {
198
        case (ast::val) { ty_mode = mo_val; }
199
        case (ast::alias(?mut)) { ty_mode = mo_alias(mut); }
200 201 202 203
    }
    ret ty_mode;
}

204 205 206

// Type tests
fn structurally_resolved_type(&@fn_ctxt fcx, &span sp, ty::t typ) -> ty::t {
207 208
    auto r =
        ty::unify::resolve_type_structure(fcx.ccx.tcx, fcx.var_bindings, typ);
209
    alt (r) {
210
        case (fix_ok(?typ_s)) { ret typ_s; }
211
        case (fix_err(_)) {
212
            fcx.ccx.tcx.sess.span_fatal(sp,
213 214
                                      "the type of this value must be " +
                                          "known in this context");
215 216 217 218
        }
    }
}

219

220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
// 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);
}


236 237
// Parses the programmer's textual representation of a type into our internal
// notion of a type. `getter` is a function that returns the type
238 239
// corresponding to a definition ID:
fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
240
    alt (tcx.ast_ty_to_ty_cache.find(ast_ty)) {
241
        case (some[option::t[ty::t]](some[ty::t](?ty))) { ret ty; }
242
        case (some[option::t[ty::t]](none)) {
243
            tcx.sess.span_fatal(ast_ty.span,
244 245 246
                              "illegal recursive type " +
                              "(insert a tag in the cycle, " +
                              "if this is desired)");
247
        }
248 249 250
        case (none[option::t[ty::t]]) { }
    } /* go on */

251
    tcx.ast_ty_to_ty_cache.insert(ast_ty, none[ty::t]);
252 253
    fn ast_arg_to_arg(&ty::ctxt tcx, &ty_getter getter, &ast::ty_arg arg) ->
       rec(ty::mode mode, ty::t ty) {
254 255
        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));
256
    }
257
    fn ast_mt_to_mt(&ty::ctxt tcx, &ty_getter getter, &ast::mt mt) -> ty::mt {
258
        ret rec(ty=ast_ty_to_ty(tcx, getter, mt.ty), mut=mt.mut);
259
    }
260
    fn instantiate(&ty::ctxt tcx, &span sp, &ty_getter getter,
261
                   &ast::def_id id, &vec[@ast::ty] args) -> ty::t {
262 263
        // TODO: maybe record cname chains so we can do
        // "foo = int" like OCaml?
264

265 266
        auto params_opt_and_ty = getter(id);
        if (params_opt_and_ty._0 == 0u) { ret params_opt_and_ty._1; }
267 268
        // The typedef is type-parametric. Do the type substitution.
        //
269

270
        let ty::t[] param_bindings = ~[];
271
        for (@ast::ty ast_ty in args) {
272
            param_bindings += ~[ast_ty_to_ty(tcx, getter, ast_ty)];
273
        }
274
        if (ivec::len(param_bindings) !=
275
                ty::count_ty_params(tcx, params_opt_and_ty._1)) {
276
            tcx.sess.span_fatal(sp,
277 278
                              "Wrong number of type arguments for a" +
                                  " polymorphic tag");
279
        }
280 281
        auto typ =
            ty::substitute_type_params(tcx, param_bindings,
282 283
                                       params_opt_and_ty._1);
        ret typ;
284
    }
285
    auto typ;
286 287
    auto cname = none[str];
    alt (ast_ty.node) {
288 289 290 291 292 293
        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); }
294
        case (ast::ty_machine(?tm)) { typ = ty::mk_mach(tcx, tm); }
295 296 297
        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); }
298 299
        case (ast::ty_box(?mt)) {
            typ = ty::mk_box(tcx, ast_mt_to_mt(tcx, getter, mt));
300
        }
301 302
        case (ast::ty_vec(?mt)) {
            typ = ty::mk_vec(tcx, ast_mt_to_mt(tcx, getter, mt));
303
        }
304 305 306
        case (ast::ty_ivec(?mt)) {
            typ = ty::mk_ivec(tcx, ast_mt_to_mt(tcx, getter, mt));
        }
307 308 309
        case (ast::ty_ptr(?mt)) {
            typ = ty::mk_ptr(tcx, ast_mt_to_mt(tcx, getter, mt));
        }
310
        case (ast::ty_task) { typ = ty::mk_task(tcx); }
311 312
        case (ast::ty_port(?t)) {
            typ = ty::mk_port(tcx, ast_ty_to_ty(tcx, getter, t));
313
        }
314 315
        case (ast::ty_chan(?t)) {
            typ = ty::mk_chan(tcx, ast_ty_to_ty(tcx, getter, t));
316
        }
317
        case (ast::ty_tup(?fields)) {
318 319
            let ty::mt[] flds = ~[];
            ivec::reserve(flds, vec::len(fields));
320
            for (ast::mt field in fields) {
321
                flds += ~[ast_mt_to_mt(tcx, getter, field)];
322
            }
323
            typ = ty::mk_tup(tcx, flds);
324
        }
325
        case (ast::ty_rec(?fields)) {
326
            let field[] flds = ~[];
327
            for (ast::ty_field f in fields) {
328
                auto tm = ast_mt_to_mt(tcx, getter, f.node.mt);
329
                flds += ~[rec(ident=f.node.ident, mt=tm)];
330
            }
331
            typ = ty::mk_rec(tcx, flds);
332
        }
333
        case (ast::ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
334 335 336 337
            auto i = ~[];
            for (ast::ty_arg ta in inputs) {
                i += ~[ast_arg_to_arg(tcx, getter, ta)];
            }
338
            auto out_ty = ast_ty_to_ty(tcx, getter, output);
339

340 341 342 343
            auto out_constrs = ~[];
            for (@ast::constr constr in constrs) {
                out_constrs += ~[ast_constr_to_constr(tcx, constr)];
            }
344
            typ = ty::mk_fn(tcx, proto, i, out_ty, cf, out_constrs);
345
        }
346
        case (ast::ty_path(?path, ?id)) {
347 348
            alt (tcx.def_map.find(id)) {
                case (some(ast::def_ty(?id))) {
349 350 351
                    typ =
                        instantiate(tcx, ast_ty.span, getter, id,
                                    path.node.types);
352
                }
353 354 355 356 357
                case (some(ast::def_native_ty(?id))) { typ = getter(id)._1; }
                case (some(ast::def_ty_arg(?id))) {
                    typ = ty::mk_param(tcx, id);
                }
                case (some(_)) {
358
                    tcx.sess.span_fatal(ast_ty.span,
359
                                      "found type name used as a variable");
360
                }
361 362 363 364
                case (_) {
                    tcx.sess.span_fatal(ast_ty.span,
                                       "internal error in instantiate");
                }
365 366 367
            }
            cname = some(path_to_str(path));
        }
368
        case (ast::ty_obj(?meths)) {
369
            let ty::method[] tmeths = ~[];
370
            for (ast::ty_method m in meths) {
371 372 373 374
                auto ins = ~[];
                for (ast::ty_arg ta in m.node.inputs) {
                    ins += ~[ast_arg_to_arg(tcx, getter, ta)];
                }
375
                auto out = ast_ty_to_ty(tcx, getter, m.node.output);
376

377 378 379 380
                auto out_constrs = ~[];
                for (@ast::constr constr in m.node.constrs) {
                    out_constrs += ~[ast_constr_to_constr(tcx, constr)];
                }
381
                let ty::method new_m =
382 383 384 385 386
                    rec(proto=m.node.proto,
                        ident=m.node.ident,
                        inputs=ins,
                        output=out,
                        cf=m.node.cf,
387
                        constrs=out_constrs);
388
                tmeths += ~[new_m];
389
            }
390
            typ = ty::mk_obj(tcx, ty::sort_methods(tmeths));
391
        }
392
    }
393
    alt (cname) {
394 395
        case (none) {/* no-op */ }
        case (some(?cname_str)) { typ = ty::rename(tcx, typ, cname_str); }
396
    }
397
    tcx.ast_ty_to_ty_cache.insert(ast_ty, some(typ));
398
    ret typ;
399 400
}

401

402
// A convenience function to use a crate_ctxt to resolve names for
403
// ast_ty_to_ty.
404 405
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 {
406
        ret ty::lookup_item_type(ccx.tcx, id);
407
    }
408
    auto f = bind getter(ccx, _);
409
    ret ast_ty_to_ty(ccx.tcx, f, ast_ty);
410 411
}

412

413 414
// Functions that write types into the node type table.
mod write {
415
    fn inner(&node_type_table ntt, ast::node_id node_id,
416
             &ty_param_substs_opt_and_ty tpot) {
417
        smallintmap::insert(*ntt, node_id as uint, tpot);
418
    }
419

420
    // Writes a type parameter count and type pair into the node type table.
421 422
    fn ty(&ty::ctxt tcx, ast::node_id node_id,
          &ty_param_substs_opt_and_ty tpot) {
423
        assert (!ty::type_contains_vars(tcx, tpot._1));
424
        ret inner(tcx.node_types, node_id, tpot);
425 426 427 428 429
    }

    // 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.
430
    fn ty_fixup(@fn_ctxt fcx, ast::node_id node_id,
431
                &ty_param_substs_opt_and_ty tpot) {
432 433 434
        inner(fcx.ccx.tcx.node_types, node_id, tpot);
        if (ty::type_contains_vars(fcx.ccx.tcx, tpot._1)) {
            fcx.fixups += [node_id];
435 436
        }
    }
437

438
    // Writes a type with no type parameters into the node type table.
439
    fn ty_only(&ty::ctxt tcx, ast::node_id node_id, ty::t typ) {
440
        ret ty(tcx, node_id, tup(none[ty::t[]], typ));
441 442 443 444
    }

    // Writes a type with no type parameters into the node type table. This
    // function allows for the possibility of type variables.
445
    fn ty_only_fixup(@fn_ctxt fcx, ast::node_id node_id, ty::t typ) {
446
        ret ty_fixup(fcx, node_id, tup(none[ty::t[]], typ));
447 448 449
    }

    // Writes a nil type into the node type table.
450
    fn nil_ty(&ty::ctxt tcx, ast::node_id node_id) {
451
        ret ty(tcx, node_id, tup(none[ty::t[]], ty::mk_nil(tcx)));
452 453 454
    }

    // Writes the bottom type into the node type table.
455
    fn bot_ty(&ty::ctxt tcx, ast::node_id node_id) {
456
        ret ty(tcx, node_id, tup(none[ty::t[]], ty::mk_bot(tcx)));
457
    }
458 459
}

460

461 462
// Item collection - a pair of bootstrap passes:
//
463
// (1) Collect the IDs of all type items (typedefs) and store them in a table.
464
//
465 466 467
// (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.
468 469 470
//
// We then annotate the AST with the resulting types and return the annotated
// AST, along with a table mapping item IDs to their types.
471 472 473 474
//
// 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.
475
mod collect {
476
    type ctxt = rec(ty::ctxt tcx);
477

478 479
    fn mk_ty_params(&@ctxt cx, uint n) -> ty::t[] {
        auto tps = ~[];
480 481
        auto i = 0u;
        while (i < n) {
482
            tps += ~[ty::mk_param(cx.tcx, i)];
483 484 485 486
            i += 1u;
        }
        ret tps;
    }
487 488 489 490 491
    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 {
492 493
        auto input_tys = ~[];
        for (ast::arg a in decl.inputs) { input_tys += ~[ty_of_arg(a)]; }
494
        auto output_ty = convert(decl.output);
495

496 497 498 499
        auto out_constrs = ~[];
        for (@ast::constr constr in decl.constraints) {
            out_constrs += ~[ast_constr_to_constr(cx.tcx, constr)];
        }
500 501
        auto t_fn =
            ty::mk_fn(cx.tcx, proto, input_tys, output_ty, decl.cf,
502
                      out_constrs);
503
        auto ty_param_count = vec::len[ast::ty_param](ty_params);
504
        auto tpt = tup(ty_param_count, t_fn);
505 506
        alt (def_id) {
            case (some(?did)) { cx.tcx.tcache.insert(did, tpt); }
507
            case (_) { }
508
        }
509 510
        ret tpt;
    }
511 512 513
    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,
514
                            &vec[ast::ty_param] ty_params,
515 516
                            &ast::def_id def_id) ->
       ty::ty_param_count_and_ty {
517 518
        auto input_tys = ~[];
        for (ast::arg a in decl.inputs) { input_tys += ~[ty_of_arg(a)]; }
519
        auto output_ty = convert(decl.output);
520

521
        auto t_fn = ty::mk_native_fn(cx.tcx, abi, input_tys, output_ty);
522
        auto ty_param_count = vec::len[ast::ty_param](ty_params);
523
        auto tpt = tup(ty_param_count, t_fn);
524
        cx.tcx.tcache.insert(def_id, tpt);
525 526
        ret tpt;
    }
527
    fn getter(@ctxt cx, &ast::def_id id) -> ty::ty_param_count_and_ty {
528
        if (id._0 != ast::local_crate) {
529
            // This is a type we need to load in from the crate reader.
530
            ret decoder::get_type(cx.tcx, id);
531
        }
532
        auto it = cx.tcx.items.find(id._1);
533
        auto tpt;
534
        alt (it) {
535 536 537 538
            case (some(ast_map::node_item(?item))) {
                tpt = ty_of_item(cx, item);
            }
            case (some(ast_map::node_native_item(?native_item))) {
539 540
                tpt = ty_of_native_item(cx, native_item,
                                        ast::native_abi_cdecl);
541
            }
542 543
            case (_) {
                cx.tcx.sess.fatal("internal error " +
544
                                  std::int::str(id._1));
545
            }
546
        }
547
        ret tpt;
548
    }
L
Lindsey Kuper 已提交
549
    fn ty_of_arg(@ctxt cx, &ast::arg a) -> ty::arg {
550
        auto ty_mode = ast_mode_to_mode(a.mode);
551
        auto f = bind getter(cx, _);
552 553 554 555
        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) {
556
                    cx.tcx.sess.span_fatal(a.ty.span,
557 558
                                         "Dynamically sized arguments \
                                          must be passed by alias");
559 560 561 562 563
                }
                case (_) { }
            }
        }
        ret rec(mode=ty_mode, ty=tt);
564
    }
L
Lindsey Kuper 已提交
565
    fn ty_of_method(@ctxt cx, &@ast::method m) -> ty::method {
566
        auto get = bind getter(cx, _);
567
        auto convert = bind ast_ty_to_ty(cx.tcx, get, _);
568 569 570 571 572 573

        auto inputs = ~[];
        for (ast::arg a in m.node.meth.decl.inputs) {
            inputs += ~[ty_of_arg(cx, a)];
        }

574
        auto output = convert(m.node.meth.decl.output);
575 576 577 578 579

        auto out_constrs = ~[];
        for (@ast::constr constr in m.node.meth.decl.constraints) {
            out_constrs += ~[ast_constr_to_constr(cx.tcx, constr)];
        }
580 581 582
        ret rec(proto=m.node.meth.proto, ident=m.node.ident,
                inputs=inputs, output=output, cf=m.node.meth.decl.cf,
                constrs=out_constrs);
583
    }
584
    fn ty_of_obj(@ctxt cx, &ast::ident id, &ast::_obj obj_info,
585
                 &vec[ast::ty_param] ty_params) -> ty::ty_param_count_and_ty {
586
        auto methods = get_obj_method_types(cx, obj_info);
587 588
        auto t_obj = ty::mk_obj(cx.tcx, ty::sort_methods(methods));
        t_obj = ty::rename(cx.tcx, t_obj, id);
589
        ret tup(vec::len(ty_params), t_obj);
590
    }
591
    fn ty_of_obj_ctor(@ctxt cx, &ast::ident id, &ast::_obj obj_info,
592
                      ast::node_id ctor_id, &vec[ast::ty_param] ty_params) ->
593
       ty::ty_param_count_and_ty {
594
        auto t_obj = ty_of_obj(cx, id, obj_info, ty_params);
595 596

        let arg[] t_inputs = ~[];
597
        for (ast::obj_field f in obj_info.fields) {
598
            auto g = bind getter(cx, _);
599
            auto t_field = ast_ty_to_ty(cx.tcx, g, f.ty);
600
            t_inputs += ~[rec(mode=ty::mo_alias(false), ty=t_field)];
601
        }
602

603
        auto t_fn = ty::mk_fn(cx.tcx, ast::proto_fn, t_inputs, t_obj._1,
604
                              ast::return, ~[]);
605
        auto tpt = tup(t_obj._0, t_fn);
606
        cx.tcx.tcache.insert(local_def(ctor_id), tpt);
607
        ret tpt;
608
    }
609
    fn ty_of_item(&@ctxt cx, &@ast::item it) -> ty::ty_param_count_and_ty {
610
        auto get = bind getter(cx, _);
611
        auto convert = bind ast_ty_to_ty(cx.tcx, get, _);
612
        alt (it.node) {
613
            case (ast::item_const(?t, _)) {
614
                auto typ = convert(t);
615
                auto tpt = tup(0u, typ);
616
                cx.tcx.tcache.insert(local_def(it.id), tpt);
617
                ret tpt;
618
            }
619
            case (ast::item_fn(?fn_info, ?tps)) {
620 621
                auto f = bind ty_of_arg(cx, _);
                ret ty_of_fn_decl(cx, convert, f, fn_info.decl, fn_info.proto,
622
                                  tps, some(local_def(it.id)));
623
            }
624 625
            case (ast::item_obj(?obj_info, ?tps, _)) {
                auto t_obj = ty_of_obj(cx, it.ident, obj_info, tps);
626
                cx.tcx.tcache.insert(local_def(it.id), t_obj);
627
                ret t_obj;
628
            }
629
            case (ast::item_ty(?t, ?tps)) {
630
                alt (cx.tcx.tcache.find(local_def(it.id))) {
631 632
                    case (some(?tpt)) { ret tpt; }
                    case (none) { }
633 634 635
                }
                // Tell ast_ty_to_ty() that we want to perform a recursive
                // call to resolve any named types.
636

637
                auto typ = convert(t);
638
                auto ty_param_count = vec::len[ast::ty_param](tps);
639
                auto tpt = tup(ty_param_count, typ);
640
                cx.tcx.tcache.insert(local_def(it.id), tpt);
641
                ret tpt;
642
            }
643 644 645
            case (ast::item_res(?f, _, ?tps, _)) {
                auto t_arg = ty_of_arg(cx, f.decl.inputs.(0));
                auto t_res = tup(vec::len(tps), ty::mk_res
646 647
                                 (cx.tcx, local_def(it.id), t_arg.ty,
                                  mk_ty_params(cx, vec::len(tps))));
648 649 650
                cx.tcx.tcache.insert(local_def(it.id), t_res);
                ret t_res;
            }
651
            case (ast::item_tag(_, ?tps)) {
652
                // Create a new generic polytype.
653

654
                auto ty_param_count = vec::len[ast::ty_param](tps);
655

656 657
                let ty::t[] subtys = mk_ty_params(cx, ty_param_count);
                auto t = ty::mk_tag(cx.tcx, local_def(it.id), subtys);
658
                auto tpt = tup(ty_param_count, t);
659
                cx.tcx.tcache.insert(local_def(it.id), tpt);
660
                ret tpt;
661
            }
662 663
            case (ast::item_mod(_)) { fail; }
            case (ast::item_native_mod(_)) { fail; }
664 665
        }
    }
666 667
    fn ty_of_native_item(&@ctxt cx, &@ast::native_item it,
                         ast::native_abi abi) -> ty::ty_param_count_and_ty {
668
        alt (it.node) {
669
            case (ast::native_item_fn(_, ?fn_decl, ?params)) {
670
                auto get = bind getter(cx, _);
671
                auto convert = bind ast_ty_to_ty(cx.tcx, get, _);
672 673
                auto f = bind ty_of_arg(cx, _);
                ret ty_of_native_fn_decl(cx, convert, f, fn_decl, abi, params,
674
                                         ast::local_def(it.id));
675
            }
676 677
            case (ast::native_item_ty) {
                alt (cx.tcx.tcache.find(local_def(it.id))) {
678 679
                    case (some(?tpt)) { ret tpt; }
                    case (none) { }
680
                }
681
                auto t = ty::mk_native(cx.tcx, ast::local_def(it.id));
682
                auto tpt = tup(0u, t);
683
                cx.tcx.tcache.insert(local_def(it.id), tpt);
684
                ret tpt;
685 686 687
            }
        }
    }
688 689
    fn get_tag_variant_types(&@ctxt cx, &ast::def_id tag_id,
                             &vec[ast::variant] variants,
690
                             &vec[ast::ty_param] ty_params) {
691
        // Create a set of parameter types shared among all the variants.
692

693
        auto ty_param_count = vec::len[ast::ty_param](ty_params);
694
        let ty::t[] ty_param_tys = mk_ty_params(cx, ty_param_count);
695
        for (ast::variant variant in variants) {
696
            // Nullary tag constructors get turned into constants; n-ary tag
P
Patrick Walton 已提交
697
            // constructors get turned into functions.
698

P
Patrick Walton 已提交
699
            auto result_ty;
700
            if (vec::len[ast::variant_arg](variant.node.args) == 0u) {
701
                result_ty = ty::mk_tag(cx.tcx, tag_id, ty_param_tys);
P
Patrick Walton 已提交
702 703 704 705
            } else {
                // As above, tell ast_ty_to_ty() that trans_ty_item_to_ty()
                // should be called to resolve named types.

706
                auto f = bind getter(cx, _);
707
                let arg[] args = ~[];
708
                for (ast::variant_arg va in variant.node.args) {
709
                    auto arg_ty = ast_ty_to_ty(cx.tcx, f, va.ty);
710
                    args += ~[rec(mode=ty::mo_alias(false), ty=arg_ty)];
P
Patrick Walton 已提交
711
                }
712
                auto tag_t = ty::mk_tag(cx.tcx, tag_id, ty_param_tys);
713
                // FIXME: this will be different for constrained types
714
                result_ty = ty::mk_fn(cx.tcx, ast::proto_fn, args, tag_t,
715
                                      ast::return, ~[]);
P
Patrick Walton 已提交
716
            }
717
            auto tpt = tup(ty_param_count, result_ty);
718 719
            cx.tcx.tcache.insert(local_def(variant.node.id), tpt);
            write::ty_only(cx.tcx, variant.node.id, result_ty);
P
Patrick Walton 已提交
720 721
        }
    }
722 723 724 725 726 727
    fn get_obj_method_types(&@ctxt cx, &ast::_obj object) -> ty::method[] {
        auto meths = ~[];
        for (@ast::method m in object.methods) {
            meths += ~[ty_of_method(cx, m)];
        }
        ret meths;
728 729 730 731
    }
    fn convert(@ctxt cx, @mutable option::t[ast::native_abi] abi,
               &@ast::item it) {
        alt (it.node) {
732
            case (ast::item_mod(_)) {
733
                // ignore item_mod, it has no type.
734

735
            }
736
            case (ast::item_native_mod(?native_mod)) {
737 738
                // Propagate the native ABI down to convert_native() below,
                // but otherwise do nothing, as native modules have no types.
739

740 741
                *abi = some[ast::native_abi](native_mod.abi);
            }
742
            case (ast::item_tag(?variants, ?ty_params)) {
743
                auto tpt = ty_of_item(cx, it);
744 745 746
                write::ty_only(cx.tcx, it.id, tpt._1);
                get_tag_variant_types(cx, local_def(it.id), variants,
                                      ty_params);
747
            }
748
            case (ast::item_obj(?object, ?ty_params, ?ctor_id)) {
749 750 751
                // Now we need to call ty_of_obj_ctor(); this is the type that
                // we write into the table for this item.

T
Tim Chevalier 已提交
752 753
                ty_of_item(cx, it);

754
                auto tpt =
755
                    ty_of_obj_ctor(cx, it.ident, object, ctor_id, ty_params);
756
                write::ty_only(cx.tcx, ctor_id, tpt._1);
757 758 759 760 761
                // 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().)
762

763 764
                auto method_types = get_obj_method_types(cx, object);
                auto i = 0u;
765
                while (i < vec::len[@ast::method](object.methods)) {
766
                    write::ty_only(cx.tcx, object.methods.(i).node.id,
767
                                   ty::method_ty_to_fn_ty(cx.tcx,
768
                                                          method_types.(i)));
769 770 771 772
                    i += 1u;
                }
                // Write in the types of the object fields.
                //
773
                // FIXME: We want to use uint::range() here, but that causes
774
                // an assertion in trans.
775

776 777
                auto args = ty::ty_fn_args(cx.tcx, tpt._1);
                i = 0u;
778
                while (i < ivec::len[ty::arg](args)) {
779
                    auto fld = object.fields.(i);
780
                    write::ty_only(cx.tcx, fld.id, args.(i).ty);
781 782 783 784 785
                    i += 1u;
                }

                // Finally, write in the type of the destructor.
                alt (object.dtor) {
786
                    case (none) {/* nothing to do */ }
787
                    case (some(?m)) {
788
                        auto t = ty::mk_fn(cx.tcx, ast::proto_fn, ~[],
789
                                   ty::mk_nil(cx.tcx), ast::return, ~[]);
790
                        write::ty_only(cx.tcx, m.node.id, t);
791 792 793
                    }
                }
            }
794 795
            case (ast::item_res(?f, ?dtor_id, ?tps, ?ctor_id)) {
                auto t_arg = ty_of_arg(cx, f.decl.inputs.(0));
796 797
                auto t_res = ty::mk_res(cx.tcx, local_def(it.id), t_arg.ty,
                                        mk_ty_params(cx, vec::len(tps)));
798
                auto t_ctor = ty::mk_fn(cx.tcx, ast::proto_fn, ~[t_arg],
799
                                        t_res, ast::return, ~[]);
800
                auto t_dtor = ty::mk_fn(cx.tcx, ast::proto_fn, ~[t_arg],
801
                                        ty::mk_nil(cx.tcx), ast::return, ~[]);
G
Graydon Hoare 已提交
802
                write::ty_only(cx.tcx, it.id, t_res);
803 804 805 806 807
                write::ty_only(cx.tcx, ctor_id, t_ctor);
                cx.tcx.tcache.insert(local_def(ctor_id),
                                     tup(vec::len(tps), t_ctor));
                write::ty_only(cx.tcx, dtor_id, t_dtor);
            }
808
            case (_) {
809 810 811
                // 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.
812

813
                auto tpt = ty_of_item(cx, it);
814
                write::ty_only(cx.tcx, it.id, tpt._1);
815 816 817 818 819 820 821 822 823
            }
        }
    }
    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.

824 825
        auto tpt =
            ty_of_native_item(cx, i, option::get[ast::native_abi]({ *abi }));
826
        alt (i.node) {
827
            case (ast::native_item_ty) {
828
                // FIXME: Native types have no annotation. Should they? --pcw
829

830
            }
831 832
            case (ast::native_item_fn(_, _, _)) {
                write::ty_only(cx.tcx, i.id, tpt._1);
833 834
            }
        }
835
    }
836
    fn collect_item_types(&ty::ctxt tcx, &@ast::crate crate) {
837 838 839
        // We have to propagate the surrounding ABI to the native items
        // contained within the native module.

840
        auto abi = @mutable none[ast::native_abi];
841
        auto cx = @rec(tcx=tcx);
842
        auto visit =
843 844 845
            rec(visit_item_pre=bind convert(cx, abi, _),
                visit_native_item_pre=bind convert_native(cx, abi, _)
                with walk::default_visitor());
846
        walk::walk_crate(visit, *crate);
847
    }
848 849
}

850 851 852

// Type unification

853
// TODO: rename to just "unify"
854
mod unify {
855 856
    fn simple(&@fn_ctxt fcx, &ty::t expected, &ty::t actual) ->
       ty::unify::result {
857
        ret ty::unify::unify(expected, actual, fcx.var_bindings, fcx.ccx.tcx);
858
    }
859 860
}

861
tag autoderef_kind { AUTODEREF_OK; NO_AUTODEREF; }
862

863 864 865
// FIXME This is almost a duplicate of ty::type_autoderef, with structure_of
// instead of ty::struct.
fn do_autoderef(&@fn_ctxt fcx, &span sp, &ty::t t) -> ty::t {
866 867
    auto t1 = t;
    while (true) {
868
        alt (structure_of(fcx, sp, t1)) {
869
            case (ty::ty_box(?inner)) { t1 = inner.ty; }
870
            case (ty::ty_res(_, ?inner, ?tps)) {
871 872 873 874 875
                // FIXME: Remove this vec->ivec conversion.
                auto tps_ivec = ~[];
                for (ty::t tp in tps) { tps_ivec += ~[tp]; }

                t1 = ty::substitute_type_params(fcx.ccx.tcx, tps_ivec, inner);
876 877 878
            }
            case (ty::ty_tag(?did, ?tps)) {
                auto variants = ty::tag_variants(fcx.ccx.tcx, did);
879 880
                if (ivec::len(variants) != 1u ||
                        ivec::len(variants.(0).args) != 1u) {
881 882 883 884 885
                    ret t1;
                }
                t1 = ty::substitute_type_params(fcx.ccx.tcx, tps,
                                                variants.(0).args.(0));
            }
886 887 888 889 890 891
            case (_) { ret t1; }
        }
    }
    fail;
}

892
fn add_boxes(&@crate_ctxt ccx, uint n, &ty::t t) -> ty::t {
893
    auto t1 = t;
894
    while (n != 0u) { t1 = ty::mk_imm_box(ccx.tcx, t1); n -= 1u; }
895 896 897
    ret t1;
}

898
fn count_boxes(&@fn_ctxt fcx, &span sp, &ty::t t) -> uint {
899 900 901
    auto n = 0u;
    auto t1 = t;
    while (true) {
902
        alt (structure_of(fcx, sp, t1)) {
903
            case (ty::ty_box(?inner)) { n += 1u; t1 = inner.ty; }
904 905 906 907 908 909
            case (_) { ret n; }
        }
    }
    fail;
}

910 911 912 913 914 915 916 917
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; }
    }
}


918 919
// Demands - procedures that require that two types unify and emit an error
// message if they don't.
920
type ty_param_substs_and_ty = tup(ty::t[], ty::t);
921

922
mod demand {
923 924
    fn simple(&@fn_ctxt fcx, &span sp, &ty::t expected, &ty::t actual) ->
       ty::t {
925
        ret full(fcx, sp, expected, actual, ~[], NO_AUTODEREF)._1;
926
    }
927
    fn autoderef(&@fn_ctxt fcx, &span sp, &ty::t expected, &ty::t actual,
928
                 autoderef_kind adk) -> ty::t {
929
        ret full(fcx, sp, expected, actual, ~[], adk)._1;
930
    }
931

932 933
    // Requires that the two types unify, and prints an error message if they
    // don't. Returns the unified type and the type parameter substitutions.
934
    fn full(&@fn_ctxt fcx, &span sp, &ty::t expected, &ty::t actual,
935
            &ty::t[] ty_param_substs_0, autoderef_kind adk) ->
936
       ty_param_substs_and_ty {
937 938 939 940
        auto expected_1 = expected;
        auto actual_1 = actual;
        auto implicit_boxes = 0u;
        if (adk == AUTODEREF_OK) {
941 942
            expected_1 = do_autoderef(fcx, sp, expected_1);
            actual_1 = do_autoderef(fcx, sp, actual_1);
943
            implicit_boxes = count_boxes(fcx, sp, actual);
944
        }
945
        let vec[mutable ty::t] ty_param_substs = [mutable ];
946
        let vec[int] ty_param_subst_var_ids = [];
947
        for (ty::t ty_param_subst in ty_param_substs_0) {
948 949
            // Generate a type variable and unify it with the type parameter
            // substitution. We will then pull out these type variables.
950

951 952 953 954
            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);
955
        }
956 957 958 959

        fn mk_result(&@fn_ctxt fcx, &ty::t result_ty,
                     &vec[int] ty_param_subst_var_ids,
                     uint implicit_boxes) -> ty_param_substs_and_ty {
960
            let ty::t[] result_ty_param_substs = ~[];
961 962
            for (int var_id in ty_param_subst_var_ids) {
                auto tp_subst = ty::mk_var(fcx.ccx.tcx, var_id);
963
                result_ty_param_substs += ~[tp_subst];
964 965 966 967 968
            }
            ret tup(result_ty_param_substs,
                    add_boxes(fcx.ccx, implicit_boxes, result_ty));
        }

969
        alt (unify::simple(fcx, expected_1, actual_1)) {
970
            case (ures_ok(?t)) {
971 972
                ret mk_result(fcx, t, ty_param_subst_var_ids,
                              implicit_boxes);
973
            }
974
            case (ures_err(?err)) {
975 976
                auto e_err = resolve_type_vars_if_possible(fcx, expected_1);
                auto a_err = resolve_type_vars_if_possible(fcx, actual_1);
977
                fcx.ccx.tcx.sess.span_err(sp,
978
                                          "mismatched types: expected " +
979 980 981 982 983 984 985
                                          ty_to_str(fcx.ccx.tcx, e_err) +
                                          " but found " +
                                          ty_to_str(fcx.ccx.tcx, a_err) +
                                          " (" + ty::type_err_to_str(err)
                                          + ")");
                ret mk_result(fcx, expected_1,
                              ty_param_subst_var_ids, implicit_boxes);
986
            }
987 988 989 990
        }
    }
}

991

992
// Returns true if the two types unify and false if they don't.
993 994
fn are_compatible(&@fn_ctxt fcx, &ty::t expected, &ty::t actual) -> bool {
    alt (unify::simple(fcx, expected, actual)) {
995 996
        case (ures_ok(_)) { ret true; }
        case (ures_err(_)) { ret false; }
997 998 999
    }
}

1000

1001
// Returns the types of the arguments to a tag variant.
1002
fn variant_arg_types(&@crate_ctxt ccx, &span sp, &ast::def_id vid,
1003
                     &ty::t[] tag_ty_params) -> vec[ty::t] {
1004
    let vec[ty::t] result = [];
1005
    auto tpt = ty::lookup_item_type(ccx.tcx, vid);
1006
    alt (ty::struct(ccx.tcx, tpt._1)) {
1007
        case (ty::ty_fn(_, ?ins, _, _, _)) {
1008

1009
            // N-ary variant.
1010
            for (ty::arg arg in ins) {
1011 1012 1013
                auto arg_ty =
                    ty::substitute_type_params(ccx.tcx, tag_ty_params,
                                               arg.ty);
1014
                result += [arg_ty];
1015 1016 1017 1018
            }
        }
        case (_) {
            // Nullary variant. Do nothing, as there are no arguments.
1019

1020 1021
        }
    }
1022
    /* result is a vector of the *expected* types of all the fields */
1023

1024 1025 1026
    ret result;
}

1027

1028 1029 1030 1031 1032 1033
// 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.
1034
mod writeback {
1035 1036 1037

    export resolve_type_vars_in_block;

1038
    fn resolve_type_vars_in_type(&@fn_ctxt fcx, &span sp, ty::t typ) ->
1039 1040
        option::t[ty::t] {
        if (!ty::type_contains_vars(fcx.ccx.tcx, typ)) { ret some(typ); }
1041
        alt (ty::unify::fixup_vars(fcx.ccx.tcx, fcx.var_bindings, typ)) {
1042
            case (fix_ok(?new_type)) { ret some(new_type); }
1043
            case (fix_err(?vid)) {
1044
                fcx.ccx.tcx.sess.span_err(sp,
1045 1046
                                          "cannot determine a type \
                                           for this expression");
1047
                ret none;
1048
            }
1049
        }
1050
    }
1051 1052 1053
    fn resolve_type_vars_for_node(&@wb_ctxt wbcx,
                                  &span sp, ast::node_id id) {
        auto fcx = wbcx.fcx;
1054 1055
        auto tpot = ty::node_id_to_ty_param_substs_opt_and_ty
            (fcx.ccx.tcx, id);
1056 1057 1058 1059 1060 1061 1062
        auto new_ty = alt (resolve_type_vars_in_type(fcx, sp, tpot._1)) {
            case (some(?t)) { t }
            case (none) {
                wbcx.success = false;
                ret
            }
        };
1063 1064
        auto new_substs_opt;
        alt (tpot._0) {
1065 1066 1067
            case (none[ty::t[]]) { new_substs_opt = none[ty::t[]]; }
            case (some[ty::t[]](?substs)) {
                let ty::t[] new_substs = ~[];
1068
                for (ty::t subst in substs) {
1069 1070
                    alt (resolve_type_vars_in_type(fcx, sp, subst)) {
                        case (some(?t)) {
1071
                            new_substs += ~[t];
1072 1073 1074 1075 1076 1077
                        }
                        case (none) {
                            wbcx.success = false;
                            ret;
                        }
                    }
1078
                }
1079
                new_substs_opt = some[ty::t[]](new_substs);
1080
            }
P
Patrick Walton 已提交
1081
        }
1082
        write::ty(fcx.ccx.tcx, id, tup(new_substs_opt, new_ty));
P
Patrick Walton 已提交
1083
    }
1084 1085 1086

    type wb_ctxt = rec(@fn_ctxt fcx,
                       // A flag to ignore contained items and lambdas
1087
                       mutable bool ignore,
1088 1089
                       // As soon as we hit an error we have to stop resolving
                       // the entire function
1090
                       mutable bool success);
1091 1092

    fn visit_stmt_pre(@wb_ctxt wbcx, &@ast::stmt s) {
1093
        resolve_type_vars_for_node(wbcx, s.span, ty::stmt_node_id(s));
1094
    }
1095
    fn visit_expr_pre(@wb_ctxt wbcx, &@ast::expr e) {
1096
        resolve_type_vars_for_node(wbcx, e.span, e.id);
1097
    }
1098
    fn visit_block_pre(@wb_ctxt wbcx, &ast::block b) {
1099
        resolve_type_vars_for_node(wbcx, b.span, b.node.id);
1100
    }
1101
    fn visit_pat_pre(@wb_ctxt wbcx, &@ast::pat p) {
1102
        resolve_type_vars_for_node(wbcx, p.span, p.id);
1103
    }
1104 1105
    fn visit_local_pre(@wb_ctxt wbcx, &@ast::local l) {
        auto var_id = lookup_local(wbcx.fcx, l.span, l.node.id);
1106
        auto fix_rslt =
1107 1108
            ty::unify::resolve_type_var(wbcx.fcx.ccx.tcx,
                                        wbcx.fcx.var_bindings,
1109
                                        var_id);
1110 1111
        alt (fix_rslt) {
            case (fix_ok(?lty)) {
1112
                write::ty_only(wbcx.fcx.ccx.tcx, l.node.id, lty);
1113 1114
            }
            case (fix_err(_)) {
1115 1116 1117 1118
                wbcx.fcx.ccx.tcx.sess.span_err(l.span,
                                               "cannot determine a type \
                                                for this local variable");
                wbcx.success = false;
1119
            }
1120
        }
1121
    }
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
    fn visit_item_pre(@wb_ctxt wbcx, &@ast::item item) {
        wbcx.ignore = true;
    }
    fn visit_item_post(@wb_ctxt wbcx, &@ast::item item) {
        wbcx.ignore = false;
    }
    fn visit_fn_pre(@wb_ctxt wbcx, &ast::_fn f,
                    &vec[ast::ty_param] tps, &span sp,
                    &ast::fn_ident i, ast::node_id d) {
        wbcx.ignore = true;
    }
    fn visit_fn_post(@wb_ctxt wbcx, &ast::_fn f,
                     &vec[ast::ty_param] tps, &span sp,
                     &ast::fn_ident i, ast::node_id d) {
        wbcx.ignore = false;
    }
1138
    fn keep_going(@wb_ctxt wbcx) -> bool { !wbcx.ignore && wbcx.success }
1139

1140
    fn resolve_type_vars_in_block(&@fn_ctxt fcx, &ast::block block) -> bool {
1141
        auto wbcx = @rec(fcx = fcx,
1142 1143
                         mutable ignore = false,
                         mutable success = true);
1144
        auto visit =
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
            rec(keep_going=bind keep_going(wbcx),
                visit_item_pre=bind visit_item_pre(wbcx, _),
                visit_item_post=bind visit_item_post(wbcx, _),
                visit_fn_pre=bind visit_fn_pre(wbcx, _, _, _, _, _),
                visit_fn_post=bind visit_fn_post(wbcx, _, _, _, _, _),
                visit_stmt_pre=bind visit_stmt_pre(wbcx, _),
                visit_expr_pre=bind visit_expr_pre(wbcx, _),
                visit_block_pre=bind visit_block_pre(wbcx, _),
                visit_pat_pre=bind visit_pat_pre(wbcx, _),
                visit_local_pre=bind visit_local_pre(wbcx, _)
1155
                with walk::default_visitor());
1156
        walk::walk_block(visit, block);
1157
        ret wbcx.success;
1158
    }
1159 1160
}

1161

1162 1163
// Local variable gathering. We gather up all locals and create variable IDs
// for them before typechecking the function.
1164 1165
type gather_result =
    rec(@ty::unify::var_bindings var_bindings,
1166 1167
        hashmap[ast::node_id, int] locals,
        hashmap[ast::node_id, ast::ident] local_names,
1168
        int next_var_id);
1169 1170

fn gather_locals(&@crate_ctxt ccx, &ast::fn_decl decl, &ast::block body,
1171
                 &ast::node_id id) -> gather_result {
1172 1173 1174 1175 1176
    fn next_var_id(@mutable int nvi) -> int {
        auto rv = *nvi;
        *nvi += 1;
        ret rv;
    }
1177
    fn assign(&ty::ctxt tcx, &@ty::unify::var_bindings var_bindings,
1178 1179 1180 1181
              &hashmap[ast::node_id, int] locals,
              &hashmap[ast::node_id, ast::ident] local_names,
              @mutable int nvi,
              ast::node_id nid, &ast::ident ident, option::t[ty::t] ty_opt) {
1182
        auto var_id = next_var_id(nvi);
1183 1184
        locals.insert(nid, var_id);
        local_names.insert(nid, ident);
1185
        alt (ty_opt) {
1186
            case (none[ty::t]) {/* nothing to do */ }
1187 1188 1189 1190 1191 1192 1193
            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();
1194 1195
    auto locals = new_int_hash[int]();
    auto local_names = new_int_hash[ast::ident]();
1196 1197
    auto nvi = @mutable 0;
    // Add object fields, if any.
1198

1199 1200 1201
    alt (get_obj_info(ccx)) {
        case (option::some(?oinfo)) {
            for (ast::obj_field f in oinfo.obj_fields) {
1202 1203 1204
                auto field_ty = ty::node_id_to_type(ccx.tcx, f.id);
                assign(ccx.tcx, vb, locals, local_names, nvi, f.id,
                       f.ident, some(field_ty));
1205 1206
            }
        }
1207
        case (option::none) {/* no fields */ }
1208 1209
    }
    // Add formal parameters.
1210

1211
    auto args = ty::ty_fn_args(ccx.tcx, ty::node_id_to_type(ccx.tcx, id));
1212 1213 1214 1215 1216 1217 1218
    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.
1219 1220

    fn visit_local_pre(@crate_ctxt ccx, @ty::unify::var_bindings vb,
1221 1222
                       hashmap[ast::node_id, int] locals,
                       hashmap[ast::node_id, ast::ident] local_names,
1223
                       @mutable int nvi, &@ast::local local) {
1224 1225 1226
        alt (local.node.ty) {
            case (none) {
                // Auto slot.
1227 1228 1229

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

1234
                auto local_ty = ast_ty_to_ty_crate(ccx, ast_ty);
1235 1236
                assign(ccx.tcx, vb, locals, local_names, nvi, local.node.id,
                       local.node.ident, some[ty::t](local_ty));
1237 1238 1239 1240
            }
        }
    }
    // Add pattern bindings.
1241 1242

    fn visit_pat_pre(@crate_ctxt ccx, @ty::unify::var_bindings vb,
1243 1244
                     hashmap[ast::node_id, int] locals,
                     hashmap[ast::node_id, ast::ident] local_names,
1245
                     @mutable int nvi, &@ast::pat p) {
1246
        alt (p.node) {
1247
            case (ast::pat_bind(?ident)) {
1248
                assign(ccx.tcx, vb, locals, local_names, nvi,
1249
                       p.id, ident, none[ty::t]);
1250
            }
1251
            case (_) {/* no-op */ }
1252 1253 1254
        }
    }
    auto visit =
1255
        rec(visit_local_pre=bind visit_local_pre(ccx, vb, locals, local_names,
1256
                                                 nvi, _),
1257 1258 1259 1260
            visit_pat_pre=bind visit_pat_pre(ccx, vb, locals, local_names,
                                             nvi, _)
            with walk::default_visitor());
    walk::walk_block(visit, body);
1261 1262 1263 1264
    ret rec(var_bindings=vb,
            locals=locals,
            local_names=local_names,
            next_var_id=*nvi);
1265 1266 1267
}


1268
// AST fragment utilities
1269
fn replace_expr_type(&@fn_ctxt fcx, &@ast::expr expr,
1270
                     &tup(ty::t[], ty::t) new_tyt) {
1271
    auto new_tps;
1272
    if (ty::expr_has_ty_params(fcx.ccx.tcx, expr)) {
1273 1274
        new_tps = some[ty::t[]](new_tyt._0);
    } else { new_tps = none[ty::t[]]; }
1275
    write::ty_fixup(fcx, expr.id, tup(new_tps, new_tyt._1));
1276 1277
}

1278

1279
// AST fragment checking
1280
fn check_lit(@crate_ctxt ccx, &@ast::lit lit) -> ty::t {
1281
    alt (lit.node) {
1282
        case (ast::lit_str(_, ast::sk_rc)) { ret ty::mk_str(ccx.tcx); }
1283
        case (ast::lit_str(_, ast::sk_unique)) { ret ty::mk_istr(ccx.tcx); }
1284 1285 1286 1287 1288 1289 1290 1291
        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); }
1292 1293 1294
    }
}

1295

1296 1297
// Pattern checking is top-down rather than bottom-up so that bindings get
// their types immediately.
1298
fn check_pat(&@fn_ctxt fcx, &@ast::pat pat, ty::t expected) {
1299
    alt (pat.node) {
1300 1301
        case (ast::pat_wild) {
            write::ty_only_fixup(fcx, pat.id, expected);
1302
        }
1303
        case (ast::pat_lit(?lt)) {
1304 1305
            auto typ = check_lit(fcx.ccx, lt);
            typ = demand::simple(fcx, pat.span, expected, typ);
1306
            write::ty_only_fixup(fcx, pat.id, typ);
1307
        }
1308 1309
        case (ast::pat_bind(?name)) {
            auto vid = lookup_local(fcx, pat.span, pat.id);
1310 1311
            auto typ = ty::mk_var(fcx.ccx.tcx, vid);
            typ = demand::simple(fcx, pat.span, expected, typ);
1312
            write::ty_only_fixup(fcx, pat.id, typ);
1313
        }
1314
        case (ast::pat_tag(?path, ?subpats)) {
1315
            // Typecheck the path.
1316
            auto v_def = lookup_def(fcx, path.span, pat.id);
1317
            auto v_def_ids = ast::variant_def_ids(v_def);
1318
            auto tag_tpt = ty::lookup_item_type(fcx.ccx.tcx, v_def_ids._0);
1319
            auto path_tpot = instantiate_path(fcx, path, tag_tpt, pat.span);
1320
            // Take the tag type params out of `expected`.
1321

1322
            alt (structure_of(fcx, pat.span, expected)) {
1323 1324 1325 1326 1327 1328 1329 1330
              case (ty::ty_tag(_, ?expected_tps)) {
                // Unify with the expected tag type.

                auto ctor_ty =
                    ty::ty_param_substs_opt_and_ty_to_monotype(fcx.ccx.tcx,
                                                               path_tpot);

                // FIXME: Remove this ivec->vec conversion.
1331 1332
                auto tps_vec = ~[];
                for (ty::t tp in expected_tps) { tps_vec += ~[tp]; }
1333 1334 1335 1336

                auto path_tpt =
                    demand::full(fcx, pat.span, expected, ctor_ty, tps_vec,
                                 NO_AUTODEREF);
1337
                path_tpot = tup(some[ty::t[]](path_tpt._0), path_tpt._1);
1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
                // Get the number of arguments in this tag variant.

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

                    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...
                        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_fatal(pat.span, s);
                    }
                    // TODO: vec::iter2
1364

1365 1366 1367 1368 1369 1370
                    auto i = 0u;
                    for (@ast::pat subpat in subpats) {
                        check_pat(fcx, subpat, arg_types.(i));
                        i += 1u;
                    }
                } else if (subpats_len > 0u) {
1371 1372 1373
                    // TODO: note definition of tag variant
                    // TODO (issue #448): Wrap a #fmt string over multiple
                    // lines...
1374

1375
                    fcx.ccx.tcx.sess.span_fatal(pat.span,
1376 1377 1378 1379 1380 1381 1382
                                          #fmt("this pattern has %u field%s, \
                                                but the corresponding \
                                                variant has no fields",
                                               subpats_len,
                                               if (subpats_len == 1u) {
                                                   ""
                                               } else { "s" }));
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
                }
                write::ty_fixup(fcx, pat.id, path_tpot);
              }
              case (_) {
                // FIXME: Switch expected and actual in this message? I
                // can never tell.

                fcx.ccx.tcx.sess.span_fatal(pat.span,
                                            #fmt("mismatched types: \
                                                  expected tag, found %s",
                                                 ty_to_str(fcx.ccx.tcx,
                                                           expected)));
              }
1396
            }
1397
            write::ty_fixup(fcx, pat.id, path_tpot);
1398 1399 1400 1401
        }
    }
}

1402
fn require_impure(&session::session sess, &ast::purity f_purity, &span sp) {
1403
    alt (f_purity) {
1404
        case (ast::impure_fn) { ret; }
1405
        case (ast::pure_fn) {
1406
            sess.span_fatal(sp,
1407
                          "Found impure expression in pure function decl");
1408 1409 1410 1411
        }
    }
}

1412 1413
fn require_pure_call(@crate_ctxt ccx, &ast::purity caller_purity,
                     &@ast::expr callee, &span sp) {
1414
    alt (caller_purity) {
1415
        case (ast::impure_fn) { ret; }
1416
        case (ast::pure_fn) {
1417 1418
            alt (ccx.tcx.def_map.find(callee.id)) {
                case (some(ast::def_fn(_, ast::pure_fn))) {
1419
                    ret;
1420 1421
                }
                case (_) {
1422
                    ccx.tcx.sess.span_fatal(sp,
1423
                     "Pure function calls function not known to be pure");
1424 1425 1426 1427 1428 1429
                }
            }
        }
    }
}

1430 1431
fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
    // fcx.ccx.tcx.sess.span_warn(expr.span, "typechecking expr " +
1432
    //                            syntax::print::pprust::expr_to_str(expr));
1433

1434 1435
    // A generic function to factor out common logic from call and bind
    // expressions.
1436

1437
    fn check_call_or_bind(&@fn_ctxt fcx, &span sp, &@ast::expr f,
1438
                          &vec[option::t[@ast::expr]] args, bool is_call) {
1439 1440
        // Check the function.

1441
        check_expr(fcx, f);
1442
        // Get the function type.
1443

1444 1445
        auto fty = expr_ty(fcx.ccx.tcx, f);

1446 1447
        // We want to autoderef calls but not binds
        auto fty_stripped =
1448
            if (is_call) { do_autoderef(fcx, sp, fty) } else { fty };
1449 1450

        // Grab the argument types and the return type.
1451
        auto arg_tys;
1452
        alt (structure_of(fcx, sp, fty_stripped)) {
1453 1454
            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; }
1455
            case (_) {
1456
                fcx.ccx.tcx.sess.span_fatal(f.span,
1457 1458 1459 1460
                                          "mismatched types: \
                                           expected function or native \
                                           function but found "
                                          + ty_to_str(fcx.ccx.tcx, fty));
1461 1462 1463
            }
        }
        // Check that the correct number of arguments were supplied.
1464

1465
        auto expected_arg_count = ivec::len[ty::arg](arg_tys);
1466 1467
        auto supplied_arg_count = vec::len[option::t[@ast::expr]](args);
        if (expected_arg_count != supplied_arg_count) {
1468
            fcx.ccx.tcx.sess.span_fatal(sp,
1469 1470 1471 1472 1473 1474 1475 1476 1477 1478
                                      #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" }));
1479 1480 1481
        }
        // Check the arguments.
        // TODO: iter2
1482

1483
        auto i = 0u;
1484
        for (option::t[@ast::expr] a_opt in args) {
1485
            alt (a_opt) {
1486
                case (some(?a)) {
1487
                    check_expr(fcx, a);
1488 1489
                    demand::simple(fcx, a.span, arg_tys.(i).ty,
                                   expr_ty(fcx.ccx.tcx, a));
1490
                }
1491
                case (none) {/* no-op */ }
1492
            }
1493
            i += 1u;
1494 1495
        }
    }
1496
    // A generic function for checking assignment expressions
1497

1498
    fn check_assignment(&@fn_ctxt fcx, &span sp, &@ast::expr lhs,
1499
                        &@ast::expr rhs, &ast::node_id id) {
1500 1501
        check_expr(fcx, lhs);
        check_expr(fcx, rhs);
1502 1503
        demand::simple(fcx, sp, expr_ty(fcx.ccx.tcx, lhs),
                       expr_ty(fcx.ccx.tcx, rhs));
1504
        write::ty_only_fixup(fcx, id, ty::mk_nil(fcx.ccx.tcx));
1505
    }
1506
    // A generic function for checking call expressions
1507

1508 1509
    fn check_call(&@fn_ctxt fcx, &span sp, &@ast::expr f,
                  &vec[@ast::expr] args) {
1510
        let vec[option::t[@ast::expr]] args_opt_0 = [];
1511
        for (@ast::expr arg in args) {
1512
            args_opt_0 += [some[@ast::expr](arg)];
1513 1514
        }
        // Call the generic checker.
1515

1516
        check_call_or_bind(fcx, sp, f, args_opt_0, true);
1517
    }
1518
    // A generic function for checking for or for-each loops
1519

1520
    fn check_for_or_for_each(&@fn_ctxt fcx, &@ast::local local,
1521
                             &ty::t element_ty, &ast::block body,
1522
                             ast::node_id node_id) {
P
Paul Stansifer 已提交
1523
        check_decl_local(fcx, local);
1524
        check_block(fcx, body);
1525
        // Unify type of decl with element type of the seq
1526
        demand::simple(fcx, local.span,
P
Paul Stansifer 已提交
1527
                       ty::decl_local_ty(fcx.ccx.tcx, local),
1528
                       element_ty);
1529 1530
        auto typ = ty::mk_nil(fcx.ccx.tcx);
        write::ty_only_fixup(fcx, node_id, typ);
1531
    }
T
Tim Chevalier 已提交
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542

    // A generic function for checking the pred in a check
    // or if-check
    fn check_pred_expr(&@fn_ctxt fcx, &@ast::expr e) {
        check_expr(fcx, e);
        demand::simple(fcx, e.span, ty::mk_bool(fcx.ccx.tcx),
                       expr_ty(fcx.ccx.tcx, e));
        
        /* e must be a call expr where all arguments are either
           literals or slots */
            alt (e.node) {
1543
                case (ast::expr_call(?operator, ?operands)) {
T
Tim Chevalier 已提交
1544
                    alt (operator.node) {
1545
                        case (ast::expr_path(?oper_name)) {
1546 1547 1548
                            alt (fcx.ccx.tcx.def_map.find(operator.id)) {
                                case (some(ast::def_fn(?_d_id,
                                                       ast::pure_fn))) { 
1549 1550 1551 1552 1553 1554 1555
                                    // do nothing
                                }
                                case (_) {
                                    fcx.ccx.tcx.sess.span_fatal(operator.span,
                                      "non-predicate as operator \
                                       in constraint");
                                }
T
Tim Chevalier 已提交
1556 1557 1558 1559 1560
                            }
                            for (@ast::expr operand in operands) {
                                if (!ast::is_constraint_arg(operand)) {
                                    auto s = "Constraint args must be \
                                              slot variables or literals";
1561
                                    fcx.ccx.tcx.sess.span_fatal(e.span, s);
T
Tim Chevalier 已提交
1562 1563
                                }
                            }
1564
                        }
T
Tim Chevalier 已提交
1565 1566 1567
                        case (_) {
                            auto s = "In a constraint, expected the \
                                      constraint name to be an explicit name";
1568
                            fcx.ccx.tcx.sess.span_fatal(e.span,s);
T
Tim Chevalier 已提交
1569 1570 1571 1572
                        }
                    }
                }
                case (_) {
1573
                    fcx.ccx.tcx.sess.span_fatal(e.span,
T
Tim Chevalier 已提交
1574 1575 1576 1577 1578 1579 1580 1581
                                              "check on non-predicate");
                }
            }
    }

    // A generic function for checking the then and else in an if
    // or if-check
    fn check_then_else(&@fn_ctxt fcx, &ast::block thn,
1582 1583
                       &option::t[@ast::expr] elsopt,
                       ast::node_id id, &span sp) {
T
Tim Chevalier 已提交
1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597
        check_block(fcx, thn);
        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, sp, thn_t, elsopt_t);
                        if (!ty::type_is_bot(fcx.ccx.tcx, elsopt_t)) {
                            elsopt_t
                                } else { thn_t }
                    }
                    case (none) { ty::mk_nil(fcx.ccx.tcx) }
            };
1598
        write::ty_only_fixup(fcx, id, if_t);
T
Tim Chevalier 已提交
1599 1600
    }

1601
    // Checks the compatibility 
1602
    fn check_binop_type_compat(&@fn_ctxt fcx, span span,
1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613
                               ty::t ty, ast::binop binop) {
        auto resolved_t = resolve_type_vars_if_possible(fcx, ty);
        if (!ty::is_binopable(fcx.ccx.tcx, resolved_t, binop)) {
            auto binopstr = ast::binop_to_str(binop);
            auto t_str = ty_to_str(fcx.ccx.tcx, resolved_t);
            auto errmsg = "binary operation " + binopstr
                + " cannot be applied to type `" + t_str + "`";
            fcx.ccx.tcx.sess.span_fatal(span, errmsg);
        }
    }

1614
    auto id = expr.id;
1615
    alt (expr.node) {
1616
        case (ast::expr_lit(?lit)) {
1617
            auto typ = check_lit(fcx.ccx, lit);
1618
            write::ty_only_fixup(fcx, id, typ);
1619
        }
1620
        case (ast::expr_binary(?binop, ?lhs, ?rhs)) {
1621 1622
            check_expr(fcx, lhs);
            check_expr(fcx, rhs);
1623

1624
            auto lhs_t = expr_ty(fcx.ccx.tcx, lhs);
1625 1626
            auto rhs_t = expr_ty(fcx.ccx.tcx, rhs);

1627
            demand::autoderef(fcx, rhs.span, lhs_t, rhs_t, AUTODEREF_OK);
1628 1629 1630 1631 1632 1633 1634 1635 1636
            check_binop_type_compat(fcx, expr.span, lhs_t, binop);

            auto t = alt (binop) {
                case (ast::eq) { ty::mk_bool(fcx.ccx.tcx) }
                case (ast::lt) { ty::mk_bool(fcx.ccx.tcx) }
                case (ast::le) { ty::mk_bool(fcx.ccx.tcx) }
                case (ast::ne) { ty::mk_bool(fcx.ccx.tcx) }
                case (ast::ge) { ty::mk_bool(fcx.ccx.tcx) }
                case (ast::gt) { ty::mk_bool(fcx.ccx.tcx) }
1637
                case (_) { do_autoderef(fcx, expr.span, lhs_t) }
1638
            };
1639
            write::ty_only_fixup(fcx, id, t);
1640
        }
1641
        case (ast::expr_unary(?unop, ?oper)) {
1642 1643
            check_expr(fcx, oper);
            auto oper_t = expr_ty(fcx.ccx.tcx, oper);
1644
            alt (unop) {
1645
                case (ast::box(?mut)) {
1646
                    oper_t = ty::mk_box(fcx.ccx.tcx, rec(ty=oper_t, mut=mut));
1647
                }
1648
                case (ast::deref) {
1649
                    alt (structure_of(fcx, expr.span, oper_t)) {
1650
                        case (ty::ty_box(?inner)) { oper_t = inner.ty; }
1651
                        case (ty::ty_res(_, ?inner, _)) { oper_t = inner; }
1652 1653
                        case (ty::ty_tag(?id, ?tps)) {
                            auto variants = ty::tag_variants(fcx.ccx.tcx, id);
1654 1655
                            if (ivec::len(variants) != 1u ||
                                    ivec::len(variants.(0).args) != 1u) {
1656 1657 1658 1659 1660 1661 1662 1663
                                fcx.ccx.tcx.sess.span_fatal
                                    (expr.span, "can only dereference tags " +
                                     "with a single variant which has a " +
                                     "single argument");
                            }
                            oper_t = ty::substitute_type_params
                                (fcx.ccx.tcx, tps, variants.(0).args.(0));
                        }
1664
                        case (_) {
1665 1666 1667 1668
                            fcx.ccx.tcx.sess.span_fatal
                                (expr.span, "dereferencing non-" + 
                                 "dereferenceable type: " +
                                 ty_to_str(fcx.ccx.tcx, oper_t));
1669 1670 1671
                        }
                    }
                }
1672 1673
                case (ast::not) {
                    if (!type_is_integral(fcx, oper.span, oper_t) &&
1674 1675
                            structure_of(fcx, oper.span, oper_t) !=
                                ty::ty_bool) {
1676
                        fcx.ccx.tcx.sess.span_fatal(expr.span,
1677 1678 1679 1680 1681
                                                  #fmt("mismatched types: \
                                                        expected bool or \
                                                        integer but found %s",
                                                       ty_to_str(fcx.ccx.tcx,
                                                                 oper_t)));
1682 1683
                    }
                }
1684
                case (_) { oper_t = do_autoderef(fcx, expr.span, oper_t); }
1685
            }
1686
            write::ty_only_fixup(fcx, id, oper_t);
1687
        }
1688
        case (ast::expr_path(?pth)) {
1689
            auto defn = lookup_def(fcx, pth.span, id);
1690
            auto tpt = ty_param_count_and_ty_for_def(fcx, expr.span, defn);
1691
            if (ty::def_has_ty_params(defn)) {
1692
                auto path_tpot = instantiate_path(fcx, pth, tpt, expr.span);
1693
                write::ty_fixup(fcx, id, path_tpot);
1694
                ret;
1695 1696 1697
            }
            // The definition doesn't take type parameters. If the programmer
            // supplied some, that's an error.
1698

1699
            if (vec::len[@ast::ty](pth.node.types) > 0u) {
1700
                fcx.ccx.tcx.sess.span_fatal(expr.span,
1701 1702
                                          "this kind of value does not \
                                           take type parameters");
1703
            }
1704
            write::ty_only_fixup(fcx, id, tpt._1);
1705
        }
1706
        case (ast::expr_ext(?p, ?args, ?body, ?expanded)) {
1707 1708
            check_expr(fcx, expanded);
            auto t = expr_ty(fcx.ccx.tcx, expanded);
1709
            write::ty_only_fixup(fcx, id, t);
1710
        }
1711 1712 1713
        case (ast::expr_fail(?expr_opt)) {
            alt (expr_opt) {
                case (none) { /* do nothing */ }
1714 1715 1716 1717
                case (some(?e)) {
                    check_expr(fcx, e);
                    auto tcx = fcx.ccx.tcx;
                    auto ety = expr_ty(tcx, e);
1718
                    demand::simple(fcx, e.span, ty::mk_str(tcx), ety);
1719
                }
1720 1721 1722
            }
            write::bot_ty(fcx.ccx.tcx, id);
        }
1723 1724 1725
        case (ast::expr_break) { write::bot_ty(fcx.ccx.tcx, id); }
        case (ast::expr_cont) { write::bot_ty(fcx.ccx.tcx, id); }
        case (ast::expr_ret(?expr_opt)) {
1726
            alt (expr_opt) {
1727
                case (none) {
1728 1729
                    auto nil = ty::mk_nil(fcx.ccx.tcx);
                    if (!are_compatible(fcx, fcx.ret_ty, nil)) {
1730
                        fcx.ccx.tcx.sess.span_fatal(expr.span,
1731 1732
                                                  "ret; in function \
                                                   returning non-nil");
1733
                    }
1734
                    write::bot_ty(fcx.ccx.tcx, id);
1735
                }
1736
                case (some(?e)) {
1737
                    check_expr(fcx, e);
1738 1739
                    demand::simple(fcx, expr.span, fcx.ret_ty,
                                   expr_ty(fcx.ccx.tcx, e));
1740
                    write::bot_ty(fcx.ccx.tcx, id);
1741 1742 1743
                }
            }
        }
1744
        case (ast::expr_put(?expr_opt)) {
1745
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
1746
            alt (expr_opt) {
1747
                case (none) {
1748 1749
                    auto nil = ty::mk_nil(fcx.ccx.tcx);
                    if (!are_compatible(fcx, fcx.ret_ty, nil)) {
1750
                        fcx.ccx.tcx.sess.span_fatal(expr.span,
1751 1752
                                                  "put; in iterator \
                                                   yielding non-nil");
1753
                    }
1754
                    write::nil_ty(fcx.ccx.tcx, id);
1755
                }
1756
                case (some(?e)) {
1757
                    check_expr(fcx, e);
1758
                    write::nil_ty(fcx.ccx.tcx, id);
1759 1760 1761
                }
            }
        }
1762
        case (ast::expr_be(?e)) {
1763
            // FIXME: prove instead of assert
P
Patrick Walton 已提交
1764

1765
            assert (ast::is_call_expr(e));
1766
            check_expr(fcx, e);
1767
            demand::simple(fcx, e.span, fcx.ret_ty, expr_ty(fcx.ccx.tcx, e));
1768
            write::nil_ty(fcx.ccx.tcx, id);
1769
        }
1770
        case (ast::expr_log(?l, ?e)) {
T
Tim Chevalier 已提交
1771
            check_expr(fcx, e);
1772
            write::nil_ty(fcx.ccx.tcx, id);
1773
        }
T
Tim Chevalier 已提交
1774
        case (ast::expr_check(_, ?e)) {
T
Tim Chevalier 已提交
1775
            check_pred_expr(fcx, e);
1776
            write::nil_ty(fcx.ccx.tcx, id);
T
Tim Chevalier 已提交
1777
        }
1778
        case (ast::expr_if_check(?cond, ?thn, ?elsopt)) {
T
Tim Chevalier 已提交
1779
            check_pred_expr(fcx, cond);
1780
            check_then_else(fcx, thn, elsopt, id, expr.span);
1781
        }
1782 1783 1784
        case (ast::expr_ternary(_, _, _)) {
            check_expr(fcx, ast::ternary_to_if(expr));
        }
1785
        case (ast::expr_assert(?e)) {
1786 1787 1788
            check_expr(fcx, e);
            auto ety = expr_ty(fcx.ccx.tcx, e);
            demand::simple(fcx, expr.span, ty::mk_bool(fcx.ccx.tcx), ety);
1789
            write::nil_ty(fcx.ccx.tcx, id);
1790
        }
1791
        case (ast::expr_move(?lhs, ?rhs)) {
1792
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
1793
            check_assignment(fcx, expr.span, lhs, rhs, id);
1794
        }
1795
        case (ast::expr_assign(?lhs, ?rhs)) {
1796
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
1797
            check_assignment(fcx, expr.span, lhs, rhs, id);
1798
        }
1799
        case (ast::expr_swap(?lhs, ?rhs)) {
1800
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
1801
            check_assignment(fcx, expr.span, lhs, rhs, id);
1802
        }
1803
        case (ast::expr_assign_op(?op, ?lhs, ?rhs)) {
1804
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
1805
            check_assignment(fcx, expr.span, lhs, rhs, id);
1806 1807
            check_binop_type_compat(fcx, expr.span,
                                    expr_ty(fcx.ccx.tcx, lhs), op);
1808
        }
1809
        case (ast::expr_send(?lhs, ?rhs)) {
1810 1811 1812 1813 1814 1815
            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);
            auto lhs_t = expr_ty(fcx.ccx.tcx, lhs);
1816
            alt (structure_of(fcx, expr.span, lhs_t)) {
T
Tim Chevalier 已提交
1817
                case (ty::ty_chan(?it)) { }
1818
                case (_) {
1819 1820 1821 1822
                    auto s = #fmt("mismatched types: expected chan \
                                   but found %s",
                                  ty_to_str(fcx.ccx.tcx,
                                            lhs_t));
1823
                    fcx.ccx.tcx.sess.span_fatal(expr.span,s);
1824
                }
1825
            }
1826
            write::ty_only_fixup(fcx, id, chan_t);
1827
        }
1828
        case (ast::expr_recv(?lhs, ?rhs)) {
1829 1830 1831
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
            check_expr(fcx, lhs);
            check_expr(fcx, rhs);
1832
            auto item_t = expr_ty(fcx.ccx.tcx, rhs);
1833
            auto port_t = ty::mk_port(fcx.ccx.tcx, item_t);
1834
            demand::simple(fcx, expr.span, port_t, expr_ty(fcx.ccx.tcx, lhs));
1835
            write::ty_only_fixup(fcx, id, item_t);
1836
        }
1837
        case (ast::expr_if(?cond, ?thn, ?elsopt)) {
1838
            check_expr(fcx, cond);
1839 1840 1841
            demand::simple(fcx, cond.span,
                           ty::mk_bool(fcx.ccx.tcx),
                           expr_ty(fcx.ccx.tcx, cond));
1842
            check_then_else(fcx, thn, elsopt, id, expr.span);
1843
        }
1844
        case (ast::expr_for(?decl, ?seq, ?body)) {
1845
            check_expr(fcx, seq);
1846
            auto elt_ty;
1847 1848
            auto ety = expr_ty(fcx.ccx.tcx, seq);
            alt (structure_of(fcx, expr.span, ety)) {
1849
                case (ty::ty_vec(?vec_elt_ty)) { elt_ty = vec_elt_ty.ty; }
1850
                case (ty::ty_str) {
1851
                    elt_ty = ty::mk_mach(fcx.ccx.tcx, ast::ty_u8);
1852
                }
1853 1854
                case (ty::ty_ivec(?vec_elt_ty)) { elt_ty = vec_elt_ty.ty; }
                case (ty::ty_istr) {
1855
                    elt_ty = ty::mk_mach(fcx.ccx.tcx, ast::ty_u8);
1856
                }
1857
                case (_) {
1858
                    fcx.ccx.tcx.sess.span_fatal(expr.span,
1859 1860
                        "mismatched types: expected vector or string but " +
                        "found " + ty_to_str(fcx.ccx.tcx, ety));
1861 1862
                }
            }
1863
            check_for_or_for_each(fcx, decl, elt_ty, body, id);
1864
        }
1865
        case (ast::expr_for_each(?decl, ?seq, ?body)) {
1866
            check_expr(fcx, seq);
1867
            check_for_or_for_each(fcx, decl, expr_ty(fcx.ccx.tcx, seq), body,
1868
                                  id);
1869
        }
1870
        case (ast::expr_while(?cond, ?body)) {
1871 1872
            check_expr(fcx, cond);
            check_block(fcx, body);
1873 1874
            demand::simple(fcx, cond.span, ty::mk_bool(fcx.ccx.tcx),
                           expr_ty(fcx.ccx.tcx, cond));
1875
            auto typ = ty::mk_nil(fcx.ccx.tcx);
1876
            write::ty_only_fixup(fcx, id, typ);
1877
        }
1878
        case (ast::expr_do_while(?body, ?cond)) {
1879 1880 1881
            check_expr(fcx, cond);
            check_block(fcx, body);
            auto typ = block_ty(fcx.ccx.tcx, body);
1882
            write::ty_only_fixup(fcx, id, typ);
1883
        }
1884
        case (ast::expr_alt(?expr, ?arms)) {
1885
            check_expr(fcx, expr);
1886 1887
            // Typecheck the patterns first, so that we get types for all the
            // bindings.
1888

1889
            auto pattern_ty = ty::expr_ty(fcx.ccx.tcx, expr);
1890
            let vec[@ast::pat] pats = [];
1891
            for (ast::arm arm in arms) {
1892
                check_pat(fcx, arm.pat, pattern_ty);
1893
                pats += [arm.pat];
1894 1895 1896
            }
            // Now typecheck the blocks.

1897
            auto result_ty = next_ty_var(fcx);
1898
            for (ast::arm arm in arms) {
1899 1900
                check_block(fcx, arm.block);
                auto bty = block_ty(fcx.ccx.tcx, arm.block);
1901

1902
                // Failing alt arms don't need to have a matching type
1903
                if (!ty::type_is_bot(fcx.ccx.tcx, bty)) {
1904 1905
                    result_ty =
                        demand::simple(fcx, arm.block.span, result_ty, bty);
1906
                }
1907
            }
1908
            write::ty_only_fixup(fcx, id, result_ty);
1909
        }
1910
        case (ast::expr_fn(?f)) {
1911 1912 1913
            auto cx = @rec(tcx=fcx.ccx.tcx);
            auto convert =
                bind ast_ty_to_ty(cx.tcx, bind collect::getter(cx, _), _);
1914
            auto ty_of_arg = bind collect::ty_of_arg(cx, _);
1915 1916 1917
            auto fty =
                collect::ty_of_fn_decl(cx, convert, ty_of_arg, f.decl,
                                       f.proto, [], none)._1;
1918 1919
            write::ty_only_fixup(fcx, id, fty);
            check_fn(fcx.ccx, f.decl, f.proto, f.body, id);
1920
        }
1921
        case (ast::expr_block(?b)) {
1922
            check_block(fcx, b);
1923
            alt (b.node.expr) {
1924
                case (some(?expr)) {
1925
                    auto typ = expr_ty(fcx.ccx.tcx, expr);
1926
                    write::ty_only_fixup(fcx, id, typ);
1927
                }
1928
                case (none) {
1929
                    auto typ = ty::mk_nil(fcx.ccx.tcx);
1930
                    write::ty_only_fixup(fcx, id, typ);
1931 1932 1933
                }
            }
        }
1934
        case (ast::expr_bind(?f, ?args)) {
1935
            // Call the generic checker.
G
Graydon Hoare 已提交
1936

1937
            check_call_or_bind(fcx, expr.span, f, args, false);
1938
            // Pull the argument and return types out.
1939

B
Brian Anderson 已提交
1940
            auto proto_1;
1941
            let ty::arg[] arg_tys_1 = ~[];
B
Brian Anderson 已提交
1942
            auto rt_1;
1943
            auto fty = expr_ty(fcx.ccx.tcx, f);
1944
            auto t_1;
1945
            alt (structure_of(fcx, expr.span, fty)) {
1946
                case (ty::ty_fn(?proto, ?arg_tys, ?rt, ?cf, ?constrs)) {
1947 1948
                    proto_1 = proto;
                    rt_1 = rt;
1949 1950 1951 1952
                    // FIXME:
                    // probably need to munge the constrs to drop constraints
                    // for any bound args

1953 1954
                    // For each blank argument, add the type of that argument
                    // to the resulting function type.
1955

1956
                    auto i = 0u;
1957
                    while (i < vec::len[option::t[@ast::expr]](args)) {
1958
                        alt (args.(i)) {
1959
                            case (some(_)) {/* no-op */ }
1960
                            case (none) { arg_tys_1 += ~[arg_tys.(i)]; }
1961 1962
                        }
                        i += 1u;
G
Graydon Hoare 已提交
1963
                    }
1964 1965 1966
                    t_1 =
                        ty::mk_fn(fcx.ccx.tcx, proto_1, arg_tys_1, rt_1, cf,
                                  constrs);
G
Graydon Hoare 已提交
1967
                }
1968
                case (_) {
1969
                    log_err "LHS of bind expr didn't have a function type?!";
1970 1971
                    fail;
                }
G
Graydon Hoare 已提交
1972
            }
1973
            write::ty_only_fixup(fcx, id, t_1);
G
Graydon Hoare 已提交
1974
        }
1975
        case (ast::expr_call(?f, ?args)) {
1976 1977
            /* 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
1978
            inside a pure function, and need an environment mapping from
1979 1980
            function name onto purity-designation */

1981
            require_pure_call(fcx.ccx, fcx.purity, f, expr.span);
1982
            check_call(fcx, expr.span, f, args);
1983
            // Pull the return type out of the type of the function.
1984

1985
            auto rt_1;
1986
            auto fty = do_autoderef(fcx, expr.span,
1987
                                   ty::expr_ty(fcx.ccx.tcx, f));
1988
            alt (structure_of(fcx, expr.span, fty)) {
1989 1990
                case (ty::ty_fn(_, _, ?rt, _, _)) { rt_1 = rt; }
                case (ty::ty_native_fn(_, _, ?rt)) { rt_1 = rt; }
1991
                case (_) {
1992
                    log_err "LHS of call expr didn't have a function type?!";
1993 1994
                    fail;
                }
1995
            }
1996
            write::ty_only_fixup(fcx, id, rt_1);
1997
        }
1998
        case (ast::expr_self_method(?ident)) {
1999
            auto t = ty::mk_nil(fcx.ccx.tcx);
2000
            let ty::t this_obj_ty;
2001
            let option::t[obj_info] this_obj_info = get_obj_info(fcx.ccx);
L
Lindsey Kuper 已提交
2002
            alt (this_obj_info) {
2003 2004 2005
                case (
                     // If we're inside a current object, grab its type.
                     some(?obj_info)) {
L
Lindsey Kuper 已提交
2006 2007 2008 2009
                    // 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

2010 2011
                    this_obj_ty =
                        ty::lookup_item_type(fcx.ccx.tcx,
2012
                                             local_def(obj_info.this_obj))._1;
2013
                }
2014
                case (none) { fail; }
L
Lindsey Kuper 已提交
2015
            }
2016
            // Grab this method's type out of the current object type.
2017

2018
            alt (structure_of(fcx, expr.span, this_obj_ty)) {
2019 2020
                case (ty::ty_obj(?methods)) {
                    for (ty::method method in methods) {
2021
                        if (method.ident == ident) {
2022
                            t = ty::method_ty_to_fn_ty(fcx.ccx.tcx, method);
2023 2024 2025 2026 2027
                        }
                    }
                }
                case (_) { fail; }
            }
2028
            write::ty_only_fixup(fcx, id, t);
2029
            require_impure(fcx.ccx.tcx.sess, fcx.purity, expr.span);
2030
        }
2031
        case (ast::expr_spawn(_, _, ?f, ?args)) {
2032
            check_call(fcx, expr.span, f, args);
2033 2034 2035
            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);
2036 2037
            // FIXME: Other typechecks needed

2038
            auto typ = ty::mk_task(fcx.ccx.tcx);
2039
            write::ty_only_fixup(fcx, id, typ);
2040
        }
2041
        case (ast::expr_cast(?e, ?t)) {
2042 2043
            check_expr(fcx, e);
            auto t_1 = ast_ty_to_ty_crate(fcx.ccx, t);
2044
            // FIXME: there are more forms of cast to support, eventually.
2045 2046 2047

            if (!(type_is_scalar(fcx, expr.span, expr_ty(fcx.ccx.tcx, e)) &&
                      type_is_scalar(fcx, expr.span, t_1))) {
2048
                fcx.ccx.tcx.sess.span_fatal(expr.span,
2049 2050 2051 2052 2053
                                          "non-scalar cast: " +
                                              ty_to_str(fcx.ccx.tcx,
                                                        expr_ty(fcx.ccx.tcx,
                                                                e)) + " as " +
                                              ty_to_str(fcx.ccx.tcx, t_1));
2054
            }
2055
            write::ty_only_fixup(fcx, id, t_1);
2056
        }
2057
        case (ast::expr_vec(?args, ?mut, ?kind)) {
2058
            let ty::t t;
2059
            if (vec::len[@ast::expr](args) == 0u) {
2060
                t = next_ty_var(fcx);
G
Graydon Hoare 已提交
2061
            } else {
2062 2063
                check_expr(fcx, args.(0));
                t = expr_ty(fcx.ccx.tcx, args.(0));
G
Graydon Hoare 已提交
2064
            }
2065
            for (@ast::expr e in args) {
2066 2067 2068
                check_expr(fcx, e);
                auto expr_t = expr_ty(fcx.ccx.tcx, e);
                demand::simple(fcx, expr.span, t, expr_t);
G
Graydon Hoare 已提交
2069
            }
2070 2071 2072 2073 2074 2075 2076 2077 2078
            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));
                }
            }
2079
            write::ty_only_fixup(fcx, id, typ);
G
Graydon Hoare 已提交
2080
        }
2081
        case (ast::expr_tup(?elts)) {
2082 2083
            let ty::mt[] elts_mt = ~[];
            ivec::reserve(elts_mt, vec::len(elts));
2084
            for (ast::elt e in elts) {
2085 2086
                check_expr(fcx, e.expr);
                auto ety = expr_ty(fcx.ccx.tcx, e.expr);
2087
                elts_mt += ~[rec(ty=ety, mut=e.mut)];
G
Graydon Hoare 已提交
2088
            }
2089
            auto typ = ty::mk_tup(fcx.ccx.tcx, elts_mt);
2090
            write::ty_only_fixup(fcx, id, typ);
G
Graydon Hoare 已提交
2091
        }
2092
        case (ast::expr_rec(?fields, ?base)) {
2093
            alt (base) {
2094
                case (none) {/* no-op */ }
2095
                case (some(?b_0)) { check_expr(fcx, b_0); }
2096
            }
2097
            let field[] fields_t = ~[];
2098
            for (ast::field f in fields) {
2099 2100
                check_expr(fcx, f.node.expr);
                auto expr_t = expr_ty(fcx.ccx.tcx, f.node.expr);
2101
                auto expr_mt = rec(ty=expr_t, mut=f.node.mut);
2102
                fields_t += ~[rec(ident=f.node.ident, mt=expr_mt)];
2103
            }
G
Graydon Hoare 已提交
2104
            alt (base) {
2105
                case (none) {
2106
                    auto typ = ty::mk_rec(fcx.ccx.tcx, fields_t);
2107
                    write::ty_only_fixup(fcx, id, typ);
G
Graydon Hoare 已提交
2108
                }
2109
                case (some(?bexpr)) {
2110 2111
                    check_expr(fcx, bexpr);
                    auto bexpr_t = expr_ty(fcx.ccx.tcx, bexpr);
2112
                    let field[] base_fields = ~[];
2113
                    alt (structure_of(fcx, expr.span, bexpr_t)) {
2114
                        case (ty::ty_rec(?flds)) { base_fields = flds; }
G
Graydon Hoare 已提交
2115
                        case (_) {
2116
                            fcx.ccx.tcx.sess.span_fatal(expr.span,
2117 2118
                                                      "record update \
                                                       non-record base");
G
Graydon Hoare 已提交
2119 2120
                        }
                    }
2121
                    write::ty_only_fixup(fcx, id, bexpr_t);
2122
                    for (ty::field f in fields_t) {
G
Graydon Hoare 已提交
2123
                        auto found = false;
2124
                        for (ty::field bf in base_fields) {
2125
                            if (str::eq(f.ident, bf.ident)) {
2126 2127
                                demand::simple(fcx, expr.span, bf.mt.ty,
                                               f.mt.ty);
G
Graydon Hoare 已提交
2128 2129 2130 2131
                                found = true;
                            }
                        }
                        if (!found) {
2132
                            fcx.ccx.tcx.sess.span_fatal(expr.span,
2133 2134 2135
                                                      "unknown field in \
                                                       record update: "
                                                      + f.ident);
G
Graydon Hoare 已提交
2136 2137 2138 2139
                        }
                    }
                }
            }
2140
        }
2141
        case (ast::expr_field(?base, ?field)) {
2142 2143
            check_expr(fcx, base);
            auto base_t = expr_ty(fcx.ccx.tcx, base);
2144
            base_t = do_autoderef(fcx, expr.span, base_t);
2145
            alt (structure_of(fcx, expr.span, base_t)) {
2146
                case (ty::ty_tup(?args)) {
2147 2148
                    let uint ix =
                        ty::field_num(fcx.ccx.tcx.sess, expr.span, field);
2149
                    if (ix >= ivec::len[ty::mt](args)) {
2150
                        fcx.ccx.tcx.sess.span_fatal(expr.span,
2151
                                                  "bad index on tuple");
G
Graydon Hoare 已提交
2152
                    }
2153
                    write::ty_only_fixup(fcx, id, args.(ix).ty);
G
Graydon Hoare 已提交
2154
                }
2155
                case (ty::ty_rec(?fields)) {
2156 2157 2158
                    let uint ix =
                        ty::field_idx(fcx.ccx.tcx.sess, expr.span, field,
                                      fields);
2159
                    if (ix >= ivec::len[ty::field](fields)) {
2160
                        fcx.ccx.tcx.sess.span_fatal(expr.span,
2161
                                                  "bad index on record");
2162
                    }
2163
                    write::ty_only_fixup(fcx, id, fields.(ix).mt.ty);
2164
                }
2165
                case (ty::ty_obj(?methods)) {
2166
                    // log_err "checking method_idx 1...";
2167 2168 2169
                    let uint ix =
                        ty::method_idx(fcx.ccx.tcx.sess, expr.span, field,
                                       methods);
2170
                    if (ix >= ivec::len[ty::method](methods)) {
2171
                        fcx.ccx.tcx.sess.span_fatal(expr.span,
2172
                                                  "bad index on obj");
G
Graydon Hoare 已提交
2173 2174
                    }
                    auto meth = methods.(ix);
2175 2176 2177
                    auto t =
                        ty::mk_fn(fcx.ccx.tcx, meth.proto, meth.inputs,
                                  meth.output, meth.cf, meth.constrs);
2178
                    write::ty_only_fixup(fcx, id, t);
G
Graydon Hoare 已提交
2179
                }
G
Graydon Hoare 已提交
2180
                case (_) {
2181 2182 2183 2184
                    auto t_err = resolve_type_vars_if_possible(fcx, base_t);
                    auto msg = #fmt("attempted field access on type %s",
                                    ty_to_str(fcx.ccx.tcx, t_err));
                    fcx.ccx.tcx.sess.span_fatal(expr.span, msg);
G
Graydon Hoare 已提交
2185 2186 2187
                }
            }
        }
2188
        case (ast::expr_index(?base, ?idx)) {
2189 2190
            check_expr(fcx, base);
            auto base_t = expr_ty(fcx.ccx.tcx, base);
2191
            base_t = do_autoderef(fcx, expr.span, base_t);
2192 2193
            check_expr(fcx, idx);
            auto idx_t = expr_ty(fcx.ccx.tcx, idx);
2194
            if (!type_is_integral(fcx, idx.span, idx_t)) {
2195
                fcx.ccx.tcx.sess.span_fatal(idx.span,
2196 2197 2198
                                          "mismatched types: expected \
                                           integer but found "
                                          + ty_to_str(fcx.ccx.tcx, idx_t));
2199
            }
2200
            alt (structure_of(fcx, expr.span, base_t)) {
2201
                case (ty::ty_vec(?mt)) {
2202
                    write::ty_only_fixup(fcx, id, mt.ty);
2203 2204
                }
                case (ty::ty_ivec(?mt)) {
2205
                    write::ty_only_fixup(fcx, id, mt.ty);
G
Graydon Hoare 已提交
2206
                }
2207
                case (ty::ty_str) {
2208
                    auto typ = ty::mk_mach(fcx.ccx.tcx, ast::ty_u8);
2209
                    write::ty_only_fixup(fcx, id, typ);
2210 2211
                }
                case (ty::ty_istr) {
2212
                    auto typ = ty::mk_mach(fcx.ccx.tcx, ast::ty_u8);
2213
                    write::ty_only_fixup(fcx, id, typ);
G
Graydon Hoare 已提交
2214 2215
                }
                case (_) {
2216
                    fcx.ccx.tcx.sess.span_fatal(expr.span,
2217 2218 2219
                                              "vector-indexing bad type: " +
                                                  ty_to_str(fcx.ccx.tcx,
                                                            base_t));
G
Graydon Hoare 已提交
2220 2221 2222
                }
            }
        }
2223
        case (ast::expr_port(?typ)) {
2224
            auto t = next_ty_var(fcx);
2225 2226 2227 2228 2229 2230 2231 2232
            alt(typ) {
                case (some(?_t)) {
                    demand::simple(fcx, expr.span, 
                                   ast_ty_to_ty_crate(fcx.ccx, _t), 
                                   t);
                }
                case (none) {}
            }
2233
            auto pt = ty::mk_port(fcx.ccx.tcx, t);
2234
            write::ty_only_fixup(fcx, id, pt);
2235
        }
2236
        case (ast::expr_chan(?x)) {
2237 2238
            check_expr(fcx, x);
            auto port_t = expr_ty(fcx.ccx.tcx, x);
2239
            alt (structure_of(fcx, expr.span, port_t)) {
2240
                case (ty::ty_port(?subtype)) {
2241
                    auto ct = ty::mk_chan(fcx.ccx.tcx, subtype);
2242
                    write::ty_only_fixup(fcx, id, ct);
2243 2244
                }
                case (_) {
2245
                    fcx.ccx.tcx.sess.span_fatal(expr.span,
2246 2247 2248
                                              "bad port type: " +
                                                  ty_to_str(fcx.ccx.tcx,
                                                            port_t));
2249 2250 2251
                }
            }
        }
L
Lindsey Kuper 已提交
2252
        case (ast::expr_anon_obj(?anon_obj, ?tps)) {
L
Lindsey Kuper 已提交
2253 2254 2255 2256
            // 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.
2257

2258
            let vec[ast::anon_obj_field] fields = [];
L
Lindsey Kuper 已提交
2259
            alt (anon_obj.fields) {
2260 2261
                case (none) { }
                case (some(?v)) { fields = v; }
L
Lindsey Kuper 已提交
2262
            }
2263 2264 2265 2266 2267 2268 2269 2270

            // FIXME: this is duplicated between here and trans -- it should
            // appear in one place
            fn anon_obj_field_to_obj_field(&ast::anon_obj_field f) 
                -> ast::obj_field {
                ret rec(mut=f.mut, ty=f.ty, ident=f.ident, id=f.id);
            }

2271
            vec::push[obj_info](fcx.ccx.obj_infos,
2272 2273 2274
                                rec(obj_fields=
                                    vec::map(anon_obj_field_to_obj_field, 
                                             fields),
L
Lindsey Kuper 已提交
2275
                                    this_obj=id));
2276

L
Lindsey Kuper 已提交
2277 2278 2279 2280 2281 2282 2283 2284
            // 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, _);
2285 2286 2287 2288 2289 2290

                auto inputs = ~[];
                for (ast::arg aa in m.node.meth.decl.inputs) {
                    inputs += ~[ty_of_arg(ccx, aa)];
                }

L
Lindsey Kuper 已提交
2291
                auto output = convert(m.node.meth.decl.output);
2292 2293 2294 2295 2296 2297

                auto out_constrs = ~[];
                for (@ast::constr constr in m.node.meth.decl.constraints) {
                    out_constrs += ~[ast_constr_to_constr(ccx.tcx, constr)];
                }

2298 2299 2300
                ret rec(proto=m.node.meth.proto, ident=m.node.ident,
                        inputs=inputs, output=output, cf=m.node.meth.decl.cf,
                        constrs=out_constrs);
L
Lindsey Kuper 已提交
2301
            }
2302
            fn get_anon_obj_method_types(@fn_ctxt fcx,
2303 2304
                                         &ast::anon_obj anon_obj)
                -> ty::method[] {
2305

2306
                let ty::method[] methods = ~[];
2307 2308

                // Outer methods.
2309 2310 2311
                for (@ast::method m in anon_obj.methods) {
                    methods += ~[ty_of_method(fcx.ccx, m)];
                }
2312 2313 2314 2315 2316

                // Inner methods.

                // Typecheck 'with_obj'.  If it exists, it had better have
                // object type.
2317
                let ty::method[] with_obj_methods = ~[];
2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340
                alt (anon_obj.with_obj) {
                    case (none) { }
                    case (some(?e)) {
                        check_expr(fcx, e);
                        auto with_obj_ty = expr_ty(fcx.ccx.tcx, e);

                        alt (structure_of(fcx, e.span, with_obj_ty)) {
                            case (ty::ty_obj(?ms)) {
                                with_obj_methods = ms;
                            }
                            case (_) {
                                // The user is trying to extend a non-object.
                                fcx.ccx.tcx.sess.span_fatal(
                                    e.span,
                                    syntax::print::pprust::expr_to_str(e) + 
                                    " does not have object type");
                            }
                        }
                    }
                }
                methods += with_obj_methods;

                ret methods;
L
Lindsey Kuper 已提交
2341
            }
2342 2343

            auto method_types = get_anon_obj_method_types(fcx, anon_obj);
2344
            auto ot = ty::mk_obj(fcx.ccx.tcx, ty::sort_methods(method_types));
2345

2346
            write::ty_only_fixup(fcx, id, ot);
2347 2348
            // Write the methods into the node type table.  (This happens in
            // collect::convert for regular objects.)
2349

2350 2351
            auto i = 0u;
            while (i < vec::len[@ast::method](anon_obj.methods)) {
2352
                write::ty_only(fcx.ccx.tcx, anon_obj.methods.(i).node.id,
2353 2354 2355 2356 2357
                               ty::method_ty_to_fn_ty(fcx.ccx.tcx,
                                                      method_types.(i)));
                i += 1u;
            }
            // Typecheck the methods.
2358

2359 2360 2361
            for (@ast::method method in anon_obj.methods) {
                check_method(fcx.ccx, method);
            }
T
Tim Chevalier 已提交
2362
            next_ty_var(fcx);
L
Lindsey Kuper 已提交
2363
            // Now remove the info from the stack.
2364

2365
            vec::pop[obj_info](fcx.ccx.obj_infos);
L
Lindsey Kuper 已提交
2366
        }
2367
        case (_) {
2368
            fcx.ccx.tcx.sess.unimpl("expr type in typeck::check_expr");
2369
        }
2370 2371 2372
    }
}

2373 2374 2375 2376 2377 2378 2379 2380
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));
2381 2382
}

2383 2384 2385 2386
fn get_obj_info(&@crate_ctxt ccx) -> option::t[obj_info] {
    ret vec::last[obj_info](ccx.obj_infos);
}

2387 2388
fn ast_constr_to_constr(ty::ctxt tcx, &@ast::constr c)
    -> @ty::constr_def {
2389
    alt (tcx.def_map.find(c.node.id)) {
2390
        case (some(ast::def_fn(?pred_id, ast::pure_fn))) {
2391 2392 2393 2394 2395 2396 2397
            // FIXME: Remove this vec->ivec conversion.
            let (@ast::constr_arg_general[uint])[] cag_ivec = ~[];
            for (@ast::constr_arg_general[uint] cag in c.node.args) {
                cag_ivec += ~[cag];
            }

            ret @respan(c.span, rec(path=c.node.path, args=cag_ivec,
2398 2399 2400
                                    id=pred_id));
        }
        case (_) {
2401
            tcx.sess.span_fatal(c.span, "Predicate "
2402
                              + path_to_str(c.node.path)
2403 2404
                              + " is unbound or bound to a non-function or an\
                                impure function");
2405 2406 2407 2408
        }
    }
}

2409
fn check_decl_initializer(&@fn_ctxt fcx, ast::node_id nid,
2410
                          &ast::initializer init) {
2411
    check_expr(fcx, init.expr);
2412 2413
    auto lty = ty::mk_var(fcx.ccx.tcx,
                          lookup_local(fcx, init.expr.span, nid));
2414 2415
    alt (init.op) {
        case (ast::init_assign) {
2416 2417
            demand::simple(fcx, init.expr.span, lty,
                           expr_ty(fcx.ccx.tcx, init.expr));
2418
        }
2419
        case (ast::init_move) {
2420 2421
            demand::simple(fcx, init.expr.span, lty,
                           expr_ty(fcx.ccx.tcx, init.expr));
2422
        }
2423
        case (ast::init_recv) {
2424
            auto port_ty = ty::mk_port(fcx.ccx.tcx, lty);
2425 2426
            demand::simple(fcx, init.expr.span, port_ty,
                           expr_ty(fcx.ccx.tcx, init.expr));
2427 2428 2429 2430
        }
    }
}

P
Paul Stansifer 已提交
2431
fn check_decl_local(&@fn_ctxt fcx, &@ast::local local) -> @ast::local {
2432 2433
    auto a_id = local.node.id;
    alt (fcx.locals.find(a_id)) {
2434
        case (none) {
P
Paul Stansifer 已提交
2435

2436
            fcx.ccx.tcx.sess.bug("check_decl_local: local id not found " +
P
Paul Stansifer 已提交
2437
                                     local.node.ident);
2438 2439 2440
        }
        case (some(?i)) {
            auto t = ty::mk_var(fcx.ccx.tcx, i);
2441
            write::ty_only_fixup(fcx, a_id, t);
P
Paul Stansifer 已提交
2442 2443
            auto initopt = local.node.init;
            alt (initopt) {
2444
                case (some(?init)) {
P
Paul Stansifer 已提交
2445
                    check_decl_initializer(fcx, local.node.id, init);
2446
                }
2447
                case (_) {/* fall through */ }
2448
            }
2449
            auto newlocal = rec(init=initopt with local.node);
P
Paul Stansifer 已提交
2450
            ret @rec(node=newlocal, span=local.span);
2451 2452 2453 2454
        }
    }
}

2455 2456
fn check_stmt(&@fn_ctxt fcx, &@ast::stmt stmt) {
    auto node_id;
2457
    alt (stmt.node) {
2458 2459
        case (ast::stmt_decl(?decl, ?id)) {
            node_id = id;
2460
            alt (decl.node) {
2461
                case (ast::decl_local(?l)) { check_decl_local(fcx, l); }
2462
                case (ast::decl_item(_)) {/* ignore for now */ }
2463 2464
            }
        }
2465 2466
        case (ast::stmt_expr(?expr, ?id)) {
            node_id = id;
2467
            check_expr(fcx, expr);
2468 2469
        }
    }
2470
    write::nil_ty(fcx.ccx.tcx, node_id);
2471 2472
}

2473 2474
fn check_block(&@fn_ctxt fcx, &ast::block block) {
    for (@ast::stmt s in block.node.stmts) { check_stmt(fcx, s); }
2475
    alt (block.node.expr) {
2476
        case (none) { write::nil_ty(fcx.ccx.tcx, block.node.id); }
2477
        case (some(?e)) {
2478 2479
            check_expr(fcx, e);
            auto ety = expr_ty(fcx.ccx.tcx, e);
2480
            write::ty_only_fixup(fcx, block.node.id, ety);
2481 2482
        }
    }
2483 2484
}

2485
fn check_const(&@crate_ctxt ccx, &span sp, &@ast::expr e, &ast::node_id id) {
2486 2487
    // FIXME: this is kinda a kludge; we manufacture a fake function context
    // and statement context for checking the initializer expression.
2488

2489 2490
    auto rty = node_id_to_type(ccx.tcx, id);
    let vec[ast::node_id] fixups = [];
2491 2492 2493 2494
    let @fn_ctxt fcx =
        @rec(ret_ty=rty,
             purity=ast::pure_fn,
             var_bindings=ty::unify::mk_var_bindings(),
2495 2496
             locals=new_int_hash[int](),
             local_names=new_int_hash[ast::ident](),
2497 2498 2499
             mutable next_var_id=0,
             mutable fixups=fixups,
             ccx=ccx);
2500
    check_expr(fcx, e);
2501 2502
}

2503
fn check_fn(&@crate_ctxt ccx, &ast::fn_decl decl, ast::proto proto,
2504 2505 2506
            &ast::block body, &ast::node_id id) {
    auto gather_result = gather_locals(ccx, decl, body, id);
    let vec[ast::node_id] fixups = [];
2507 2508 2509 2510 2511 2512 2513 2514 2515
    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);
2516

2517
    check_block(fcx, body);
2518
    alt (decl.purity) {
2519
        case (ast::pure_fn) {
2520

2521 2522
            // per the previous comment, this just checks that the declared
            // type is bool, and trusts that that's the actual return type.
2523
            if (!ty::type_is_bool(ccx.tcx, fcx.ret_ty)) {
2524
                ccx.tcx.sess.span_fatal(body.span,
2525
                                      "Non-boolean return type in pred");
2526 2527
            }
        }
2528
        case (_) { }
2529
    }
2530

2531
    auto success = writeback::resolve_type_vars_in_block(fcx, body);
2532

2533
    if (success && option::is_some(body.node.expr)) {
2534 2535 2536 2537 2538 2539 2540 2541 2542
        auto tail_expr = option::get(body.node.expr);
        auto tail_expr_ty = expr_ty(ccx.tcx, tail_expr);
        // Have to exclude ty_nil to allow functions to end in
        // while expressions, etc.
        if (!ty::type_is_nil(ccx.tcx, tail_expr_ty)) {
            demand::simple(fcx, tail_expr.span,
                           fcx.ret_ty, tail_expr_ty);
        }
    }
2543
}
2544

2545
fn check_method(&@crate_ctxt ccx, &@ast::method method) {
2546
    auto m = method.node.meth;
2547
    check_fn(ccx, m.decl, m.proto, m.body, method.node.id);
2548 2549
}

2550 2551
fn check_item(@crate_ctxt ccx, &@ast::item it) {
    alt (it.node) {
2552
        case (ast::item_const(_, ?e)) {
2553
            check_const(ccx, it.span, e, it.id);
2554
        }
2555
        case (ast::item_fn(?f, _)) {
2556
            check_fn(ccx, f.decl, f.proto, f.body, it.id);
2557
        }
2558 2559 2560
        case (ast::item_res(?f, ?dtor_id, _, _)) {
            check_fn(ccx, f.decl, f.proto, f.body, dtor_id);
        }
2561
        case (ast::item_obj(?ob, _, _)) {
2562
            // We're entering an object, so gather up the info we need.
2563

2564
            vec::push[obj_info](ccx.obj_infos,
2565
                                rec(obj_fields=ob.fields, this_obj=it.id));
2566
            // Typecheck the methods.
2567

2568 2569 2570 2571 2572
            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.
2573

2574
            vec::pop[obj_info](ccx.obj_infos);
2575
        }
2576
        case (_) {/* nothing to do */ }
2577 2578 2579
    }
}

2580
fn check_crate(&ty::ctxt tcx, &@ast::crate crate) {
2581
    collect::collect_item_types(tcx, crate);
2582
    let vec[obj_info] obj_infos = [];
2583

2584
    auto ccx =
2585
        @rec(mutable obj_infos=obj_infos, tcx=tcx);
2586 2587 2588
    auto visit =
        rec(visit_item_pre=bind check_item(ccx, _)
            with walk::default_visitor());
2589
    walk::walk_crate(visit, *crate);
2590
    tcx.sess.abort_if_errors();
2591
}
2592 2593 2594 2595 2596 2597 2598
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
2599
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
2600 2601
// End:
//